Sound.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #include "Sound.h"
  2. #ifdef WIN32
  3. #include "Player.h"
  4. #else
  5. #include "Player.h"
  6. #endif
  7. using namespace GSL;
  8. #ifdef WIN32
  9. extern GSLPlayer *_player;
  10. void CALLBACK AudioOutProc( HWAVEOUT hOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 );
  11. #endif
  12. // Inhalt der Sound Klasse aus Sound.h
  13. // Konstruktor
  14. GSLSound::GSLSound( const SoundKopf &skpf )
  15. : Thread()
  16. {
  17. kpf = skpf;
  18. dat = new Datei();
  19. dat->setDatei( kpf.pfad );
  20. #ifdef WIN32
  21. status = 0;
  22. hAudioId = 0;
  23. uAudioDelay = 0;
  24. uAudioCount = 0;
  25. uAudioPlay = 16;
  26. hAudioEvent = 0;
  27. uAudioWrite = 0;
  28. uAudioStop = 0;
  29. lAudioDone = 0;
  30. uAudioWrOk = 0;
  31. iAudioThEnd = 0;
  32. linksV = 1;
  33. rechtsV = 1;
  34. #endif
  35. ref = 1;
  36. }
  37. // Destruktor
  38. GSLSound::~GSLSound()
  39. {
  40. #ifdef WIN32
  41. if( status )
  42. stopSound();
  43. #endif
  44. dat->release();
  45. }
  46. // privat
  47. int GSLSound::audioOpen()
  48. {
  49. #ifdef WIN32
  50. WAVEFORMATEX sAudioWm;
  51. sAudioWm.wFormatTag = WAVE_FORMAT_PCM;
  52. sAudioWm.nChannels = kpf.channels;
  53. sAudioWm.nSamplesPerSec = kpf.sampleRate;
  54. sAudioWm.nBlockAlign = ( ( 16 * kpf.channels ) + 7 ) >> 3;
  55. sAudioWm.nAvgBytesPerSec = kpf.sampleRate * sAudioWm.nBlockAlign;
  56. sAudioWm.wBitsPerSample = 16;
  57. sAudioWm.cbSize = 0;
  58. MMRESULT uRes = waveOutOpen( &hAudioId, WAVE_MAPPER, &sAudioWm, (DWORD_PTR)AudioOutProc, 0x00000000, CALLBACK_FUNCTION );
  59. if( uRes || !hAudioId )
  60. {
  61. memset( &sAudioWm, 0, sizeof( sAudioWm ) );
  62. return 1;
  63. }
  64. uAudioDelay = 0;
  65. uAudioWrite = 0;
  66. uAudioStop = 0;
  67. lAudioDone = 0;
  68. for( uAudioCount = 0; uAudioCount < 16; uAudioCount++ )
  69. {
  70. aAudioHdr[ uAudioCount ] = (LPWAVEHDR)GlobalAllocPtr( GMEM_MOVEABLE | GMEM_SHARE, sizeof( WAVEHDR ) + 0x4000 );
  71. if( !aAudioHdr[ uAudioCount ] )
  72. break;
  73. aAudioHdr[ uAudioCount ]->dwFlags = WHDR_DONE;
  74. aAudioHdr[ uAudioCount ]->lpData = (LPSTR)aAudioHdr[ uAudioCount ] + sizeof( WAVEHDR );
  75. aAudioHdr[ uAudioCount ]->dwBufferLength = 0x4000;
  76. aAudioHdr[ uAudioCount ]->dwUser = uAudioCount;
  77. aAudioHdr[ uAudioCount ]->dwBytesRecorded = 0;
  78. aAudioHdr[ uAudioCount ]->dwLoops = 1;
  79. aAudioHdr[ uAudioCount ]->lpNext = 0;
  80. aAudioPtr[ uAudioCount ] = (char*)( aAudioHdr[ uAudioCount ] ) + sizeof( WAVEHDR );
  81. if( !waveOutPrepareHeader( hAudioId, aAudioHdr[ uAudioCount ], sizeof( WAVEHDR ) ) )
  82. continue;
  83. GlobalFreePtr( (LPCVOID)aAudioHdr[ uAudioCount ] );
  84. break;
  85. }
  86. uAudioPlay = uAudioCount - 1;
  87. if( uAudioCount < 12 )
  88. {
  89. audioClose();
  90. return 2;
  91. }
  92. hAudioEvent = CreateEvent( 0, TRUE, TRUE, 0 );
  93. if( !hAudioEvent )
  94. {
  95. audioClose();
  96. return 3;
  97. }
  98. if( waveOutGetDevCaps( (UINT_PTR)hAudioId, (LPWAVEOUTCAPSA)&sAudioCaps, sizeof( WAVEOUTCAPS ) ) )
  99. memset( &sAudioCaps, 0, sizeof( sAudioCaps ) );
  100. waveOutReset( hAudioId );
  101. waveOutSetVolume( hAudioId, 0xFFFFFFFF );
  102. #endif
  103. dat->open( Datei::Style::lesen );
  104. #ifdef WIN32
  105. uAudioWrOk = 1;
  106. #endif
  107. return 0;
  108. }
  109. int GSLSound::audioClose()
  110. {
  111. int iErr = 0;
  112. #ifdef WIN32
  113. if( !hAudioId )
  114. return 1;
  115. audioStop();
  116. while( uAudioCount > 0 )
  117. {
  118. uAudioCount--;
  119. if( waveOutUnprepareHeader( hAudioId, aAudioHdr[ uAudioCount ], sizeof( WAVEHDR ) ) )
  120. iErr = 1;
  121. if( GlobalFreePtr( (LPCVOID)aAudioHdr[ uAudioCount ] ) )
  122. iErr = 1;
  123. aAudioHdr[ uAudioCount ] = 0;
  124. aAudioPtr[ uAudioCount ] = 0;
  125. }
  126. if( waveOutClose( hAudioId ) )
  127. iErr = 1;
  128. if( !CloseHandle( hAudioEvent ) )
  129. iErr = 1;
  130. hAudioId = 0;
  131. uAudioWrite = 0;
  132. uAudioDelay = 0;
  133. uAudioPlay = uAudioCount - 1;
  134. #endif
  135. dat->close();
  136. return iErr;
  137. }
  138. int GSLSound::audioStop()
  139. {
  140. #ifdef WIN32
  141. unsigned uPos;
  142. if( !hAudioId )
  143. return 1;
  144. uAudioStop = 1;
  145. uAudioWrOk = 0;
  146. warteAufThread( 5000 );
  147. SetEvent( hAudioEvent );
  148. waveOutReset( hAudioId );
  149. if( uAudioWrite != 0 && uAudioPlay != uAudioCount - 1 )
  150. {
  151. for( uPos = 0; uPos < uAudioCount; uPos++ ) // clears all buffers
  152. {
  153. memset( aAudioHdr[ uPos ]->lpData, 0, 0x4000 );
  154. break;
  155. }
  156. }
  157. uAudioPlay = uAudioCount - 1;
  158. uAudioWrite = 0;
  159. uAudioDelay = 0;
  160. SetEvent( hAudioEvent );
  161. uAudioWrOk = 1;
  162. if( isRunning() ) // close thread
  163. {
  164. warteAufThread( 1000 );
  165. if( !iAudioThEnd )
  166. {
  167. warteAufThread( 1000 );
  168. if( run )
  169. ende();
  170. Sleep( 100 );
  171. }
  172. }
  173. #endif
  174. return 0;
  175. }
  176. int GSLSound::audioSchreiben( unsigned int uCount )
  177. {
  178. #ifdef WIN32
  179. int iDelta, i, iPos;
  180. WAVEHDR *pHeader;
  181. if( !uAudioWrOk )
  182. return 4;
  183. if( uCount > 0x4000 )
  184. return 2;
  185. if( WaitForSingleObject( hAudioEvent, 2000 ) == WAIT_FAILED )
  186. return 1;
  187. if( uAudioDelay < 8 )
  188. {
  189. aAudioSize[ uAudioDelay ] = uCount;
  190. uAudioDelay++;
  191. hAudioCs.lock(); // increase write pos
  192. uAudioWrite++;
  193. if( uAudioWrite >= uAudioCount )
  194. uAudioWrite = 0;
  195. hAudioCs.unlock();
  196. return 0;
  197. }
  198. if( uAudioDelay == 8 )
  199. {
  200. uAudioDelay++;
  201. for( i = 8; i > 0; i-- )
  202. {
  203. iPos = uAudioWrite - i;
  204. if( iPos < 0 )iPos += uAudioCount;
  205. pHeader = aAudioHdr[ iPos ];
  206. pHeader->dwBufferLength = aAudioSize[ 8 - i ];
  207. if( waveOutWrite( hAudioId, pHeader, sizeof( WAVEHDR ) ) )
  208. return 3;
  209. }
  210. }
  211. pHeader = aAudioHdr[ uAudioWrite ];
  212. pHeader->dwBufferLength = uCount;
  213. if( waveOutWrite( hAudioId, pHeader, sizeof( WAVEHDR ) ) )
  214. return 3;
  215. hAudioCs.lock();
  216. uAudioWrite++;
  217. if( uAudioWrite >= uAudioCount )
  218. uAudioWrite = 0;
  219. iDelta = uAudioPlay - uAudioWrite;
  220. if( iDelta < 0 )
  221. iDelta += uAudioCount;
  222. if( iDelta < 2 )
  223. ResetEvent( hAudioEvent );
  224. hAudioCs.unlock();
  225. #endif
  226. return 0;
  227. }
  228. int GSLSound::audioLesen( char *buff, int len )
  229. {
  230. if( dat->getLPosition() < kpf.datPos )
  231. dat->setLPosition( kpf.datPos, 0 );
  232. if( dat->getLPosition() >= kpf.datEnd )
  233. return -1;
  234. if( dat->getLPosition() + len > kpf.datEnd )
  235. len = (int)( kpf.datEnd - dat->getLPosition() );
  236. if( len > 0 )
  237. dat->lese( buff, len );
  238. #ifdef WIN32
  239. for( int i = 0; i < len; i++, buff++ )
  240. {
  241. if( i % 4 >= 2 )
  242. *buff = (char)( *buff * rechtsV );
  243. else
  244. *buff = (char)( *buff * linksV );
  245. }
  246. #endif
  247. return len;
  248. }
  249. // nicht constant
  250. void GSLSound::playSound()
  251. {
  252. #ifdef WIN32
  253. if( !status )
  254. {
  255. if( _player->addSound( (GSLSound*)getThis() ) )
  256. status = 1;
  257. if( !audioOpen() )
  258. start();
  259. else
  260. {
  261. _player->removeSound( this );
  262. status = 0;
  263. }
  264. }
  265. setPause( 0 );
  266. #endif
  267. }
  268. void GSLSound::setPause( bool p )
  269. {
  270. #ifdef WIN32
  271. if( p )
  272. {
  273. if( !status )
  274. playSound();
  275. if( status == 1 )
  276. {
  277. waveOutPause( hAudioId );
  278. status = 2;
  279. }
  280. }
  281. else
  282. {
  283. if( status == 2 )
  284. {
  285. waveOutRestart( hAudioId );
  286. status = 1;
  287. }
  288. }
  289. #endif
  290. }
  291. void GSLSound::stopSound()
  292. {
  293. #ifdef WIN32
  294. setPause( 0 );
  295. if( status == 1 )
  296. {
  297. status = 0;
  298. _player->removeSound( this );
  299. audioClose();
  300. }
  301. #endif
  302. }
  303. void GSLSound::warteAufSound( int zeit )
  304. {
  305. warteAufThread( zeit );
  306. }
  307. void GSLSound::setVolume( unsigned int links, unsigned int rechts )
  308. {
  309. #ifdef WIN32
  310. linksV = (float)links / 0xFFFF;
  311. rechtsV = (float)rechts / 0xFFFF;
  312. #endif
  313. }
  314. #ifdef WIN32
  315. void GSLSound::msg( UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
  316. {
  317. WAVEHDR *pHeader;
  318. int iDelta;
  319. switch( uMsg )
  320. {
  321. case WOM_DONE:
  322. pHeader = (WAVEHDR*)dwParam1;
  323. hAudioCs.lock();
  324. InterlockedExchangeAdd( (unsigned __int64*)&lAudioDone, (__int64)pHeader->dwBufferLength );
  325. iDelta = (int)( uAudioPlay - pHeader->dwUser );
  326. if( iDelta < 0 )
  327. iDelta += uAudioCount;
  328. if( iDelta > ( (int)uAudioCount >> 1 ) )
  329. {
  330. uAudioPlay = (unsigned int)pHeader->dwUser;
  331. if( uAudioPlay >= uAudioCount )
  332. uAudioPlay = 0;
  333. iDelta = uAudioPlay - uAudioWrite;
  334. if( iDelta < 0 )
  335. iDelta += uAudioCount;
  336. if( iDelta >= 2 )
  337. SetEvent( hAudioEvent );
  338. }
  339. hAudioCs.unlock();
  340. break;
  341. }
  342. }
  343. #endif
  344. void GSLSound::thread()
  345. {
  346. #ifdef WIN32
  347. iAudioThEnd = 0;
  348. uAudioStop = 0;
  349. if( !hAudioId )
  350. return;
  351. int iCount;
  352. while( !uAudioStop && hAudioId )
  353. {
  354. iCount = audioLesen( aAudioPtr[ uAudioWrite ], 0x4000 );
  355. if( iCount <= 0 )
  356. break;
  357. audioSchreiben( iCount );
  358. }
  359. iAudioThEnd = 1;
  360. stopSound();
  361. #endif
  362. run = 0;
  363. }
  364. // zum Speichern
  365. void GSLSound::open()
  366. {
  367. #ifdef WIN32
  368. if( !status )
  369. {
  370. dat->open( Datei::Style::lesen );
  371. status = 3;
  372. }
  373. #else
  374. dat->open( Datei::Style::lesen );
  375. #endif
  376. }
  377. int GSLSound::getDaten( char *buffer, int len )
  378. {
  379. #ifdef WIN32
  380. if( status != 3 )
  381. return -1;
  382. #endif
  383. return audioLesen( buffer, len );
  384. }
  385. void GSLSound::close()
  386. {
  387. #ifdef WIN32
  388. if( status == 3 )
  389. {
  390. dat->close();
  391. status = 0;
  392. }
  393. #else
  394. dat->close();
  395. #endif
  396. }
  397. bool GSLSound::istMono() const
  398. {
  399. return kpf.channels == 1;
  400. }
  401. int GSLSound::getSampleRate() const
  402. {
  403. return kpf.sampleRate;
  404. }
  405. __int64 GSLSound::getDatLength() const
  406. {
  407. return kpf.datEnd - kpf.datPos;
  408. }
  409. // constant
  410. #ifdef WIN32
  411. HWAVEOUT GSLSound::getHandle() const
  412. {
  413. return hAudioId;
  414. }
  415. #endif
  416. // Reference Counting
  417. GSLSoundV *GSLSound::getThis()
  418. {
  419. ref++;
  420. return this;
  421. }
  422. GSLSoundV *GSLSound::release()
  423. {
  424. ref--;
  425. if( !ref )
  426. delete this;
  427. return 0;
  428. }