sampling.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #include "main.h"
  2. #include <ks.h>
  3. #include <ksmedia.h>
  4. #include <malloc.h>
  5. static void make_wfx(WAVEFORMATEX * wfx,int srate,int nch,int bps)
  6. {
  7. wfx->wFormatTag=WAVE_FORMAT_PCM;
  8. wfx->nChannels=nch;
  9. wfx->nSamplesPerSec=srate;
  10. wfx->nAvgBytesPerSec=srate*nch*(bps>>3);
  11. wfx->nBlockAlign=nch * (bps>>3);
  12. wfx->wBitsPerSample=bps;
  13. wfx->cbSize=0;
  14. }
  15. static void make_wfxe(WAVEFORMATEXTENSIBLE * wfx,int srate,int nch,int bps)
  16. {
  17. make_wfx(&wfx->Format,srate,nch,bps);
  18. wfx->Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
  19. wfx->Format.cbSize=22;
  20. wfx->Samples.wReserved=0;
  21. wfx->dwChannelMask=0;
  22. wfx->SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
  23. }
  24. #ifndef IN_MIDI_NO_WAVEIN_SOURCE
  25. extern cfg_int cfg_samp_revert;
  26. #define MMBOOL MIXERCONTROLDETAILS_BOOLEAN
  27. static MMBOOL *do_mixer_shit(DWORD param,DWORD type,BOOL store,UINT input,MMBOOL *tab)
  28. {
  29. UINT id=0;
  30. mixerGetID((HMIXEROBJ)param,&id,type);
  31. MIXERCAPS caps;
  32. mixerGetDevCaps(id,&caps,sizeof(caps));
  33. MIXERLINE ml;
  34. ZeroMemory(&ml,sizeof(ml));
  35. ml.cbStruct=sizeof(ml);
  36. ml.dwComponentType=MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
  37. mixerGetLineInfo((HMIXEROBJ)id,&ml,MIXER_GETLINEINFOF_COMPONENTTYPE|MIXER_OBJECTF_MIXER);
  38. MIXERLINECONTROLS cs;
  39. MIXERCONTROL c;
  40. ZeroMemory(&cs,sizeof(cs));
  41. cs.cbStruct=sizeof(cs);
  42. cs.cControls=1;
  43. cs.dwLineID=ml.dwLineID;
  44. cs.dwControlType=MIXERCONTROL_CONTROLTYPE_MUX;
  45. cs.cbmxctrl=sizeof(c);
  46. cs.pamxctrl=&c;
  47. ZeroMemory(&c,sizeof(c));
  48. c.cbStruct=sizeof(c);
  49. if (!mixerGetLineControls((HMIXEROBJ)id,&cs,MIXER_OBJECTF_MIXER|MIXER_GETLINECONTROLSF_ONEBYTYPE))
  50. {
  51. if (store)
  52. {
  53. if (!tab)
  54. {
  55. tab=(MMBOOL*)alloca(sizeof(MMBOOL)*c.cMultipleItems);
  56. memset(tab,0,sizeof(MMBOOL)*c.cMultipleItems);
  57. tab[input].fValue=1;
  58. }
  59. }
  60. else
  61. {
  62. if (!tab) tab=new MMBOOL[c.cMultipleItems];
  63. }
  64. if (tab)
  65. {
  66. MIXERCONTROLDETAILS d;
  67. d.cbStruct=sizeof(d);
  68. d.dwControlID=c.dwControlID;
  69. d.cbDetails=sizeof(MMBOOL);
  70. d.cChannels=ml.cChannels;
  71. d.cMultipleItems=c.cMultipleItems;
  72. d.paDetails=tab;
  73. if (store) mixerSetControlDetails((HMIXEROBJ)id,&d,MIXER_SETCONTROLDETAILSF_VALUE |MIXER_OBJECTF_MIXER);
  74. else mixerGetControlDetails((HMIXEROBJ)id,&d,MIXER_GETCONTROLDETAILSF_VALUE |MIXER_OBJECTF_MIXER);
  75. }
  76. }
  77. return tab;
  78. }
  79. #endif
  80. class CVis : public CStream
  81. {
  82. private:
  83. #ifndef IN_MIDI_NO_WAVEIN_SOURCE
  84. MMBOOL * old_settings;
  85. UINT wavein_id;
  86. void src_init()
  87. {
  88. wavein_id=(UINT)cfg_wavein_dev;
  89. if (cfg_wavein_src)
  90. {
  91. if (cfg_samp_revert) old_settings = do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,0,0,0);
  92. do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,1,cfg_wavein_src-1,0);
  93. }
  94. }
  95. void src_deinit()
  96. {
  97. if (old_settings)
  98. {
  99. do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,1,0,old_settings);
  100. delete[] old_settings;
  101. old_settings=0;
  102. }
  103. }
  104. #endif
  105. bool eof;
  106. public:
  107. bool init(int p_srate,int p_nch,int p_bps);
  108. void Eof() {eof=1;}
  109. virtual void Pause(int);
  110. virtual UINT ReadData(void*,UINT,bool*);
  111. virtual void Flush();
  112. virtual ~CVis();
  113. CVis()
  114. {
  115. #ifndef IN_MIDI_NO_WAVEIN_SOURCE
  116. old_settings=0;
  117. #endif
  118. eof=0;buffer=0;blox=0;hWi=0;}
  119. private:
  120. BYTE * buffer;
  121. UINT bufsize;
  122. UINT read_pos;
  123. UINT data;
  124. UINT blocksize;
  125. HWAVEIN hWi;
  126. WAVEHDR *blox;
  127. UINT numblocks;
  128. UINT cur_block,cur_done;
  129. int paused;
  130. UINT in_mm;
  131. int srate,nch,bps;
  132. // void on_done(WAVEBUFFER*);
  133. };
  134. void CVis::Flush()
  135. {
  136. if (paused) return;
  137. waveInReset(hWi);
  138. UINT n;
  139. for(n=0;n<numblocks;n++)
  140. {
  141. blox[n].dwUser=0;
  142. waveInAddBuffer(hWi,&blox[n],sizeof(WAVEHDR));
  143. }
  144. cur_block=0;
  145. cur_done=0;
  146. in_mm=numblocks;//added all blocks already
  147. read_pos=0;
  148. data=0;
  149. waveInStart(hWi);
  150. }
  151. void CALLBACK waveInProc(HWAVEIN hWi,UINT msg,DWORD dwIns,DWORD p1,DWORD p2)
  152. {
  153. if (msg==WIM_DATA && p1)
  154. {
  155. ((WAVEHDR*)p1)->dwUser=1;
  156. }
  157. }
  158. bool CVis::init(int p_srate,int p_nch,int p_bps)
  159. {
  160. srate=p_srate;
  161. nch=p_nch;
  162. bps=p_bps;
  163. blocksize=576 * (bps/8) * (nch);
  164. if (cfg_sampout) blocksize<<=3;
  165. numblocks=(2 * srate * nch * (bps>>3))/blocksize;
  166. bufsize=numblocks*blocksize;
  167. blox=new WAVEHDR[numblocks];
  168. memset(blox,0,sizeof(WAVEHDR)*numblocks);
  169. buffer=(BYTE*)malloc(bufsize);
  170. try
  171. {
  172. WAVEFORMATEX wfx;
  173. make_wfx(&wfx,srate,nch,bps);
  174. if (waveInOpen(&hWi,cfg_wavein_dev,&wfx,(DWORD)waveInProc,0,CALLBACK_FUNCTION))
  175. {
  176. WAVEFORMATEXTENSIBLE wfxe = {0};
  177. make_wfxe(&wfxe,srate,nch,bps);
  178. if (waveInOpen(&hWi,cfg_wavein_dev,&wfxe.Format,(DWORD)waveInProc,0,CALLBACK_FUNCTION))
  179. {
  180. return 0;
  181. }
  182. }
  183. } catch(...)//gay drivers etc
  184. {
  185. return 0;
  186. }
  187. #ifndef IN_MIDI_NO_WAVEIN_SOURCE
  188. src_init();
  189. #endif
  190. UINT n;
  191. for(n=0;n<numblocks;n++)
  192. {
  193. blox[n].lpData=(char*)(buffer+blocksize*n);
  194. blox[n].dwBufferLength=blocksize;
  195. waveInPrepareHeader(hWi,&blox[n],sizeof(WAVEHDR));
  196. }
  197. paused=0;
  198. Flush();
  199. #ifdef USE_LOG
  200. log_write("sampling started OK");
  201. #endif
  202. return 1;
  203. }
  204. CVis::~CVis()
  205. {
  206. #ifdef USE_LOG
  207. log_write("shutting down sampling");
  208. #endif
  209. if (hWi)
  210. {
  211. waveInReset(hWi);
  212. UINT n;
  213. for(n=0;n<numblocks;n++)
  214. {
  215. waveInUnprepareHeader(hWi,&blox[n],sizeof(WAVEHDR));
  216. }
  217. #ifndef IN_MIDI_NO_WAVEIN_SOURCE
  218. src_deinit();
  219. #endif
  220. waveInClose(hWi);
  221. hWi=0;
  222. }
  223. #ifdef USE_LOG
  224. log_write("sampling shut down OK");
  225. #endif
  226. if (blox) delete[] blox;
  227. if (buffer) free(buffer);
  228. }
  229. UINT CVis::ReadData(void * _dst,UINT bytes,bool * ks)
  230. {
  231. if (eof) return 0;
  232. BYTE * dst=(BYTE*)_dst;
  233. if (paused) return 0;
  234. while(!*ks)
  235. {
  236. while(blox[cur_done].dwUser)
  237. {
  238. blox[cur_done].dwUser=0;
  239. cur_done=(cur_done+1)%numblocks;
  240. in_mm--;
  241. data+=blocksize;
  242. }
  243. {
  244. UINT d=data;
  245. if (d)
  246. {
  247. if (d>bytes) d=bytes;
  248. if (read_pos+d>bufsize)
  249. {
  250. UINT foo=bufsize-read_pos;
  251. memcpy(dst,buffer+read_pos,foo);
  252. memcpy(dst+foo,buffer,read_pos=d-foo);
  253. }
  254. else
  255. {
  256. memcpy(dst,buffer+read_pos,d);
  257. read_pos+=d;
  258. }
  259. dst+=d;
  260. data-=d;
  261. bytes-=d;
  262. }
  263. }
  264. {
  265. UINT max=numblocks-(data+blocksize-1)/blocksize;
  266. while(in_mm < max)
  267. {
  268. waveInAddBuffer(hWi,&blox[cur_block],sizeof(WAVEHDR));
  269. cur_block=(cur_block+1)%numblocks;
  270. in_mm++;
  271. }
  272. }
  273. if (!bytes) break;
  274. MIDI_callback::Idle();
  275. }
  276. return dst-(BYTE*)_dst;
  277. }
  278. void CVis::Pause(int b)
  279. {
  280. paused=b;
  281. if (b)
  282. {
  283. waveInStop(hWi);
  284. }
  285. else
  286. {
  287. Flush();
  288. }
  289. }
  290. CStream * sampling_create(int srate,int nch,int bps)
  291. {
  292. CVis * ptr = new CVis;
  293. if (!ptr->init(srate,nch,bps))
  294. {
  295. delete ptr;
  296. ptr=0;
  297. }
  298. return ptr;
  299. }