/*
* $Id:  $
*
* Description  : Sound source node data container.
* Author       : Jiri Bittner
* 
* Purpose      :
* Sound source node data container - mainly based on OpenAL sound source
* possibilities. All the sound API dependent data are stored within the sound renderer, not
* in the scene graph.
*/


#ifndef __SOUNDSOURCENODE__H__
#define __SOUNDSOURCENODE__H__

#include "scenenode.h"

namespace VRUT
{
	///\c SceneNode with sound source definition
	class SoundSourceNode : public SceneNode {
		friend class Scene;

	public:
		static const SCENENODE_TYPE ClassType = SOUND_SOURCE;

		enum SoundSourceState
		{
			PLAY=0,
			PLAY_ONCE,
			PAUSE,
			STOP,
			REWIND,
			NONE
		};

		///Class constructor
		SoundSourceNode(const wxString & _name) : SceneNode(_name, ClassType),
			gain(1.0f), looping(false), state(PLAY), minGain(0.0f), maxGain(1.0f), referenceDistance(1.0f), rollOffFactor(1.0f), maxDistance(FLT_MAX),
			pitch(1.0f), direction(0.0f,0.0f,0.0f), coneInnerAngle(360.0f), coneOuterAngle(360.0f), coneOuterGain(0.0f), secOffset(0.0f), dataSource()
		{
		}

		///Copy constructor
		SoundSourceNode(const SoundSourceNode &n) : SceneNode(n),
			gain(n.gain), looping(n.looping), state(n.state), minGain(n.minGain), maxGain(n.maxGain), referenceDistance(n.referenceDistance),
			rollOffFactor(n.rollOffFactor), maxDistance(n.maxDistance), pitch(n.pitch), direction(n.direction), coneInnerAngle(n.coneInnerAngle), coneOuterAngle(n.coneOuterAngle),
			coneOuterGain(n.coneOuterGain), secOffset(n.secOffset), dataSource(CloneWxString(n.dataSource))
		{
		}

		///Class destructor
		virtual ~SoundSourceNode()
		{
		}

		///Get string with node's properties - \c SceneNode overload
		virtual wxString ToString() const
		{
			return SceneNode::ToString() + wxT("\nGain ") + TextWriter::WriteToWxString(gain) +
				wxString::Format(wxT("\nLooping %i\nPitch "), looping) + TextWriter::WriteToWxString(pitch) + wxT("\ndataSource ") + dataSource + wxT("\n");
		}

		///Get copy of instance - \c SceneNode overload
		virtual SceneNode * Clone() const
		{
			return new SoundSourceNode(*this);
		}

		/** AL_POSITION specifies the current location of the object in the world coordinate
		system. Any 3-tuple of valid float values is allowed. Implementation behavior on
		encountering NaN and infinity is not defined. The object position is always defined in the
		world coordinate system. We will use position from transformation matrix.*/

		/** AL_GAIN defines a scalar amplitude multiplier. As a source
		attribute, it applies to that particular source only. As a
		listener attribute, it effectively applies to all sources in the
		current context. The default 1.0 means that the sound is
		unattenuated. An AL_GAIN value of 0.5 is equivalent to an
		attenuation of 6 dB. The value zero equals silence (no
		contribution to the output mix). Driver implementations are free
		to optimize this case and skip mixing and processing stages
		where applicable. The implementation is in charge of ensuring
		artifact-free (click-free) changes of gain values and is free to
		defer actual modification of the sound samples, within the
		limits of acceptable latencies.  AL_GAIN larger than one
		(i.e. amplification) is permitted for source and listener.
		However, the implementation is free to clamp the total gain
		(effective gain per-source multiplied by the listener gain) to
		one to prevent overflow. */
		float gain;

		/** AL_LOOPING is a flag that indicates that the source will not be
		in AL_STOPPED state once it reaches the end of last buffer in
		the buffer queue. Instead, the source will immediately promote
		to AL_INITIAL and AL_PLAYING. The default value is
		AL_FALSE. AL_LOOPING can be changed on a source in any execution
		state. In particular, it can be changed on a AL_PLAYING
		source. */
		bool looping;

		SoundSourceState state;

		/** AL_MIN_GAIN is a scalar amplitude threshold. It indicates the
		minimal AL_GAIN that is always guaranteed for this source. At the end
		of the processing of various attenuation factors such as distance
		based attenuation and source AL_GAIN, the effective gain calculated is
		compared to this value. If the effective gain is lower than
		AL_MIN_GAIN, AL_MIN_GAIN is applied. This happens before the listener
		gain is applied. If a zero AL_MIN_GAIN is set, then the effective gain
		will not be corrected. */
		float minGain;

		/** AL_MAX_GAIN defines a scalar amplitude threshold. It indicates
		the maximal AL_GAIN permitted for this source. At the end of the
		processing of various attenuation factors such as distance based
		attenuation and source AL_GAIN, the effective gain calculated is
		compared to this value. If the effective gain is higher than
		AL_MAX_GAIN, AL_MAX_GAIN is applied. This happens before the
		listener AL_GAIN is applied. If the listener gain times
		AL_MAX_GAIN still exceeds the maximum gain the implementation
		can handle, the implementation is free to clamp. If a zero
		AL_MAX_GAIN is set, then the source is effectively muted. The
		implementation is free to optimize for this situation, but no
		optimization is required or recommended as setting GAIN to zero
		is the proper way to mute a source.*/
		float maxGain;

		/** This is used for distance attenuation calculations based on
		inverse distance with rolloff.  Depending on the distance model it
		will also act as a distance threshold below which gain is clamped. See
		the section on distance models for details. */

		float referenceDistance;

		/**  This is used for distance attenuation calculations based on inverse
		distance with rolloff.  For distances smaller than AL_MAX_DISTANCE
		(and, depending on the distance model, larger than
		AL_REFERENCE_DISTANCE), this will scale the distance attenuation over
		the applicable range. See section on distance models for details how
		the attenuation is computed as a function of the distance.  In
		particular, AL_ROLLOFF_FACTOR can be set to zero for those sources
		that are supposed to be exempt from distance attenuation. The
		implementation is encouraged to optimize this case, bypassing distance
		attenuation calculation entirely on a per-source basis. */
		float rollOffFactor;

		/**  This is used for distance attenuation calculations based on inverse
		distance with rolloff, if the Inverse Clamped Distance Model is
		used. In this case, distances greater than AL_MAX_DISTANCE will be
		clamped to AL_MAX_DISTANCE.  AL_MAX_DISTANCE based clamping is applied
		before AL_MIN_GAIN clamping, so if the effective gain at
		AL_MAX_DISTANCE is larger than AL_MIN_GAIN, AL_MIN_GAIN will have no
		effect. No culling is supported. */
		float maxDistance;

		/** Desired pitch shift, where 1.0 equals identity. Each reduction by 50
		percent equals a pitch shift of -12 semitones (one octave
		reduction). Each doubling equals a pitch shift of 12 semitones (one
		octave increase). Zero is not a legal value. Implementations may clamp
		the actual output pitch range to any values subject to the
		implementation's own limits. */
		float pitch;

		/** If AL_DIRECTION does not equal the zero vector, the source is
		directional. The sound emission is presumed to be symmetric
		around the direction vector (cylinder symmetry).  sources are
		not oriented in full 3 degrees of freedom, only two angles are
		effectively needed.  The zero vector is default, indicating that
		a source is not directional. Specifying a nonzero vector will
		make the source directional. Specifying a zero vector for a
		directional source will effectively mark it as non-directional. */
		Vector3 direction;

		/** Inside angle of the sound cone, in degrees. The default
		of 360 means that the inner angle covers the entire world, which is
		equivalent to an omni-directional source.  */
		float coneInnerAngle;

		/** Outer angle of the sound cone, in degrees. The default of 360 means that the
		outer angle covers the entire world. If the inner angle is also 360, then the
		zone for angle dependent attenuation is zero. */
		float coneOuterAngle;

		/** Description: the factor with which AL_GAIN is multiplied to determine the effective gain
		outside the cone defined by the outer angle. The effective gain applied outside the outer
		cone is AL_GAIN times AL_CONE_OUTER_GAIN. Changing AL_GAIN affects all
		directions, i.e. the source is attenuated in all directions, for any position of the listener.
		The application has to change AL_CONE_OUTER_GAIN as well if a different behavior
		is desired. */
		float coneOuterGain;

		/** The playback position, expressed in seconds (the value will loop back to zero
		for looping sources). */
		float secOffset;

		/** Path to the file storing the sound. If supported by the renderer
		dynamically generated procedural sounds can be generated by storing
		a script instead of the filename (this feature is not supported
		yet). */
		wxString dataSource;
	};
}

#endif
