fakedsound.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "main.h"
  2. #include "fakedsound.h"
  3. //DirectMusic output capture hack.
  4. class FakeDirectSoundBuffer : public IDirectSoundBuffer
  5. {
  6. private:
  7. ULONG ref;
  8. CPipe* out;
  9. UINT freq;
  10. BYTE * buf;
  11. UINT buf_size;
  12. bool playing;
  13. DWORD pos_play;
  14. DWORD samples_played;
  15. DWORD start;
  16. void do_update();
  17. public:
  18. ~FakeDirectSoundBuffer()
  19. {
  20. if (buf) free(buf);
  21. };
  22. HRESULT _stdcall QueryInterface(REFIID iid, void** i)
  23. {
  24. if (IsEqualIID(iid,IID_IUnknown) || IsEqualIID(iid,IID_IDirectSoundBuffer))
  25. {
  26. ref++;
  27. *i = this;
  28. return S_OK;
  29. }
  30. else return E_NOINTERFACE;
  31. }
  32. ULONG _stdcall AddRef() {return ++ref;};
  33. ULONG _stdcall Release()
  34. {
  35. UINT r=--ref;
  36. if (!r)
  37. {
  38. delete this;
  39. }
  40. return r;
  41. }
  42. HRESULT _stdcall GetCaps(LPDSBCAPS _caps)
  43. {
  44. DSBCAPS caps=
  45. {
  46. sizeof(DSBCAPS),
  47. DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_LOCSOFTWARE,
  48. buf_size,
  49. 0,0 //CPU crap
  50. };
  51. *_caps = caps;
  52. return S_OK;
  53. }
  54. HRESULT _stdcall Initialize(LPDIRECTSOUND, LPCDSBUFFERDESC) {return DSERR_ALREADYINITIALIZED;}
  55. HRESULT _stdcall SetFormat(LPCWAVEFORMATEX) {return DSERR_INVALIDCALL;}
  56. HRESULT _stdcall GetFormat(LPWAVEFORMATEX wfx,DWORD,LPDWORD w)
  57. {
  58. wfx->wFormatTag=WAVE_FORMAT_PCM;
  59. wfx->nChannels=2;
  60. wfx->nSamplesPerSec=freq;
  61. wfx->nAvgBytesPerSec=4*freq;
  62. wfx->nBlockAlign=4;
  63. wfx->wBitsPerSample=16;
  64. wfx->cbSize=0;
  65. if (w) *w=sizeof(WAVEFORMATEX);
  66. return S_OK;
  67. }
  68. HRESULT _stdcall GetVolume(long* v) {return S_OK;}
  69. HRESULT _stdcall SetVolume(long v) {return S_OK;}
  70. HRESULT _stdcall GetPan(long *p) {return S_OK;}
  71. HRESULT _stdcall SetPan(long p) {return S_OK;}
  72. HRESULT _stdcall GetFrequency(DWORD* f) {*f=freq;return S_OK;}
  73. HRESULT _stdcall SetFrequency(DWORD f) {return S_OK;}
  74. HRESULT _stdcall GetStatus(DWORD* s)
  75. {
  76. *s = DSBSTATUS_PLAYING|DSBSTATUS_LOOPING;
  77. return S_OK;
  78. }
  79. HRESULT _stdcall SetCurrentPosition(DWORD) {return S_OK;}
  80. HRESULT _stdcall Restore() {return S_OK;}
  81. HRESULT _stdcall Lock(DWORD wr_cur, DWORD wr_b, void** p1, DWORD* s1, void** p2, DWORD* s2, DWORD flagz)
  82. {
  83. if (wr_b>buf_size)
  84. {
  85. return DSERR_INVALIDPARAM;
  86. }
  87. *p1 = buf + wr_cur;
  88. if (wr_cur + wr_b > buf_size)
  89. {
  90. *s1 = buf_size - wr_cur;
  91. *p2 = buf;
  92. *s2 = wr_cur+wr_b - buf_size;
  93. }
  94. else
  95. {
  96. *s1 = wr_b;
  97. *p2 = 0;
  98. *s2 = 0;
  99. }
  100. return S_OK;
  101. }
  102. HRESULT _stdcall GetCurrentPosition(LPDWORD p, LPDWORD w)
  103. {
  104. do_update();
  105. if (p) *p=pos_play;
  106. if (w) *w=pos_play;
  107. return S_OK;
  108. }
  109. HRESULT _stdcall Play(DWORD, DWORD, DWORD)
  110. {
  111. playing=1;
  112. pos_play=0;
  113. samples_played=0;
  114. start=timeGetTime();
  115. return S_OK;
  116. }
  117. HRESULT _stdcall Stop() {do_update();playing=0;return S_OK;}
  118. HRESULT _stdcall Unlock(LPVOID, DWORD, LPVOID, DWORD)
  119. {
  120. do_update();
  121. return S_OK;
  122. }
  123. FakeDirectSoundBuffer(UINT _freq,UINT size)
  124. {
  125. ref=1;
  126. buf_size=size;
  127. buf=(BYTE*)malloc(size);
  128. memset(buf,0,size);
  129. freq=_freq;
  130. out=new CPipe(4,freq);
  131. MIDI_core::player_setSource(out);
  132. playing=0;
  133. pos_play=0;
  134. samples_played=0;
  135. }
  136. };
  137. void FakeDirectSoundBuffer::do_update()
  138. {
  139. if (playing)
  140. {
  141. int ds=MulDiv(timeGetTime()-start,freq,1000)-samples_played;
  142. if (ds>0)
  143. {
  144. UINT todo=ds*4;
  145. while(pos_play+todo>buf_size)
  146. {
  147. out->WriteData(buf+pos_play,buf_size-pos_play);
  148. todo-=buf_size-pos_play;
  149. pos_play=0;
  150. }
  151. if (todo)
  152. {
  153. out->WriteData(buf+pos_play,todo);
  154. pos_play+=todo;
  155. //todo=0;
  156. }
  157. samples_played+=ds;
  158. }
  159. }
  160. }
  161. IDirectSoundBuffer* dhb_create(DWORD s,DWORD f)
  162. {
  163. return new FakeDirectSoundBuffer(f,s);
  164. }
  165. //fake IDirectSound crap. one static instance
  166. static DSCAPS h_caps=
  167. {
  168. sizeof(DSCAPS),
  169. DSCAPS_SECONDARY16BIT|DSCAPS_SECONDARYSTEREO,
  170. 1000,
  171. 100000,
  172. 1,
  173. 1000,
  174. 1000,
  175. 1000,//streaming buffers
  176. 1000,
  177. 1000,
  178. 1000,
  179. 0,0,0,0,0,0,//3d crap
  180. 1024*1024,
  181. 1024*1024,
  182. 1024*1024,
  183. 0,0, //CPU speed crap
  184. 0,0 //reserved crap
  185. };
  186. class FakeDsound : public IDirectSound
  187. {
  188. ULONG ref:1;
  189. HRESULT _stdcall QueryInterface(REFIID iid,void** i)
  190. {
  191. if (IsEqualIID(iid,IID_IUnknown) || IsEqualIID(iid,IID_IDirectSound))
  192. {
  193. ref++;
  194. *i = this;
  195. return S_OK;
  196. }
  197. else return E_NOINTERFACE;
  198. }
  199. ULONG _stdcall AddRef() {return ++ref;}
  200. ULONG _stdcall Release() {return --ref;}
  201. HRESULT _stdcall CreateSoundBuffer(LPCDSBUFFERDESC, LPDIRECTSOUNDBUFFER *, LPUNKNOWN) {return DSERR_INVALIDCALL;}
  202. HRESULT _stdcall GetCaps(LPDSCAPS _caps)
  203. {
  204. *_caps = h_caps;
  205. return S_OK;
  206. }
  207. HRESULT _stdcall DuplicateSoundBuffer(LPDIRECTSOUNDBUFFER, LPDIRECTSOUNDBUFFER *) {return DSERR_INVALIDCALL;}
  208. HRESULT _stdcall SetCooperativeLevel(HWND, DWORD) {return S_OK;}
  209. HRESULT _stdcall Compact() {return S_OK;}
  210. HRESULT _stdcall GetSpeakerConfig(LPDWORD moo) {*moo=0;return S_OK;}
  211. HRESULT _stdcall SetSpeakerConfig(DWORD) {return S_OK;}
  212. HRESULT _stdcall Initialize(LPCGUID) {return DSERR_ALREADYINITIALIZED;}
  213. };
  214. static FakeDsound HACK;
  215. IDirectSound * get_ds() {return &HACK;}