sound.c 14 KB

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