sound.c 14 KB

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