ds2.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #ifndef _DS2_H
  2. #define _DS2_H
  3. #ifndef STRICT
  4. #define STRICT
  5. #endif
  6. #include <windows.h>
  7. #include <mmsystem.h>
  8. #include <dsound.h>
  9. #include "ds_main.h"
  10. #include "Config.h"
  11. #include "SoundBlockList.h"
  12. #include "DevEnum.h"
  13. #include "VolCtrl.h"
  14. class CriticalSection : public CRITICAL_SECTION
  15. {
  16. public:
  17. inline void Enter() {EnterCriticalSection(this);}
  18. inline void Leave() {LeaveCriticalSection(this);}
  19. CriticalSection() {InitializeCriticalSection(this);}
  20. ~CriticalSection() {DeleteCriticalSection(this);}
  21. //BOOL TryEnter() {return TryEnterCriticalSection(this);}
  22. };
  23. typedef struct
  24. {
  25. UINT sr,bps,nch;
  26. UINT buf_size_bytes,buf_size_ms;
  27. UINT pos_play,pos_write,latency,latency_ms;
  28. UINT lock_count;
  29. UINT underruns;
  30. size_t bytes_async;
  31. __int64 bytes_written,bytes_played;
  32. double vol_left,vol_right;
  33. GUID current_device;
  34. bool have_primary_buffer;
  35. bool paused;
  36. DWORD dscaps_flags;
  37. DWORD dscaps_flags_primary;
  38. } DS2_REALTIME_STAT;
  39. class DS2
  40. {
  41. private:
  42. DS2(DS2config * cfg);
  43. SoundBlockList BlockList;
  44. UINT LockCount;
  45. UINT Underruns;
  46. bool DoLock();
  47. public:
  48. ~DS2();
  49. int WriteData(void * data,UINT size,bool *killswitch);//returns 1 on success and 0 on failure
  50. int WriteDataNow(void * data,UINT size);//sleep-less version, writes CanWrite() of bytes immediately, returns amount of data written
  51. int ForceWriteData(void * data,UINT size);//sleep-less force-write all the data w/o sleep/canwrite (async buffer has no size limit), use with caution
  52. /*
  53. how to use writedata shit
  54. a) just WriteData(), will sleep until its done
  55. b) WriteDataNow() until we're done (writes as much data as possible at the moment, without sleep)
  56. c) ForceWriteData() (evil!), then sleep while CanWrite()<0
  57. */
  58. void StartNewStream();
  59. UINT GetLatency();
  60. void _inline Release() {delete this;}//obsolete
  61. void Pause(int new_state);
  62. void SetVolume(double);
  63. inline void SetVolume_Int(int i) {SetVolume((double)i/255.0);}
  64. void SetPan(double);
  65. inline void SetPan_Int(int i) {SetPan((double)i/128.0);}
  66. void Flush();//causes problems with some um.. drivers
  67. int CanWrite();//can be negative !!!!!!! (eg. after ForceWriteData)
  68. inline UINT BufferStatusPercent() {return MulDiv(data_buffered+(UINT)BlockList.DataSize(),buf_size,100);}
  69. void ForcePlay();
  70. void KillEndGap();
  71. #ifdef DS2_HAVE_FADES
  72. void FadePause(UINT time);
  73. void FadeAndForget(UINT time);
  74. void Fade(UINT time,double destvol);
  75. inline void Fade_Int(UINT time,int destvol) {Fade(time,(double)destvol/255.0);}
  76. void FadeX(UINT time,double destvol);//actual fade time depends on volume difference
  77. inline void FadeX_Int(UINT time,int destvol) {FadeX(time,(double)destvol/255.0);}
  78. #endif
  79. void WaitFor(DS2 * prev,UINT fadeout=0);
  80. //gapless mode stuff
  81. void SetCloseOnStop(bool b);
  82. bool IsClosed();
  83. private:
  84. #ifdef _DEBUG
  85. DWORD serial;
  86. UINT sync_n;
  87. #endif
  88. int Open(DS2config * cfg);
  89. DS2 * next;
  90. DS2 * wait;
  91. UINT prebuf;
  92. DWORD flags;
  93. enum
  94. {
  95. FLAG_UPDATED=1,
  96. FLAG_WAITED=1<<1,
  97. FLAG_NEED_PLAY_NOW=1<<2,
  98. FLAG_DIE_ON_STOP=1<<3,
  99. FLAG_CLOSE_ON_STOP=1<<4,
  100. FLAG_PAUSED=1<<5,
  101. FLAG_PLAYING=1<<6,
  102. // FLAG_UNDERRUNNING=1<<7,
  103. FLAG_USE_CPU_MNGMNT=1<<8,
  104. FLAG_FADEPAUSE=1<<9,
  105. FLAG_FADEPAUSING=1<<10,
  106. FLAG_STARTSIL=1<<11,
  107. FLAG_SWMIXED=1<<12,
  108. };
  109. IDirectSoundBuffer * pDSB;
  110. IDirectSound * myDS;
  111. UINT fmt_nch,fmt_bps,fmt_sr,fmt_mul;
  112. UINT buf_size,clear_size;
  113. __int64 last_nonsil,pos_delta,pos_delta2;
  114. inline __int64 GetCurPos() {return data_written-data_buffered;}
  115. __int64 GetSafeWrite();
  116. __int64 data_written;
  117. UINT data_buffered;
  118. UINT silence_buffered;
  119. UINT bytes2ms(UINT bytes);
  120. UINT ms2bytes(UINT ms);
  121. #ifdef DS2_HAVE_FADES
  122. DsVolCtrl VolCtrl;
  123. double fadepause_orgvol;
  124. UINT fadepause_time;
  125. UINT waitfade;
  126. #else
  127. class DsVolCtrl
  128. {
  129. private:
  130. double CurVol,CurPan;
  131. public:
  132. DsVolCtrl() {CurVol=1;CurPan=0;}
  133. inline void SetTime(__int64) {}
  134. inline void SetFade(__int64,double) {}
  135. inline void SetFadeVol(__int64,double,double) {}
  136. inline void SetFadePan(__int64,double,double) {}
  137. inline void SetVolume(double v) {CurVol=v;}
  138. inline void SetPan(double p) {CurPan=p;}
  139. // inline __int64 RelFade(__int64 max,double destvol) {return 0;}
  140. void Apply(IDirectSoundBuffer * pDSB);
  141. inline bool Fading() {return 0;}
  142. // inline double GetCurVol() {return CurVol;}
  143. // inline double GetDestVol() {return CurVol;}
  144. inline void Reset() {}
  145. };
  146. DsVolCtrl VolCtrl;
  147. #endif
  148. void SetVolumeI(double);
  149. void SetPanI(int _pan);
  150. void _setvol();
  151. void _setpan();
  152. void update_pos();
  153. void ds_stop();
  154. void ds_kill();
  155. bool Update();
  156. void reset_vars();
  157. void do_reset_vars();
  158. int silence_delta;
  159. void test_silence(char * buf,int len,int * first,int* last);
  160. static DWORD WINAPI ThreadFunc(void*);
  161. UINT _inline _align() {return (fmt_bps>>3)*fmt_nch;}
  162. UINT _inline _align_var(UINT var) {return var-(var%_align());}
  163. static void SYNC_IN();
  164. static void SYNC_OUT();
  165. typedef HRESULT (WINAPI *tDirectSoundCreate)( const GUID * lpGuid, LPDIRECTSOUND * ppDS, IUnknown FAR * pUnkOuter );
  166. static tDirectSoundCreate pDirectSoundCreate;
  167. static IDirectSound * pDS;
  168. public:
  169. static void Init();//init is OBSOLETE
  170. static void Quit(bool wait=0);//must be called on exit, NOT from DllMain, its ok to call it if init never happened
  171. static DS2 * Create(DS2config * cfg);
  172. static bool InitDLL();//used internally
  173. static HRESULT myDirectSoundCreate(const GUID * g,IDirectSound ** out);
  174. static void SetTotalTime(__int64);
  175. static __int64 GetTotalTime();
  176. static UINT InstanceCount();
  177. void GetRealtimeStat(DS2_REALTIME_STAT * stat);
  178. static bool GetRealtimeStatStatic(DS2_REALTIME_STAT * stat);
  179. __int64 GetOutputTime();
  180. #ifdef DS2_HAVE_DEVICES
  181. static bool TryGetDevCaps(const GUID *g,LPDSCAPS pCaps,DWORD * speakercfg=0);//for current device
  182. typedef HRESULT (WINAPI *tDirectSoundEnumerate)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext);
  183. static tDirectSoundEnumerate pDirectSoundEnumerate;
  184. static GUID GetCurDev();
  185. #endif
  186. #ifdef DS2_HAVE_PITCH
  187. void SetPitch(double p);
  188. #endif
  189. };
  190. #endif