sound.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
  4. // All rights reserved.
  5. //
  6. // This file is part of SDLPAL.
  7. //
  8. // SDLPAL is free software: you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation, either version 3 of the License, or
  11. // (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. //
  21. #include "palcommon.h"
  22. #include "common.h"
  23. #include "sound.h"
  24. #include "rixplay.h"
  25. #include "util.h"
  26. #ifdef PAL_HAS_NATIVEMIDI
  27. #include "midi.h"
  28. #endif
  29. #ifdef PAL_HAS_MP3
  30. #include "libmad/music_mad.h"
  31. #endif
  32. static BOOL gSndOpened = FALSE;
  33. BOOL g_fNoSound = FALSE;
  34. BOOL g_fNoMusic = FALSE;
  35. #ifdef PAL_HAS_NATIVEMIDI
  36. BOOL g_fUseMidi = FALSE;
  37. #endif
  38. static BOOL g_fUseWav = FALSE;
  39. #ifdef __SYMBIAN32__
  40. INT g_iVolume = SDL_MIX_MAXVOLUME * 0.1;
  41. #endif
  42. typedef struct tagSNDPLAYER
  43. {
  44. FILE *mkf;
  45. SDL_AudioSpec spec;
  46. SDL_mutex *mtx;
  47. LPBYTE buf[2], pos[2];
  48. INT audio_len[2];
  49. #ifdef PAL_HAS_CD
  50. SDL_CD *pCD;
  51. #endif
  52. #ifdef PAL_HAS_MP3
  53. mad_data *pMP3;
  54. BOOL fMP3Loop;
  55. INT iCurrentMP3;
  56. SDL_mutex *lock;
  57. #endif
  58. } SNDPLAYER;
  59. static SNDPLAYER gSndPlayer;
  60. static SDL_AudioSpec *
  61. SOUND_LoadVOCFromBuffer(
  62. LPCBYTE lpVOC,
  63. DWORD dwLen,
  64. SDL_AudioSpec *lpSpec,
  65. LPBYTE *lppBuffer
  66. )
  67. /*++
  68. Purpose:
  69. Load a VOC file in a buffer. Currently supports type 01 block only.
  70. Parameters:
  71. [IN] lpVOC - pointer to the buffer of the VOC file.
  72. [IN] dwLen - length of the buffer of the VOC file.
  73. [OUT] lpSpec - pointer to the SDL_AudioSpec structure, which contains
  74. some basic information about the VOC file.
  75. [OUT] lppBuffer - the output buffer.
  76. Return value:
  77. Pointer to the SDL_AudioSpec structure, NULL if failed.
  78. --*/
  79. {
  80. INT freq, len, x, i, l;
  81. SDL_RWops *rw;
  82. if (g_fUseWav)
  83. {
  84. rw = SDL_RWFromConstMem(lpVOC, dwLen);
  85. if (rw == NULL) return NULL;
  86. len = dwLen;
  87. SDL_LoadWAV_RW(rw, 1, lpSpec, lppBuffer, (Uint32 *)&len);
  88. lpSpec->size = len;
  89. return lpSpec;
  90. }
  91. else
  92. {
  93. //
  94. // Skip header
  95. //
  96. lpVOC += 0x1B;
  97. //
  98. // Length is 3 bytes long
  99. //
  100. len = (lpVOC[0] | (lpVOC[1] << 8) | (lpVOC[2] << 16)) - 2;
  101. lpVOC += 3;
  102. //
  103. // One byte for frequency
  104. //
  105. freq = 1000000 / (256 - *lpVOC);
  106. #if 1
  107. lpVOC += 2;
  108. //
  109. // Convert the sample manually, as SDL doesn't like "strange" sample rates.
  110. //
  111. x = (INT)(len * ((FLOAT)PAL_SAMPLE_RATE / freq));
  112. *lppBuffer = (LPBYTE)calloc(1, x);
  113. if (*lppBuffer == NULL)
  114. {
  115. return NULL;
  116. }
  117. for (i = 0; i < x; i++)
  118. {
  119. l = (INT)(i * (freq / (FLOAT)PAL_SAMPLE_RATE));
  120. if (l >= len)
  121. {
  122. l = len - 1;
  123. }
  124. (*lppBuffer)[i] = lpVOC[l];
  125. }
  126. lpSpec->channels = 1;
  127. lpSpec->format = AUDIO_U8;
  128. lpSpec->freq = PAL_SAMPLE_RATE;
  129. lpSpec->size = x;
  130. #else
  131. *lppBuffer = (unsigned char *)malloc(len);
  132. if (*lppBuffer == NULL)
  133. {
  134. return NULL;
  135. }
  136. lpSpec->channels = 1;
  137. lpSpec->format = AUDIO_U8;
  138. lpSpec->freq = freq;
  139. lpSpec->size = len;
  140. lpVOC += 2;
  141. memcpy(*lppBuffer, lpVOC, len);
  142. #endif
  143. return lpSpec;
  144. }
  145. }
  146. static VOID SDLCALL
  147. SOUND_FillAudio(
  148. LPVOID udata,
  149. LPBYTE stream,
  150. INT len
  151. )
  152. /*++
  153. Purpose:
  154. SDL sound callback function.
  155. Parameters:
  156. [IN] udata - pointer to user-defined parameters (Not used).
  157. [OUT] stream - pointer to the stream buffer.
  158. [IN] len - Length of the buffer.
  159. Return value:
  160. None.
  161. --*/
  162. {
  163. int i;
  164. #if SDL_VERSION_ATLEAST(2,0,0)
  165. memset(stream, 0, len);
  166. #endif
  167. //
  168. // Play music
  169. //
  170. if (!g_fNoMusic)
  171. {
  172. #ifdef PAL_HAS_MP3
  173. SDL_mutexP(gSndPlayer.lock);
  174. if (gSndPlayer.pMP3 != NULL)
  175. {
  176. mad_getSamples(gSndPlayer.pMP3, stream, len);
  177. if (!mad_isPlaying(gSndPlayer.pMP3) && gSndPlayer.fMP3Loop)
  178. {
  179. mad_seek(gSndPlayer.pMP3, 0);
  180. mad_start(gSndPlayer.pMP3);
  181. mad_getSamples(gSndPlayer.pMP3, stream, len);
  182. }
  183. }
  184. SDL_mutexV(gSndPlayer.lock);
  185. #endif
  186. RIX_FillBuffer(stream, len);
  187. }
  188. //
  189. // No current playing sound
  190. //
  191. if (g_fNoSound)
  192. {
  193. return;
  194. }
  195. SDL_mutexP(gSndPlayer.mtx);
  196. for (i = 0; i < 2; i++)
  197. {
  198. //
  199. // Only play if we have data left
  200. //
  201. if (gSndPlayer.buf[i] == NULL)
  202. {
  203. continue;
  204. }
  205. if (gSndPlayer.audio_len[i] == 0)
  206. {
  207. //
  208. // Delete the audio buffer from memory
  209. //
  210. free(gSndPlayer.buf[i]);
  211. gSndPlayer.buf[i] = NULL;
  212. continue;
  213. }
  214. //
  215. // Mix as much data as possible
  216. //
  217. len = (len > gSndPlayer.audio_len[i]) ? gSndPlayer.audio_len[i] : len;
  218. #ifdef __SYMBIAN32__
  219. SDL_MixAudio(stream, gSndPlayer.pos[i], len, g_iVolume);
  220. #else
  221. SDL_MixAudio(stream, gSndPlayer.pos[i], len, SDL_MIX_MAXVOLUME * 2 / 3);
  222. #endif
  223. gSndPlayer.pos[i] += len;
  224. gSndPlayer.audio_len[i] -= len;
  225. }
  226. SDL_mutexV(gSndPlayer.mtx);
  227. }
  228. INT
  229. SOUND_OpenAudio(
  230. VOID
  231. )
  232. /*++
  233. Purpose:
  234. Initialize the audio subsystem.
  235. Parameters:
  236. None.
  237. Return value:
  238. 0 if succeed, others if failed.
  239. --*/
  240. {
  241. SDL_AudioSpec spec;
  242. if (gSndOpened)
  243. {
  244. //
  245. // Already opened
  246. //
  247. return -1;
  248. }
  249. gSndOpened = FALSE;
  250. //
  251. // Load the MKF file.
  252. //
  253. gSndPlayer.mkf = UTIL_OpenFile("voc.mkf");
  254. if (gSndPlayer.mkf == NULL)
  255. {
  256. gSndPlayer.mkf = UTIL_OpenFile("sounds.mkf");
  257. if (gSndPlayer.mkf == NULL)
  258. {
  259. return -2;
  260. }
  261. g_fUseWav = TRUE;
  262. }
  263. else
  264. {
  265. g_fUseWav = FALSE;
  266. }
  267. //
  268. // Open the sound subsystem.
  269. //
  270. gSndPlayer.spec.freq = PAL_SAMPLE_RATE;
  271. gSndPlayer.spec.format = AUDIO_S16;
  272. gSndPlayer.spec.channels = PAL_CHANNELS;
  273. gSndPlayer.spec.samples = 1024;
  274. gSndPlayer.spec.callback = SOUND_FillAudio;
  275. if (SDL_OpenAudio(&gSndPlayer.spec, &spec) < 0)
  276. {
  277. //
  278. // Failed
  279. //
  280. return -3;
  281. }
  282. memcpy(&gSndPlayer.spec, &spec, sizeof(SDL_AudioSpec));
  283. gSndPlayer.buf[0] = NULL;
  284. gSndPlayer.pos[0] = NULL;
  285. gSndPlayer.audio_len[0] = 0;
  286. gSndPlayer.buf[1] = NULL;
  287. gSndPlayer.pos[1] = NULL;
  288. gSndPlayer.audio_len[1] = 0;
  289. gSndPlayer.mtx = SDL_CreateMutex();
  290. gSndOpened = TRUE;
  291. //
  292. // Initialize the music subsystem.
  293. //
  294. RIX_Init(va("%s%s", PAL_PREFIX, "mus.mkf"));
  295. #ifdef PAL_HAS_CD
  296. //
  297. // Initialize the CD audio.
  298. //
  299. {
  300. int i;
  301. gSndPlayer.pCD = NULL;
  302. for (i = 0; i < SDL_CDNumDrives(); i++)
  303. {
  304. gSndPlayer.pCD = SDL_CDOpen(i);
  305. if (gSndPlayer.pCD != NULL)
  306. {
  307. if (!CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  308. {
  309. SDL_CDClose(gSndPlayer.pCD);
  310. gSndPlayer.pCD = NULL;
  311. }
  312. else
  313. {
  314. break;
  315. }
  316. }
  317. }
  318. }
  319. #endif
  320. #ifdef PAL_HAS_MP3
  321. gSndPlayer.iCurrentMP3 = -1;
  322. gSndPlayer.lock = SDL_CreateMutex();
  323. #endif
  324. //
  325. // Let the callback function run so that musics will be played.
  326. //
  327. SDL_PauseAudio(0);
  328. return 0;
  329. }
  330. #ifdef PSP
  331. void
  332. SOUND_ReloadVOC(
  333. void
  334. )
  335. {
  336. fclose(gSndPlayer.mkf);
  337. gSndPlayer.mkf = UTIL_OpenFile("voc.mkf");
  338. g_fUseWav = FALSE;
  339. }
  340. #endif
  341. VOID
  342. SOUND_CloseAudio(
  343. VOID
  344. )
  345. /*++
  346. Purpose:
  347. Close the audio subsystem.
  348. Parameters:
  349. None.
  350. Return value:
  351. None.
  352. --*/
  353. {
  354. SDL_mutexP(gSndPlayer.mtx);
  355. SDL_CloseAudio();
  356. if (gSndPlayer.buf[0] != NULL)
  357. {
  358. free(gSndPlayer.buf[0]);
  359. gSndPlayer.buf[0] = NULL;
  360. }
  361. if (gSndPlayer.buf[1] != NULL)
  362. {
  363. free(gSndPlayer.buf[1]);
  364. gSndPlayer.buf[1] = NULL;
  365. }
  366. if (gSndPlayer.mkf != NULL)
  367. {
  368. fclose(gSndPlayer.mkf);
  369. gSndPlayer.mkf = NULL;
  370. }
  371. SDL_DestroyMutex(gSndPlayer.mtx);
  372. #ifdef PAL_HAS_MP3
  373. SDL_mutexP(gSndPlayer.lock);
  374. if (gSndPlayer.pMP3 != NULL)
  375. {
  376. mad_stop(gSndPlayer.pMP3);
  377. mad_closeFile(gSndPlayer.pMP3);
  378. gSndPlayer.pMP3 = NULL;
  379. }
  380. SDL_DestroyMutex(gSndPlayer.lock);
  381. #endif
  382. RIX_Shutdown();
  383. #ifdef PAL_HAS_CD
  384. if (gSndPlayer.pCD != NULL)
  385. {
  386. SOUND_PlayCDA(-1);
  387. SDL_CDClose(gSndPlayer.pCD);
  388. }
  389. #endif
  390. #ifdef PAL_HAS_NATIVEMIDI
  391. MIDI_Play(0, FALSE);
  392. #endif
  393. }
  394. #ifdef __SYMBIAN32__
  395. VOID
  396. SOUND_AdjustVolume(
  397. INT iDirectory
  398. )
  399. /*++
  400. Purpose:
  401. SDL sound volume adjust function.
  402. Parameters:
  403. [IN] iDirectory - value, Increase (>0) or decrease (<=0) 3% volume.
  404. Return value:
  405. None.
  406. --*/
  407. {
  408. if (iDirectory > 0)
  409. {
  410. if (g_iVolume <= SDL_MIX_MAXVOLUME)
  411. {
  412. g_iVolume += SDL_MIX_MAXVOLUME * 0.03;
  413. }
  414. else
  415. {
  416. g_iVolume = SDL_MIX_MAXVOLUME;
  417. }
  418. }
  419. else
  420. {
  421. if (g_iVolume > 0)
  422. {
  423. g_iVolume -= SDL_MIX_MAXVOLUME * 0.03;
  424. }
  425. else
  426. {
  427. g_iVolume = 0;
  428. }
  429. }
  430. }
  431. #endif
  432. VOID
  433. SOUND_PlayChannel(
  434. INT iSoundNum,
  435. INT iChannel
  436. )
  437. /*++
  438. Purpose:
  439. Play a sound in voc.mkf file.
  440. Parameters:
  441. [IN] iSoundNum - number of the sound.
  442. [IN] iChannel - the number of channel (0 or 1).
  443. Return value:
  444. None.
  445. --*/
  446. {
  447. SDL_AudioCVT wavecvt;
  448. SDL_AudioSpec wavespec;
  449. LPBYTE buf, bufdec;
  450. UINT samplesize;
  451. int len;
  452. if (!gSndOpened || g_fNoSound)
  453. {
  454. return;
  455. }
  456. //
  457. // Stop playing current sound.
  458. //
  459. SDL_mutexP(gSndPlayer.mtx);
  460. if (gSndPlayer.buf[iChannel] != NULL)
  461. {
  462. LPBYTE p = gSndPlayer.buf[iChannel];
  463. gSndPlayer.buf[iChannel] = NULL;
  464. free(p);
  465. }
  466. SDL_mutexV(gSndPlayer.mtx);
  467. if (iSoundNum < 0)
  468. {
  469. return;
  470. }
  471. //
  472. // Get the length of the sound file.
  473. //
  474. len = PAL_MKFGetChunkSize(iSoundNum, gSndPlayer.mkf);
  475. if (len <= 0)
  476. {
  477. return;
  478. }
  479. buf = (LPBYTE)calloc(len, 1);
  480. if (buf == NULL)
  481. {
  482. return;
  483. }
  484. //
  485. // Read the sound file from the MKF archive.
  486. //
  487. PAL_MKFReadChunk(buf, len, iSoundNum, gSndPlayer.mkf);
  488. SOUND_LoadVOCFromBuffer(buf, len, &wavespec, &bufdec);
  489. free(buf);
  490. //
  491. // Build the audio converter and create conversion buffers
  492. //
  493. if (SDL_BuildAudioCVT(&wavecvt, wavespec.format, wavespec.channels, wavespec.freq,
  494. gSndPlayer.spec.format, gSndPlayer.spec.channels, gSndPlayer.spec.freq) < 0)
  495. {
  496. free(bufdec);
  497. return;
  498. }
  499. samplesize = ((wavespec.format & 0xFF) / 8) * wavespec.channels;
  500. wavecvt.len = wavespec.size & ~(samplesize - 1);
  501. wavecvt.buf = (LPBYTE)malloc(wavecvt.len * wavecvt.len_mult);
  502. if (wavecvt.buf == NULL)
  503. {
  504. free(bufdec);
  505. return;
  506. }
  507. memcpy(wavecvt.buf, bufdec, wavespec.size);
  508. if (g_fUseWav)
  509. {
  510. SDL_FreeWAV(bufdec);
  511. }
  512. else
  513. {
  514. free(bufdec);
  515. }
  516. //
  517. // Run the audio converter
  518. //
  519. if (SDL_ConvertAudio(&wavecvt) < 0)
  520. {
  521. return;
  522. }
  523. SDL_mutexP(gSndPlayer.mtx);
  524. if (gSndPlayer.buf[iChannel] != NULL)
  525. {
  526. LPBYTE p = gSndPlayer.buf[iChannel];
  527. gSndPlayer.buf[iChannel] = NULL;
  528. free(p);
  529. }
  530. gSndPlayer.buf[iChannel] = wavecvt.buf;
  531. gSndPlayer.audio_len[iChannel] = wavecvt.len * wavecvt.len_mult;
  532. gSndPlayer.pos[iChannel] = wavecvt.buf;
  533. SDL_mutexV(gSndPlayer.mtx);
  534. }
  535. VOID
  536. PAL_PlayMUS(
  537. INT iNumRIX,
  538. BOOL fLoop,
  539. FLOAT flFadeTime
  540. )
  541. {
  542. #ifdef PAL_HAS_NATIVEMIDI
  543. if (g_fUseMidi)
  544. {
  545. MIDI_Play(iNumRIX, fLoop);
  546. return;
  547. }
  548. #endif
  549. #ifdef PAL_HAS_MP3
  550. SDL_mutexP(gSndPlayer.lock);
  551. if (gSndPlayer.pMP3 != NULL)
  552. {
  553. if (iNumRIX == gSndPlayer.iCurrentMP3 && !g_fNoMusic)
  554. {
  555. SDL_mutexV(gSndPlayer.lock);
  556. return;
  557. }
  558. mad_stop(gSndPlayer.pMP3);
  559. mad_closeFile(gSndPlayer.pMP3);
  560. gSndPlayer.pMP3 = NULL;
  561. }
  562. SDL_mutexV(gSndPlayer.lock);
  563. gSndPlayer.iCurrentMP3 = -1;
  564. if (iNumRIX > 0)
  565. {
  566. SDL_mutexP(gSndPlayer.lock);
  567. gSndPlayer.pMP3 = mad_openFile(va("%s/mp3/%.2d.mp3", PAL_PREFIX, iNumRIX), &gSndPlayer.spec);
  568. if (gSndPlayer.pMP3 != NULL)
  569. {
  570. RIX_Play(0, FALSE, flFadeTime);
  571. mad_start(gSndPlayer.pMP3);
  572. gSndPlayer.fMP3Loop = fLoop;
  573. gSndPlayer.iCurrentMP3 = iNumRIX;
  574. SDL_mutexV(gSndPlayer.lock);
  575. return;
  576. }
  577. SDL_mutexV(gSndPlayer.lock);
  578. }
  579. #endif
  580. RIX_Play(iNumRIX, fLoop, flFadeTime);
  581. }
  582. BOOL
  583. SOUND_PlayCDA(
  584. INT iNumTrack
  585. )
  586. /*++
  587. Purpose:
  588. Play a CD Audio Track.
  589. Parameters:
  590. [IN] iNumTrack - number of the CD Audio Track.
  591. Return value:
  592. TRUE if the track can be played, FALSE if not.
  593. --*/
  594. {
  595. #ifdef PAL_HAS_CD
  596. if (gSndPlayer.pCD != NULL)
  597. {
  598. if (CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  599. {
  600. SDL_CDStop(gSndPlayer.pCD);
  601. if (iNumTrack != -1)
  602. {
  603. PAL_PlayMUS(-1, FALSE, 0);
  604. if (SDL_CDPlayTracks(gSndPlayer.pCD, iNumTrack - 1, 0, 1, 0) == 0)
  605. {
  606. return TRUE;
  607. }
  608. }
  609. }
  610. }
  611. #endif
  612. return FALSE;
  613. }