Sound.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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. {
  16. kpf = skpf;
  17. dat = new Datei();
  18. dat->setDatei( kpf.pfad );
  19. #ifdef WIN32
  20. status = 0;
  21. hAudioId = 0;
  22. uAudioDelay = 0;
  23. uAudioCount = 0;
  24. uAudioPlay = 16;
  25. hAudioCs = { 0 };
  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. InitializeCriticalSection( &hAudioCs );
  101. waveOutReset( hAudioId );
  102. waveOutSetVolume( hAudioId, 0xFFFFFFFF );
  103. #endif
  104. dat->open( Datei::Style::lesen );
  105. #ifdef WIN32
  106. uAudioWrOk = 1;
  107. #endif
  108. return 0;
  109. }
  110. int GSLSound::audioClose()
  111. {
  112. int iErr = 0;
  113. #ifdef WIN32
  114. if( !hAudioId )
  115. return 1;
  116. audioStop();
  117. DeleteCriticalSection( &hAudioCs );
  118. while( uAudioCount > 0 )
  119. {
  120. uAudioCount--;
  121. if( waveOutUnprepareHeader( hAudioId, aAudioHdr[ uAudioCount ], sizeof( WAVEHDR ) ) )
  122. iErr = 1;
  123. if( GlobalFreePtr( (LPCVOID)aAudioHdr[ uAudioCount ] ) )
  124. iErr = 1;
  125. aAudioHdr[ uAudioCount ] = 0;
  126. aAudioPtr[ uAudioCount ] = 0;
  127. }
  128. if( waveOutClose( hAudioId ) )
  129. iErr = 1;
  130. if( !CloseHandle( hAudioEvent ) )
  131. iErr = 1;
  132. hAudioId = 0;
  133. uAudioWrite = 0;
  134. uAudioDelay = 0;
  135. uAudioPlay = uAudioCount - 1;
  136. #endif
  137. dat->close();
  138. return iErr;
  139. }
  140. int GSLSound::audioStop()
  141. {
  142. #ifdef WIN32
  143. unsigned uPos;
  144. if( !hAudioId )
  145. return 1;
  146. uAudioStop = 1;
  147. uAudioWrOk = 0;
  148. warteAufThread( 5000 );
  149. SetEvent( hAudioEvent );
  150. waveOutReset( hAudioId );
  151. if( uAudioWrite != 0 && uAudioPlay != uAudioCount - 1 )
  152. {
  153. for( uPos = 0; uPos < uAudioCount; uPos++ ) // clears all buffers
  154. {
  155. memset( aAudioHdr[ uPos ]->lpData, 0, 0x4000 );
  156. break;
  157. }
  158. }
  159. uAudioPlay = uAudioCount - 1;
  160. uAudioWrite = 0;
  161. uAudioDelay = 0;
  162. SetEvent( hAudioEvent );
  163. uAudioWrOk = 1;
  164. if( isRunning() ) // close thread
  165. {
  166. warteAufThread( 1000 );
  167. if( !iAudioThEnd )
  168. {
  169. warteAufThread( 1000 );
  170. if( run )
  171. ende();
  172. Sleep( 100 );
  173. }
  174. }
  175. #endif
  176. return 0;
  177. }
  178. int GSLSound::audioSchreiben( unsigned int uCount )
  179. {
  180. #ifdef WIN32
  181. int iDelta, i, iPos;
  182. WAVEHDR *pHeader;
  183. if( !uAudioWrOk )
  184. return 4;
  185. if( uCount > 0x4000 )
  186. return 2;
  187. if( WaitForSingleObject( hAudioEvent, 2000 ) == WAIT_FAILED )
  188. return 1;
  189. if( uAudioDelay < 8 )
  190. {
  191. aAudioSize[ uAudioDelay ] = uCount;
  192. uAudioDelay++;
  193. EnterCriticalSection( &hAudioCs ); // increase write pos
  194. uAudioWrite++;
  195. if( uAudioWrite >= uAudioCount )
  196. uAudioWrite = 0;
  197. LeaveCriticalSection( &hAudioCs );
  198. return 0;
  199. }
  200. if( uAudioDelay == 8 )
  201. {
  202. uAudioDelay++;
  203. for( i = 8; i > 0; i-- )
  204. {
  205. iPos = uAudioWrite - i;
  206. if( iPos < 0 )iPos += uAudioCount;
  207. pHeader = aAudioHdr[ iPos ];
  208. pHeader->dwBufferLength = aAudioSize[ 8 - i ];
  209. if( waveOutWrite( hAudioId, pHeader, sizeof( WAVEHDR ) ) )
  210. return 3;
  211. }
  212. }
  213. pHeader = aAudioHdr[ uAudioWrite ];
  214. pHeader->dwBufferLength = uCount;
  215. if( waveOutWrite( hAudioId, pHeader, sizeof( WAVEHDR ) ) )
  216. return 3;
  217. EnterCriticalSection( &hAudioCs );
  218. uAudioWrite++;
  219. if( uAudioWrite >= uAudioCount )
  220. uAudioWrite = 0;
  221. iDelta = uAudioPlay - uAudioWrite;
  222. if( iDelta < 0 )
  223. iDelta += uAudioCount;
  224. if( iDelta < 2 )
  225. ResetEvent( hAudioEvent );
  226. LeaveCriticalSection( &hAudioCs );
  227. #endif
  228. return 0;
  229. }
  230. int GSLSound::audioLesen( char *buff, int len )
  231. {
  232. if( dat->getLPosition() < kpf.datPos )
  233. dat->setLPosition( kpf.datPos, 0 );
  234. if( dat->getLPosition() >= kpf.datEnd )
  235. return -1;
  236. if( dat->getLPosition() + len > kpf.datEnd )
  237. len = (int)( kpf.datEnd - dat->getLPosition() );
  238. if( len > 0 )
  239. dat->lese( buff, len );
  240. #ifdef WIN32
  241. for( int i = 0; i < len; i++, buff++ )
  242. {
  243. if( i % 4 >= 2 )
  244. *buff = (char)( *buff * rechtsV );
  245. else
  246. *buff = (char)( *buff * linksV );
  247. }
  248. #endif
  249. return len;
  250. }
  251. // nicht constant
  252. void GSLSound::playSound()
  253. {
  254. #ifdef WIN32
  255. if( !status )
  256. {
  257. if( _player->addSound( (GSLSound*)getThis() ) )
  258. status = 1;
  259. if( !audioOpen() )
  260. start();
  261. else
  262. {
  263. _player->removeSound( this );
  264. status = 0;
  265. }
  266. }
  267. setPause( 0 );
  268. #endif
  269. }
  270. void GSLSound::setPause( bool p )
  271. {
  272. #ifdef WIN32
  273. if( p )
  274. {
  275. if( !status )
  276. playSound();
  277. if( status == 1 )
  278. {
  279. waveOutPause( hAudioId );
  280. status = 2;
  281. }
  282. }
  283. else
  284. {
  285. if( status == 2 )
  286. {
  287. waveOutRestart( hAudioId );
  288. status = 1;
  289. }
  290. }
  291. #endif
  292. }
  293. void GSLSound::stopSound()
  294. {
  295. #ifdef WIN32
  296. setPause( 0 );
  297. if( status == 1 )
  298. {
  299. status = 0;
  300. _player->removeSound( this );
  301. audioClose();
  302. }
  303. #endif
  304. }
  305. void GSLSound::warteAufSound( int zeit )
  306. {
  307. warteAufThread( zeit );
  308. }
  309. void GSLSound::setVolume( unsigned int links, unsigned int rechts )
  310. {
  311. #ifdef WIN32
  312. linksV = (float)links / 0xFFFF;
  313. rechtsV = (float)rechts / 0xFFFF;
  314. #endif
  315. }
  316. #ifdef WIN32
  317. void GSLSound::msg( UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
  318. {
  319. WAVEHDR *pHeader;
  320. int iDelta;
  321. switch( uMsg )
  322. {
  323. case WOM_DONE:
  324. pHeader = (WAVEHDR*)dwParam1;
  325. EnterCriticalSection( &hAudioCs );
  326. InterlockedExchangeAdd( (unsigned __int64*)&lAudioDone, (__int64)pHeader->dwBufferLength );
  327. iDelta = (int)( uAudioPlay - pHeader->dwUser );
  328. if( iDelta < 0 )
  329. iDelta += uAudioCount;
  330. if( iDelta > ( (int)uAudioCount >> 1 ) )
  331. {
  332. uAudioPlay = (unsigned int)pHeader->dwUser;
  333. if( uAudioPlay >= uAudioCount )
  334. uAudioPlay = 0;
  335. iDelta = uAudioPlay - uAudioWrite;
  336. if( iDelta < 0 )
  337. iDelta += uAudioCount;
  338. if( iDelta >= 2 )
  339. SetEvent( hAudioEvent );
  340. }
  341. LeaveCriticalSection( &hAudioCs );
  342. break;
  343. }
  344. }
  345. #endif
  346. void GSLSound::thread()
  347. {
  348. #ifdef WIN32
  349. iAudioThEnd = 0;
  350. uAudioStop = 0;
  351. if( !hAudioId )
  352. return;
  353. int iCount;
  354. while( !uAudioStop && hAudioId )
  355. {
  356. iCount = audioLesen( aAudioPtr[ uAudioWrite ], 0x4000 );
  357. if( iCount <= 0 )
  358. break;
  359. audioSchreiben( iCount );
  360. }
  361. iAudioThEnd = 1;
  362. stopSound();
  363. #endif
  364. run = 0;
  365. }
  366. // zum Speichern
  367. void GSLSound::open()
  368. {
  369. #ifdef WIN32
  370. if( !status )
  371. {
  372. dat->open( Datei::Style::lesen );
  373. status = 3;
  374. }
  375. #else
  376. dat->open( Datei::Style::lesen );
  377. #endif
  378. }
  379. int GSLSound::getDaten( char *buffer, int len )
  380. {
  381. #ifdef WIN32
  382. if( status != 3 )
  383. return -1;
  384. #endif
  385. return audioLesen( buffer, len );
  386. }
  387. void GSLSound::close()
  388. {
  389. #ifdef WIN32
  390. if( status == 3 )
  391. {
  392. dat->close();
  393. status = 0;
  394. }
  395. #else
  396. dat->close();
  397. #endif
  398. }
  399. bool GSLSound::istMono() const
  400. {
  401. return kpf.channels == 1;
  402. }
  403. int GSLSound::getSampleRate() const
  404. {
  405. return kpf.sampleRate;
  406. }
  407. __int64 GSLSound::getDatLength() const
  408. {
  409. return kpf.datEnd - kpf.datPos;
  410. }
  411. // constant
  412. #ifdef WIN32
  413. HWAVEOUT GSLSound::getHandle() const
  414. {
  415. return hAudioId;
  416. }
  417. #endif
  418. // Reference Counting
  419. GSLSoundV *GSLSound::getThis()
  420. {
  421. ref++;
  422. return this;
  423. }
  424. GSLSoundV *GSLSound::release()
  425. {
  426. ref--;
  427. if( !ref )
  428. delete this;
  429. return 0;
  430. }