Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / sound / driver / dsound / source_dsound.h
blob1aa2d56252405e848c425e2ba06159b1dbb793ca
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef NL_SOURCE_DSOUND_H
18 #define NL_SOURCE_DSOUND_H
20 #include "nel/sound/driver/source.h"
21 #include "nel/sound/driver/sound_driver.h"
22 #include "nel/sound/driver/buffer.h"
24 namespace NLSOUND {
26 class CBufferDSound;
28 /** Keep trace of following states of the DirectSound buffer:
29 * - the buffer is being filled with samples (filling),
30 * - the buffer still contains samples but silence is being written (silencing),
31 * - the buffer contains no samples but only silence (silenced)
33 /*enum TSourceDSoundBufferState
35 /// The buffer is being filled with samples (filling),
36 NL_DSOUND_FILLING,
37 /// The buffer still contains samples but silence is being written (silencing),
38 NL_DSOUND_SILENCING,
39 /// The buffer contains no samples but only silence (silenced)
40 NL_DSOUND_SILENCED
41 } ;
44 /** The state of the source as experienced by the user: playing, paused, and stopped. */
46 enum TSourceDSoundUserState
48 /// The buffer is playing.
49 NL_DSOUND_PLAYING,
50 /// The buffer is paused.
51 NL_DSOUND_PAUSED,
52 /// The buffer is stopped.
53 NL_DSOUND_STOPPED
57 /** To figger out whether the sound device has played all the samples in the buffer,
58 * the position of the play cursor is traced relatively to the position of the last
59 * sample in the buffer.
62 enum TSourceDSoundEndState
64 NL_DSOUND_TAIL1,
65 NL_DSOUND_TAIL2,
66 NL_DSOUND_ENDED
70 /**
71 * DirectSound sound source
74 * For arguments as 3D vectors, use the NeL vector coordinate system
76 * \author Peter Hanappe
77 * \author Nevrax France
78 * \date 2002
80 class CSourceDSound : public ISource
82 friend class CSoundDriverDSound;
84 public:
85 /// Constructor
86 CSourceDSound(uint sourcename = 0);
87 /// Destructor
88 virtual ~CSourceDSound();
90 /// Initialize the DirectSound buffers. Called by the sound driver only.
91 void init(LPDIRECTSOUND directSound, bool useEax);
93 /// \name Initialization
94 //@{
95 /// Enable or disable streaming mode. Source must be stopped to call this.
96 virtual void setStreaming(bool streaming);
97 /** Set the buffer that will be played (no streaming)
98 * If the buffer is stereo, the source mode becomes stereo and the source relative mode is on,
99 * otherwise the source is considered as a 3D source. Use submitStreamingBuffer for streaming.
101 virtual void setStaticBuffer(IBuffer *buffer);
102 /// Return the buffer, or NULL if streaming is used. Not available for streaming.
103 virtual IBuffer *getStaticBuffer();
104 /// Add a buffer to the streaming queue. A buffer of 100ms length is optimal for streaming.
105 /// Should be called by a thread which checks countStreamingBuffers every 100ms.
106 virtual void submitStreamingBuffer(IBuffer *buffer);
107 /// Return the amount of buffers in the queue (playing and waiting). 3 buffers is optimal.
108 virtual uint countStreamingBuffers() const;
109 //@}
111 /// \name Playback control
112 //@{
113 /// Set looping on/off for future playbacks (default: off), not available for streaming
114 virtual void setLooping(bool l);
115 /// Return the looping state
116 virtual bool getLooping() const;
118 /** Play the static buffer (or stream in and play).
119 * This method can return false if the sample for this sound is unloaded.
121 virtual bool play();
122 /// Stop playing
123 virtual void stop();
124 /// Pause. Call play() to resume.
125 virtual void pause();
126 /// Return true if play() or pause(), false if stop().
127 virtual bool isPlaying() const;
128 /// Return true if playing is finished or stop() has been called.
129 virtual bool isStopped() const;
130 /// Return true if the playing source is paused
131 virtual bool isPaused() const;
132 /// Returns the number of milliseconds the source has been playing
133 virtual uint32 getTime();
134 //@}
136 /// \name Source properties
137 //@{
138 /** Set the position vector (default: (0,0,0)).
139 * 3D mode -> 3D position
140 * st mode -> x is the pan value (from left (-1) to right (1)), set y and z to 0
142 virtual void setPos(const NLMISC::CVector& pos, bool deffered = true);
143 /** Get the position vector.
144 * See setPos() for details.
146 virtual const NLMISC::CVector &getPos() const;
147 /// Set the velocity vector (3D mode only, ignored in stereo mode) (default: (0,0,0))
148 virtual void setVelocity(const NLMISC::CVector& vel, bool deferred = true);
149 /// Get the velocity vector
150 virtual void getVelocity(NLMISC::CVector& vel) const;
151 /// Set the direction vector (3D mode only, ignored in stereo mode) (default: (0,0,0) as non-directional)
152 virtual void setDirection(const NLMISC::CVector& dir);
153 /// Get the direction vector
154 virtual void getDirection(NLMISC::CVector& dir) const;
155 /** Set the gain (volume value inside [0 , 1]). (default: 1)
156 * 0.0 -> silence
157 * 0.5 -> -6dB
158 * 1.0 -> no attenuation
159 * values > 1 (amplification) not supported by most drivers
161 virtual void setGain(float gain);
162 /// Get the gain
163 virtual float getGain() const;
164 /** Shift the frequency. 1.0f equals identity, each reduction of 50% equals a pitch shift
165 * of one octave. 0 is not a legal value.
167 virtual void setPitch(float pitch);
168 /// Get the pitch
169 virtual float getPitch() const;
170 /// Set the source relative mode. If true, positions are interpreted relative to the listener position
171 virtual void setSourceRelativeMode(bool mode);
172 /// Get the source relative mode
173 virtual bool getSourceRelativeMode() const;
174 /// Set the min and max distances (default: 1, MAX_FLOAT) (3D mode only)
175 virtual void setMinMaxDistances(float mindist, float maxdist, bool deferred = true);
176 /// Get the min and max distances
177 virtual void getMinMaxDistances(float& mindist, float& maxdist) const;
178 /// Set the cone angles (in radian) and gain (in [0 , 1]) (default: 2PI, 2PI, 0)
179 virtual void setCone(float innerAngle, float outerAngle, float outerGain);
180 /// Get the cone angles (in radian)
181 virtual void getCone(float& innerAngle, float& outerAngle, float& outerGain) const;
182 /** Set the alpha value for the volume-distance curve
184 * Useful only with OptionManualRolloff. value from -1 to 1 (default 0)
186 * alpha.0: the volume will decrease linearly between 0dB and -100 dB
187 * alpha = 1.0: the volume will decrease linearly between 1.0 and 0.0 (linear scale)
188 * alpha = -1.0: the volume will decrease inversely with the distance (1/dist). This
189 * is the default used by DirectSound/OpenAL
191 * For any other value of alpha, an interpolation is be done between the two
192 * adjacent curves. For example, if alpha equals 0.5, the volume will be halfway between
193 * the linear dB curve and the linear amplitude curve.
195 virtual void setAlpha(double a);
196 //@}
198 /// \name Direct output
199 //@{
200 /// Enable or disable direct output [true/false], default: true
201 virtual void setDirect(bool enable = true);
202 /// Return if the direct output is enabled
203 virtual bool getDirect() const;
204 /// Set the gain for the direct path
205 virtual void setDirectGain(float gain);
206 /// Get the gain for the direct path
207 virtual float getDirectGain() const;
209 /// Enable or disable the filter for the direct channel
210 virtual void enableDirectFilter(bool enable = true);
211 /// Check if the filter on the direct channel is enabled
212 virtual bool isDirectFilterEnabled() const;
213 /// Set the filter parameters for the direct channel
214 virtual void setDirectFilter(TFilter filter, float lowFrequency, float highFrequency, float passGain);
215 /// Get the filter parameters for the direct channel
216 virtual void getDirectFilter(TFilter &filterType, float &lowFrequency, float &highFrequency, float &passGain) const;
217 /// Set the direct filter gain
218 virtual void setDirectFilterPassGain(float passGain);
219 /// Get the direct filter gain
220 virtual float getDirectFilterPassGain() const;
221 //@}
223 /// \name Effect output
224 //@{
225 /// Set the effect send for this source, NULL to disable. [IEffect], default: NULL
226 virtual void setEffect(IReverbEffect *reverbEffect);
227 /// Get the effect send for this source
228 virtual IEffect *getEffect() const;
229 /// Set the gain for the effect path
230 virtual void setEffectGain(float gain);
231 /// Get the gain for the effect path
232 virtual float getEffectGain() const;
234 /// Enable or disable the filter for the effect channel
235 virtual void enableEffectFilter(bool enable = true);
236 /// Check if the filter on the effect channel is enabled
237 virtual bool isEffectFilterEnabled() const;
238 /// Set the filter parameters for the effect channel
239 virtual void setEffectFilter(TFilter filter, float lowFrequency, float highFrequency, float passGain);
240 /// Get the filter parameters for the effect channel
241 virtual void getEffectFilter(TFilter &filterType, float &lowFrequency, float &highFrequency, float &passGain) const;
242 /// Set the effect filter gain
243 virtual void setEffectFilterPassGain(float passGain);
244 /// Get the effect filter gain
245 virtual float getEffectFilterPassGain() const;
246 //@}
248 /// Return the OpenAL source name
249 uint sourceName() { return _SourceName; }
251 /// Returns the buffer associated with this source.
252 IBuffer *getBuffer();
254 /// Reset the source before reuse
255 void reset();
257 /// Update the source (e.g. continue to stream the data in)
258 bool update();
260 /// Update the source's volume according to its distance and fade out curve.
261 /// It takes the current position of the listener as argument.
262 void updateVolume(const NLMISC::CVector& listener);
264 private:
266 void copySampleTo16BitsTrack(void *dst, void *src, uint nbSample, TSampleFormat sourceFormat);
268 enum TSourceState
270 source_stopped,
271 source_playing,
272 source_silencing,
273 source_swap_pending
277 /// Release all DirectSound resources
278 void release();
280 // The minimum size of available space in the DS buffer for update
281 static const uint32 _UpdateCopySize;
282 // The size of the samples that are copied when buffers are swapped
283 static const uint32 _SwapCopySize;
284 // The number of channels
285 static const uint _DefaultChannels;
286 // The default sample rate
287 static const uint _DefaultSampleRate;
288 // The default sample size
289 static const uint _DefaultSampleSize;
290 // The length of the crossfade, in samples
291 static const uint32 _XFadeSize;
293 /// The play and write cursors
294 struct TCursors
296 uint32 PlayCursor;
297 uint32 WriteCursor;
298 uint32 WriteSize;
301 /// A locked buffer info.
302 struct TLockedBufferInfo
304 // First locked part.
305 sint16 *Ptr1;
306 uint32 Size1;
308 // second locked part (or 0 if none)
309 sint16 *Ptr2;
310 uint32 Size2;
313 // Utility function that locks the DirectSound buffer and restores it if it was lost.
314 // bool lock(uint32 writePos, uint32 size, uint8* &ptr1, DWORD &bytes1, uint8* &ptr2, DWORD &bytes2);
315 bool lock(uint32 writePos, uint32 size, TLockedBufferInfo &lockedInfo);
317 // Utility function that unlocks the DirectSound buffer
318 // bool unlock(uint8* ptr1, DWORD bytes1, uint8* ptr2, DWORD bytes2);
319 bool unlock(const TLockedBufferInfo &lockedInfo);
321 void getCursors(TCursors &cursors);
322 uint32 checkFillCursor();
325 void fillData(const TLockedBufferInfo &lbi, int nbSample);
326 void fillData(sint16 *dst, uint nbSample);
327 void fillSilence(const TLockedBufferInfo &lbi, int nbSample);
329 void xfade(const TLockedBufferInfo &lbi, sint16 *src);
330 void fadeOut(const TLockedBufferInfo &lbi);
331 void fadeIn(const TLockedBufferInfo &lbi);
333 void advanceFill(TLockedBufferInfo &lbi, uint nbSample);
337 // Replace the current buffer with the swap buffer
338 void swap();
339 // getFadeOutSize() calculates how many samples have been written after the
340 // write cursor in the DirectSound buffer. This value is returned in the
341 // writtenTooMuch variable. The xfadeSize contains the number of samples over
342 // which to do a xfade or fade out, and in1 points to the sample in the sample
343 // buffer where to start the fade.
344 // void getFadeOutSize(uint32 writePos, uint32& xfadeSize, sint16* &in1, uint32 &writtenTooMuch);
346 // Fill the buffer with fresh samples. Should be called inside the critical zone.
347 bool fill();
348 // Fill the buffer with sparkling silence. Should be called inside the critical zone.
349 bool silence();
350 // Do a cross fade between the current buffer and the buffer stored in the _SwapBuffer
351 // variable. Call inside the critical zone.
352 void crossFade();
353 // Fade out the current buffer. Call inside the critical zone.
354 void fadeOut();
355 // Fade in the current buffer. Call inside the critical zone.
356 void fadeIn();
357 /// Check whether the play position has advanced enough to require an update
358 bool needsUpdate();
361 // Source name
362 uint _SourceName;
365 TSourceState _State;
366 // uint32 _FillCursor;
368 // The size of the sound buffer, in bytes
369 // uint32 _BufferSize;
371 IBuffer *_Sample;
372 // Size of the buffer in sample
373 uint _SampleSize;
374 // Position in the buffer in sample.
375 uint _SampleOffset;
376 // The number of sample realy played (depend on play cursor).
377 uint32 _PlayOffset;
378 TSampleFormat _Format;
379 uint _SampleFreq;
382 // The frequency of the source [0,10], i.e. slowed down or accelerated
383 float _Freq;
384 // The sample rate of the source (= _Freq * _Buffer sample rate)
385 uint32 _SampleRate;
388 IBuffer *_NextSample;
390 uint32 _LastPlayPos;
391 uint32 _FillOffset;
392 uint32 _SilenceWriten;
394 // The next sound buffer
395 // IBuffer *_SwapBuffer;
397 // To loop or not to loop
398 bool _Loop;
400 // The state of the source (playing, paused, stopped)
401 // TSourceDSoundUserState _UserState;
403 // DirectSound secondary buffer
404 LPDIRECTSOUNDBUFFER _SecondaryBuffer;
405 // The byte size of the DirectSound secondary buffers
406 static const uint32 _SecondaryBufferSize;
407 // The mask for the buffer size
408 static const uint32 _SizeMask;
409 // 3D interface of the secondary buffer.
410 LPDIRECTSOUND3DBUFFER _3DBuffer;
411 // The critial section object to protect the swap and update functions
412 CRITICAL_SECTION _CriticalSection;
414 // The state for ADPCM decompression.
415 IBuffer::TADPCMState _ADPCMState;
418 // The state of the DirectSound buffer (filling, silencing, silenced)
419 // TSourceDSoundBufferState _SecondaryBufferState;
423 // The next position in the DirectSound buffer where we should write next
424 // uint32 _NextWritePos;
426 // The total number of bytes written from the current sound buffer
427 // uint32 _BytesWritten;
429 // The amount of silence written (in bytes) after the end of the current sound buffer
430 // uint32 _SilenceWritten;
432 // The position of the last audio sample written.
433 // uint32 _EndPosition;
436 // The state of the buffer to reach the end of the audio samples. To flag the buffer as
437 // STOPPED, we have to make sure all the samples in the buffer are played. The play
438 // cursor in the DirectSound buffer is inspected and when it crosses the position of
439 // the last sample written (_EndPosition) the buffer is flagged as stopped. The _EndState
440 // field is used to keep a trace of the whereabouts of the play cursor.
441 // TSourceDSoundEndState _EndState;
444 // Has this source been handed out.
445 /* bool _IsUsed;
447 // Set the 'used' state of the source. Managed by the driver.
448 void setUsed(bool v) { _IsUsed = v; }
450 // Return the 'used' state of the source
451 bool isUsed() { return _IsUsed; }
453 sint32 _Volume;
454 float _Gain;
455 double _Alpha;
456 NLMISC::CVector _Pos;
457 bool _PosRelative;
459 #if EAX_AVAILABLE == 1
460 LPKSPROPERTYSET _EAXSource;
461 #endif
464 #if NLSOUND_PROFILE
466 public:
468 static double _LastSwapTime;
469 static double _TotalSwapTime;
470 static double _MaxSwapTime;
471 static double _MinSwapTime;
472 static uint32 _SwapCount;
474 static double _TotalUpdateTime;
475 static double _MaxUpdateTime;
476 static double _MinUpdateTime;
477 static uint32 _UpdateCount;
478 static uint32 _TotalUpdateSize;
480 static double _PosTime;
481 static double _LockTime;
482 static double _CopyTime;
483 static double _UnlockTime;
484 static uint32 _CopyCount;
486 public:
488 static double getTestLast() { return 1000.0f * _LastSwapTime; };
489 static double getTestMax() { return 1000.0f * _MaxSwapTime; };
490 static double getTestMin() { return 1000.0f * _MinSwapTime; };
491 static double getTestAverage() { return (_SwapCount > 0) ? 1000.0f * _TotalSwapTime / _SwapCount : 0.0; };
493 static double getAveragePosTime() { return (_CopyCount > 0) ? 1000.0f * _PosTime / _CopyCount : 0.0; };
494 static double getAverageLockTime() { return (_CopyCount > 0) ? 1000.0f * _LockTime / _CopyCount : 0.0; };
495 static double getAverageCopyTime() { return (_CopyCount > 0) ? 1000.0f * _CopyTime / _CopyCount : 0.0; };
496 static double getAverageUnlockTime() { return (_CopyCount > 0) ? 1000.0f * _UnlockTime / _CopyCount : 0.0; };
497 static double getAverageCumulTime() { return (_CopyCount > 0) ? 1000.0f * (_PosTime + _LockTime + _CopyTime + _UnlockTime) / _CopyCount : 0.0; };
498 static uint getAverageUpdateSize() { return (_CopyCount > 0) ? (uint) (_TotalUpdateSize / _CopyCount) : 0; };
500 static double getMaxUpdateTime() { return 1000.0f * _MaxUpdateTime; };
501 static double getMinUpdateTime() { return 1000.0f * _MinUpdateTime; };
502 static double getAverageUpdateTime() { return (_UpdateCount > 0) ? 1000.0f * _TotalUpdateTime / _UpdateCount : 0.0; };
504 static double getTotalUpdateTime() { return 1000.0f * _TotalUpdateTime; };
505 static double getUpdateBytesPerMsec() { return (_UpdateCount > 0) ? _TotalUpdateSize / _TotalUpdateTime / 1000.0 : 0.0; }
507 #endif
512 } // NLSOUND
515 #endif // NL_SOURCE_DSOUND_H
517 /* End of source_al.h */