sound.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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 "global.h"
  23. #include "sound.h"
  24. #include "players.h"
  25. #include "util.h"
  26. #include "resampler.h"
  27. #include <math.h>
  28. #ifdef PAL_HAS_NATIVEMIDI
  29. #include "midi.h"
  30. #endif
  31. #if PAL_HAS_OGG
  32. #include <vorbis/codec.h>
  33. #endif
  34. static BOOL gSndOpened = FALSE;
  35. BOOL g_fNoSound = FALSE;
  36. BOOL g_fNoMusic = FALSE;
  37. #ifdef __SYMBIAN32__
  38. INT g_iVolume = SDL_MIX_MAXVOLUME * 0.1;
  39. #endif
  40. #ifdef PAL_CLASSIC
  41. int g_iCurrChannel = 0;
  42. #endif
  43. #define PAL_CDTRACK_BASE 10000
  44. typedef LPCBYTE(*FNLoadSoundData)(LPCBYTE, DWORD, SDL_AudioSpec *);
  45. typedef struct tagSNDPLAYER
  46. {
  47. FILE *mkf;
  48. SDL_AudioSpec spec;
  49. SDL_mutex *mtx;
  50. LPBYTE buf[2], pos[2];
  51. INT audio_len[2];
  52. void *resampler;
  53. MUSICPLAYER *pMusPlayer;
  54. MUSICPLAYER *pCDPlayer;
  55. #if PAL_HAS_SDLCD
  56. SDL_CD *pCD;
  57. #endif
  58. FNLoadSoundData LoadSoundData;
  59. } SNDPLAYER;
  60. static SNDPLAYER gSndPlayer;
  61. typedef struct tagRIFFHEADER
  62. {
  63. DWORD riff_sig; /* 'RIFF' */
  64. DWORD data_length; /* Total length minus eight, little-endian */
  65. DWORD riff_type; /* 'WAVE' */
  66. } RIFFHEADER, *LPRIFFHEADER;
  67. typedef const RIFFHEADER *LPCRIFFHEADER;
  68. typedef struct tagRIFFCHUNK
  69. {
  70. DWORD chunk_type; /* 'fmt ' and so on */
  71. DWORD chunk_length; /* Total chunk length minus eight, little-endian */
  72. } RIFFCHUNK, *LPRIFFCHUNK;
  73. typedef const RIFFCHUNK *LPCRIFFCHUNK;
  74. typedef struct tagWAVEFORMATPCM
  75. {
  76. WORD wFormatTag; /* format type */
  77. WORD nChannels; /* number of channels (i.e. mono, stereo, etc.) */
  78. DWORD nSamplesPerSec; /* sample rate */
  79. DWORD nAvgBytesPerSec; /* for buffer estimation */
  80. WORD nBlockAlign; /* block size of data */
  81. WORD wBitsPerSample;
  82. } WAVEFORMATPCM, *LPWAVEFORMATPCM;
  83. typedef const WAVEFORMATPCM *LPCWAVEFORMATPCM;
  84. static LPCBYTE
  85. SOUND_LoadWAVEData(
  86. LPCBYTE lpData,
  87. DWORD dwLen,
  88. SDL_AudioSpec *lpSpec
  89. )
  90. /*++
  91. Purpose:
  92. Return the WAVE data pointer inside the input buffer.
  93. Parameters:
  94. [IN] lpData - pointer to the buffer of the WAVE file.
  95. [IN] dwLen - length of the buffer of the WAVE file.
  96. [OUT] lpSpec - pointer to the SDL_AudioSpec structure, which contains
  97. some basic information about the WAVE file.
  98. Return value:
  99. Pointer to the WAVE data inside the input buffer, NULL if failed.
  100. --*/
  101. {
  102. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  103. # define RIFF 'RIFF'
  104. # define WAVE 'WAVE'
  105. # define FMT 'fmt '
  106. # define DATA 'data'
  107. # define PCM 0x0100
  108. #else
  109. # define RIFF 'FFIR'
  110. # define WAVE 'EVAW'
  111. # define FMT ' tmf'
  112. # define DATA 'atad'
  113. # define PCM 0x0001
  114. #endif
  115. LPCRIFFHEADER lpRiff = (LPCRIFFHEADER)lpData;
  116. LPCRIFFCHUNK lpChunk;
  117. LPCWAVEFORMATPCM lpFormat = NULL;
  118. LPCBYTE lpWaveData = NULL;
  119. DWORD len;
  120. if (dwLen < sizeof(RIFFHEADER) || lpRiff->riff_sig != RIFF || lpRiff->riff_type != WAVE || dwLen < SDL_SwapLE32(lpRiff->data_length) + 8)
  121. {
  122. return NULL;
  123. }
  124. lpChunk = (LPCRIFFCHUNK)(lpRiff + 1); dwLen -= sizeof(RIFFHEADER);
  125. while (dwLen >= sizeof(RIFFCHUNK))
  126. {
  127. len = SDL_SwapLE32(lpChunk->chunk_length);
  128. if (dwLen >= sizeof(RIFFCHUNK) + len)
  129. dwLen -= sizeof(RIFFCHUNK) + len;
  130. else
  131. return NULL;
  132. switch (lpChunk->chunk_type)
  133. {
  134. case FMT:
  135. lpFormat = (LPCWAVEFORMATPCM)(lpChunk + 1);
  136. if (len != sizeof(WAVEFORMATPCM) || lpFormat->wFormatTag != PCM)
  137. {
  138. return NULL;
  139. }
  140. break;
  141. case DATA:
  142. lpWaveData = (LPCBYTE)(lpChunk + 1);
  143. dwLen = 0;
  144. break;
  145. }
  146. lpChunk = (LPCRIFFCHUNK)((LPCBYTE)(lpChunk + 1) + len);
  147. }
  148. if (lpFormat == NULL || lpWaveData == NULL)
  149. {
  150. return NULL;
  151. }
  152. lpSpec->channels = lpFormat->nChannels;
  153. lpSpec->format = (lpFormat->wBitsPerSample == 16) ? AUDIO_S16 : AUDIO_U8;
  154. lpSpec->freq = lpFormat->nSamplesPerSec;
  155. lpSpec->size = len;
  156. return lpWaveData;
  157. #undef RIFF
  158. #undef WAVE
  159. #undef FMT
  160. }
  161. typedef struct tagVOCHEADER
  162. {
  163. char signature[0x14]; /* "Creative Voice File\x1A" */
  164. WORD data_offset; /* little endian */
  165. WORD version;
  166. WORD version_checksum;
  167. } VOCHEADER, *LPVOCHEADER;
  168. typedef const VOCHEADER *LPCVOCHEADER;
  169. static LPCBYTE
  170. SOUND_LoadVOCData(
  171. LPCBYTE lpData,
  172. DWORD dwLen,
  173. SDL_AudioSpec *lpSpec
  174. )
  175. /*++
  176. Purpose:
  177. Return the VOC data pointer inside the input buffer. Currently supports type 01 block only.
  178. Parameters:
  179. [IN] lpData - pointer to the buffer of the VOC file.
  180. [IN] dwLen - length of the buffer of the VOC file.
  181. [OUT] lpSpec - pointer to the SDL_AudioSpec structure, which contains
  182. some basic information about the VOC file.
  183. Return value:
  184. Pointer to the WAVE data inside the input buffer, NULL if failed.
  185. Reference: http://sox.sourceforge.net/AudioFormats-11.html
  186. --*/
  187. {
  188. LPCVOCHEADER lpVOC = (LPCVOCHEADER)lpData;
  189. if (dwLen < sizeof(VOCHEADER) || memcmp(lpVOC->signature, "Creative Voice File\x1A", 0x14) || SDL_SwapLE16(lpVOC->data_offset) >= dwLen)
  190. {
  191. return NULL;
  192. }
  193. lpData += SDL_SwapLE16(lpVOC->data_offset);
  194. dwLen -= SDL_SwapLE16(lpVOC->data_offset);
  195. while (dwLen && *lpData)
  196. {
  197. DWORD len;
  198. if (dwLen >= 4)
  199. {
  200. len = lpData[1] | (lpData[2] << 8) | (lpData[3] << 16);
  201. if (dwLen >= len + 4)
  202. dwLen -= len + 4;
  203. else
  204. return NULL;
  205. }
  206. else
  207. {
  208. return NULL;
  209. }
  210. if (*lpData == 0x01)
  211. {
  212. if (lpData[5] != 0) return NULL; /* Only 8-bit is supported */
  213. lpSpec->format = AUDIO_U8;
  214. lpSpec->channels = 1;
  215. lpSpec->freq = ((1000000 / (256 - lpData[4]) + 99) / 100) * 100; /* Round to next 100Hz */
  216. lpSpec->size = len - 2;
  217. return lpData + 6;
  218. }
  219. else
  220. {
  221. lpData += len + 4;
  222. }
  223. }
  224. return NULL;
  225. }
  226. static void
  227. SOUND_ResampleU8(
  228. LPCBYTE lpData,
  229. const SDL_AudioSpec *lpSpec,
  230. LPBYTE lpBuffer,
  231. DWORD dwLen,
  232. void *resampler
  233. )
  234. /*++
  235. Purpose:
  236. Resample 8-bit unsigned PCM data into 16-bit signed (little-endian) PCM data.
  237. Parameters:
  238. [IN] lpData - pointer to the buffer of the input PCM data.
  239. [IN] lpSpec - pointer to the SDL_AudioSpec structure, which contains
  240. some basic information about the input PCM data.
  241. [IN] lpBuffer - pointer of the buffer of the output PCM data.
  242. [IN] dwLen - length of the buffer of the output PCM data, should be exactly
  243. the number of bytes needed of the resampled data.
  244. [IN] resampler - pointer of the resampler instance.
  245. Return value:
  246. None.
  247. --*/
  248. {
  249. int src_samples = lpSpec->size / lpSpec->channels, i;
  250. for (i = 0; i < lpSpec->channels; i++)
  251. {
  252. LPCBYTE src = lpData + i;
  253. short *dst = (short *)lpBuffer + i;
  254. int channel_len = dwLen / lpSpec->channels, total_bytes = 0;
  255. resampler_clear(resampler);
  256. while (total_bytes < channel_len && src_samples > 0)
  257. {
  258. int to_write, j;
  259. to_write = resampler_get_free_count(resampler);
  260. if (to_write > src_samples) to_write = src_samples;
  261. for (j = 0; j < to_write; j++)
  262. {
  263. resampler_write_sample(resampler, (*src ^ 0x80) << 8);
  264. src += lpSpec->channels;
  265. }
  266. src_samples -= to_write;
  267. while (total_bytes < channel_len && resampler_get_sample_count(resampler) > 0)
  268. {
  269. *dst = SDL_SwapLE16(resampler_get_and_remove_sample(resampler));
  270. dst += lpSpec->channels; total_bytes += (SDL_AUDIO_BITSIZE(AUDIO_S16) >> 3);
  271. }
  272. }
  273. /* Flush resampler's output buffer */
  274. while (total_bytes < channel_len)
  275. {
  276. int j, to_write = resampler_get_free_count(resampler);
  277. for (j = 0; j < to_write; j++)
  278. resampler_write_sample(resampler, (src[-lpSpec->channels] ^ 0x80) << 8);
  279. while (total_bytes < channel_len && resampler_get_sample_count(resampler) > 0)
  280. {
  281. *dst = SDL_SwapLE16(resampler_get_and_remove_sample(resampler));
  282. dst += lpSpec->channels; total_bytes += (SDL_AUDIO_BITSIZE(AUDIO_S16) >> 3);
  283. }
  284. }
  285. }
  286. }
  287. static void
  288. SOUND_ResampleS16(
  289. LPCBYTE lpData,
  290. const SDL_AudioSpec *lpSpec,
  291. LPBYTE lpBuffer,
  292. DWORD dwLen,
  293. void *resampler
  294. )
  295. /*++
  296. Purpose:
  297. Resample 16-bit signed (little-endian) PCM data into 16-bit signed (little-endian) PCM data.
  298. Parameters:
  299. [IN] lpData - pointer to the buffer of the input PCM data.
  300. [IN] lpSpec - pointer to the SDL_AudioSpec structure, which contains
  301. some basic information about the input PCM data.
  302. [IN] lpBuffer - pointer of the buffer of the output PCM data.
  303. [IN] dwLen - length of the buffer of the output PCM data, should be exactly
  304. the number of bytes needed of the resampled data.
  305. [IN] resampler - pointer of the resampler instance.
  306. Return value:
  307. None.
  308. --*/
  309. {
  310. int src_samples = lpSpec->size / lpSpec->channels / 2, i;
  311. for (i = 0; i < lpSpec->channels; i++)
  312. {
  313. const short *src = (short *)lpData + i;
  314. short *dst = (short *)lpBuffer + i;
  315. int channel_len = dwLen / lpSpec->channels, total_bytes = 0;
  316. resampler_clear(resampler);
  317. while (total_bytes < channel_len && src_samples > 0)
  318. {
  319. int to_write, j;
  320. to_write = resampler_get_free_count(resampler);
  321. if (to_write > src_samples) to_write = src_samples;
  322. for (j = 0; j < to_write; j++)
  323. {
  324. resampler_write_sample(resampler, SDL_SwapLE16(*src));
  325. src += lpSpec->channels;
  326. }
  327. src_samples -= to_write;
  328. while (total_bytes < channel_len && resampler_get_sample_count(resampler) > 0)
  329. {
  330. *dst = SDL_SwapLE16(resampler_get_and_remove_sample(resampler));
  331. dst += lpSpec->channels; total_bytes += (SDL_AUDIO_BITSIZE(AUDIO_S16) >> 3);
  332. }
  333. }
  334. /* Flush resampler's output buffer */
  335. while (total_bytes < channel_len)
  336. {
  337. int j, to_write = resampler_get_free_count(resampler);
  338. short val = SDL_SwapLE16(src[-lpSpec->channels]);
  339. for (j = 0; j < to_write; j++)
  340. resampler_write_sample(resampler, val);
  341. while (total_bytes < channel_len && resampler_get_sample_count(resampler) > 0)
  342. {
  343. *dst = SDL_SwapLE16(resampler_get_and_remove_sample(resampler));
  344. dst += lpSpec->channels; total_bytes += (SDL_AUDIO_BITSIZE(AUDIO_S16) >> 3);
  345. }
  346. }
  347. }
  348. }
  349. static VOID SDLCALL
  350. SOUND_FillAudio(
  351. LPVOID udata,
  352. LPBYTE stream,
  353. INT len
  354. )
  355. /*++
  356. Purpose:
  357. SDL sound callback function.
  358. Parameters:
  359. [IN] udata - pointer to user-defined parameters (Not used).
  360. [OUT] stream - pointer to the stream buffer.
  361. [IN] len - Length of the buffer.
  362. Return value:
  363. None.
  364. --*/
  365. {
  366. int i;
  367. #if SDL_VERSION_ATLEAST(2,0,0)
  368. memset(stream, 0, len);
  369. #endif
  370. //
  371. // Play music
  372. //
  373. if (!g_fNoMusic)
  374. {
  375. SDL_mutexP(gSndPlayer.mtx);
  376. if (gSndPlayer.pMusPlayer)
  377. {
  378. gSndPlayer.pMusPlayer->FillBuffer(gSndPlayer.pMusPlayer, stream, len);
  379. }
  380. if (gSndPlayer.pCDPlayer)
  381. {
  382. gSndPlayer.pCDPlayer->FillBuffer(gSndPlayer.pCDPlayer, stream, len);
  383. }
  384. SDL_mutexV(gSndPlayer.mtx);
  385. }
  386. //
  387. // No current playing sound
  388. //
  389. if (g_fNoSound)
  390. {
  391. return;
  392. }
  393. SDL_mutexP(gSndPlayer.mtx);
  394. for (i = 0; i < 2; i++)
  395. {
  396. //
  397. // Only play if we have data left
  398. //
  399. if (gSndPlayer.buf[i] == NULL)
  400. {
  401. continue;
  402. }
  403. if (gSndPlayer.audio_len[i] == 0)
  404. {
  405. //
  406. // Delete the audio buffer from memory
  407. //
  408. free(gSndPlayer.buf[i]);
  409. gSndPlayer.buf[i] = NULL;
  410. continue;
  411. }
  412. //
  413. // Mix as much data as possible
  414. //
  415. len = (len > gSndPlayer.audio_len[i]) ? gSndPlayer.audio_len[i] : len;
  416. #ifdef __SYMBIAN32__
  417. SDL_MixAudio(stream, gSndPlayer.pos[i], len, g_iVolume);
  418. #else
  419. SDL_MixAudio(stream, gSndPlayer.pos[i], len, SDL_MIX_MAXVOLUME * 2 / 3);
  420. #endif
  421. gSndPlayer.pos[i] += len;
  422. gSndPlayer.audio_len[i] -= len;
  423. }
  424. SDL_mutexV(gSndPlayer.mtx);
  425. }
  426. static VOID
  427. SOUND_LoadMKF(
  428. VOID
  429. )
  430. /*++
  431. Purpose:
  432. Load MKF contents into memory.
  433. Parameters:
  434. None.
  435. Return value:
  436. None.
  437. --*/
  438. {
  439. char *mkfs[2];
  440. FNLoadSoundData func[2];
  441. int i;
  442. if (gpGlobals->fIsWIN95)
  443. {
  444. mkfs[0] = "sounds.mkf"; func[0] = SOUND_LoadWAVEData;
  445. mkfs[1] = "voc.mkf"; func[1] = SOUND_LoadVOCData;
  446. }
  447. else
  448. {
  449. mkfs[0] = "voc.mkf"; func[0] = SOUND_LoadVOCData;
  450. mkfs[1] = "sounds.mkf"; func[1] = SOUND_LoadWAVEData;
  451. }
  452. for (i = 0; i < 2; i++)
  453. {
  454. gSndPlayer.mkf = UTIL_OpenFile(mkfs[i]);
  455. if (gSndPlayer.mkf)
  456. {
  457. gSndPlayer.LoadSoundData = func[i];
  458. break;
  459. }
  460. }
  461. }
  462. INT
  463. SOUND_OpenAudio(
  464. VOID
  465. )
  466. /*++
  467. Purpose:
  468. Initialize the audio subsystem.
  469. Parameters:
  470. None.
  471. Return value:
  472. 0 if succeed, others if failed.
  473. --*/
  474. {
  475. SDL_AudioSpec spec;
  476. char *mkfs[2];
  477. FNLoadSoundData func[2];
  478. int i;
  479. if (gSndOpened)
  480. {
  481. //
  482. // Already opened
  483. //
  484. return -1;
  485. }
  486. gSndOpened = FALSE;
  487. //
  488. // Load the MKF file.
  489. //
  490. SOUND_LoadMKF();
  491. if (gSndPlayer.mkf == NULL)
  492. {
  493. return -2;
  494. }
  495. //
  496. // Initialize the resampler
  497. //
  498. resampler_init();
  499. gSndPlayer.resampler = resampler_create();
  500. //
  501. // Open the sound subsystem.
  502. //
  503. gSndPlayer.spec.freq = gpGlobals->iSampleRate;
  504. gSndPlayer.spec.format = AUDIO_S16;
  505. gSndPlayer.spec.channels = gpGlobals->iAudioChannels;
  506. gSndPlayer.spec.samples = 1024;
  507. gSndPlayer.spec.callback = SOUND_FillAudio;
  508. if (SDL_OpenAudio(&gSndPlayer.spec, &spec) < 0)
  509. {
  510. //
  511. // Failed
  512. //
  513. return -3;
  514. }
  515. memcpy(&gSndPlayer.spec, &spec, sizeof(SDL_AudioSpec));
  516. gSndPlayer.buf[0] = NULL;
  517. gSndPlayer.pos[0] = NULL;
  518. gSndPlayer.audio_len[0] = 0;
  519. gSndPlayer.buf[1] = NULL;
  520. gSndPlayer.pos[1] = NULL;
  521. gSndPlayer.audio_len[1] = 0;
  522. gSndPlayer.mtx = SDL_CreateMutex();
  523. gSndOpened = TRUE;
  524. //
  525. // Initialize the music subsystem.
  526. //
  527. switch (gpGlobals->eMusicType)
  528. {
  529. case MUSIC_RIX:
  530. if (!(gSndPlayer.pMusPlayer = RIX_Init(va("%s%s", PAL_PREFIX, "mus.mkf"))))
  531. {
  532. gSndPlayer.pMusPlayer = RIX_Init(va("%s%s", PAL_PREFIX, "MUS.MKF"));
  533. }
  534. break;
  535. case MUSIC_MP3:
  536. #if PAL_HAS_MP3
  537. gSndPlayer.pMusPlayer = MP3_Init(NULL);
  538. #else
  539. gSndPlayer.pMusPlayer = NULL;
  540. #endif
  541. break;
  542. case MUSIC_OGG:
  543. #if PAL_HAS_OGG
  544. gSndPlayer.pMusPlayer = OGG_Init(NULL);
  545. #else
  546. gSndPlayer.pMusPlayer = NULL;
  547. #endif
  548. break;
  549. case MUSIC_MIDI:
  550. gSndPlayer.pMusPlayer = NULL;
  551. break;
  552. }
  553. //
  554. // Initialize the CD audio.
  555. //
  556. switch (gpGlobals->eCDType)
  557. {
  558. case MUSIC_SDLCD:
  559. {
  560. #if PAL_HAS_SDLCD
  561. int i;
  562. gSndPlayer.pCD = NULL;
  563. for (i = 0; i < SDL_CDNumDrives(); i++)
  564. {
  565. gSndPlayer.pCD = SDL_CDOpen(i);
  566. if (gSndPlayer.pCD != NULL)
  567. {
  568. if (!CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  569. {
  570. SDL_CDClose(gSndPlayer.pCD);
  571. gSndPlayer.pCD = NULL;
  572. }
  573. else
  574. {
  575. break;
  576. }
  577. }
  578. }
  579. #endif
  580. gSndPlayer.pCDPlayer = NULL;
  581. break;
  582. }
  583. case MUSIC_MP3:
  584. #if PAL_HAS_MP3
  585. gSndPlayer.pCDPlayer = MP3_Init(NULL);
  586. #else
  587. gSndPlayer.pCDPlayer = NULL;
  588. #endif
  589. break;
  590. case MUSIC_OGG:
  591. #if PAL_HAS_OGG
  592. gSndPlayer.pCDPlayer = OGG_Init(NULL);
  593. #else
  594. gSndPlayer.pCDPlayer = NULL;
  595. #endif
  596. break;
  597. }
  598. //
  599. // Let the callback function run so that musics will be played.
  600. //
  601. SDL_PauseAudio(0);
  602. return 0;
  603. }
  604. VOID
  605. SOUND_CloseAudio(
  606. VOID
  607. )
  608. /*++
  609. Purpose:
  610. Close the audio subsystem.
  611. Parameters:
  612. None.
  613. Return value:
  614. None.
  615. --*/
  616. {
  617. SDL_mutexP(gSndPlayer.mtx);
  618. SDL_CloseAudio();
  619. if (gSndPlayer.buf[0] != NULL)
  620. {
  621. free(gSndPlayer.buf[0]);
  622. gSndPlayer.buf[0] = NULL;
  623. }
  624. if (gSndPlayer.buf[1] != NULL)
  625. {
  626. free(gSndPlayer.buf[1]);
  627. gSndPlayer.buf[1] = NULL;
  628. }
  629. if (gSndPlayer.mkf != NULL)
  630. {
  631. fclose(gSndPlayer.mkf);
  632. gSndPlayer.mkf = NULL;
  633. }
  634. if (gSndPlayer.pMusPlayer)
  635. {
  636. gSndPlayer.pMusPlayer->Shutdown(gSndPlayer.pMusPlayer);
  637. gSndPlayer.pMusPlayer = NULL;
  638. }
  639. if (gSndPlayer.pCDPlayer)
  640. {
  641. gSndPlayer.pCDPlayer->Shutdown(gSndPlayer.pCDPlayer);
  642. gSndPlayer.pCDPlayer = NULL;
  643. }
  644. #if PAL_HAS_SDLCD
  645. if (gSndPlayer.pCD != NULL)
  646. {
  647. SOUND_PlayCDA(-1);
  648. SDL_CDClose(gSndPlayer.pCD);
  649. }
  650. #endif
  651. #ifdef PAL_HAS_NATIVEMIDI
  652. MIDI_Play(0, FALSE);
  653. #endif
  654. if (gSndPlayer.resampler)
  655. {
  656. resampler_delete(gSndPlayer.resampler);
  657. gSndPlayer.resampler = NULL;
  658. }
  659. SDL_DestroyMutex(gSndPlayer.mtx);
  660. }
  661. SDL_AudioSpec*
  662. SOUND_GetAudioSpec(
  663. VOID
  664. )
  665. {
  666. return &gSndPlayer.spec;
  667. }
  668. #ifdef __SYMBIAN32__
  669. VOID
  670. SOUND_AdjustVolume(
  671. INT iDirectory
  672. )
  673. /*++
  674. Purpose:
  675. SDL sound volume adjust function.
  676. Parameters:
  677. [IN] iDirectory - value, Increase (>0) or decrease (<=0) 3% volume.
  678. Return value:
  679. None.
  680. --*/
  681. {
  682. if (iDirectory > 0)
  683. {
  684. if (g_iVolume <= SDL_MIX_MAXVOLUME)
  685. {
  686. g_iVolume += SDL_MIX_MAXVOLUME * 0.03;
  687. }
  688. else
  689. {
  690. g_iVolume = SDL_MIX_MAXVOLUME;
  691. }
  692. }
  693. else
  694. {
  695. if (g_iVolume > 0)
  696. {
  697. g_iVolume -= SDL_MIX_MAXVOLUME * 0.03;
  698. }
  699. else
  700. {
  701. g_iVolume = 0;
  702. }
  703. }
  704. }
  705. #endif
  706. VOID
  707. SOUND_PlayChannel(
  708. INT iSoundNum,
  709. INT iChannel
  710. )
  711. /*++
  712. Purpose:
  713. Play a sound in voc.mkf file.
  714. Parameters:
  715. [IN] iSoundNum - number of the sound.
  716. [IN] iChannel - the number of channel (0 or 1).
  717. Return value:
  718. None.
  719. --*/
  720. {
  721. SDL_AudioCVT wavecvt;
  722. SDL_AudioSpec wavespec;
  723. LPBYTE buf, bufdec;
  724. LPCBYTE bufsrc;
  725. int len;
  726. if (!gSndOpened || g_fNoSound)
  727. {
  728. return;
  729. }
  730. //
  731. // Stop playing current sound.
  732. //
  733. SDL_mutexP(gSndPlayer.mtx);
  734. if (gSndPlayer.buf[iChannel] != NULL)
  735. {
  736. free(gSndPlayer.buf[iChannel]);
  737. gSndPlayer.buf[iChannel] = NULL;
  738. }
  739. SDL_mutexV(gSndPlayer.mtx);
  740. if (iSoundNum < 0)
  741. {
  742. return;
  743. }
  744. //
  745. // Get the length of the sound file.
  746. //
  747. len = PAL_MKFGetChunkSize(iSoundNum, gSndPlayer.mkf);
  748. if (len <= 0)
  749. {
  750. return;
  751. }
  752. buf = (LPBYTE)malloc(len);
  753. if (buf == NULL)
  754. {
  755. return;
  756. }
  757. //
  758. // Read the sound file from the MKF archive.
  759. //
  760. PAL_MKFReadChunk(buf, len, iSoundNum, gSndPlayer.mkf);
  761. bufsrc = gSndPlayer.LoadSoundData(buf, len, &wavespec);
  762. if (bufsrc == NULL)
  763. {
  764. free(buf);
  765. return;
  766. }
  767. if (wavespec.freq != gSndPlayer.spec.freq)
  768. {
  769. /* Resampler is needed */
  770. resampler_set_quality(gSndPlayer.resampler, SOUND_IsIntegerConversion(wavespec.freq) ? RESAMPLER_QUALITY_MIN : gpGlobals->iResampleQuality);
  771. resampler_set_rate(gSndPlayer.resampler, (double)wavespec.freq / (double)gSndPlayer.spec.freq);
  772. len = (int)ceil(wavespec.size * (double)gSndPlayer.spec.freq / (double)wavespec.freq) * (SDL_AUDIO_BITSIZE(AUDIO_S16) / SDL_AUDIO_BITSIZE(wavespec.format));
  773. if (len >= wavespec.channels * 2)
  774. {
  775. bufdec = malloc(len);
  776. if (wavespec.format == AUDIO_S16)
  777. SOUND_ResampleS16(bufsrc, &wavespec, bufdec, len, gSndPlayer.resampler);
  778. else
  779. SOUND_ResampleU8(bufsrc, &wavespec, bufdec, len, gSndPlayer.resampler);
  780. /* Free the original buffer and reset the pointer for simpler later operations */
  781. free(buf); buf = bufdec;
  782. wavespec.format = AUDIO_S16;
  783. wavespec.freq = gSndPlayer.spec.freq;
  784. }
  785. else
  786. {
  787. free(buf);
  788. return;
  789. }
  790. }
  791. else
  792. {
  793. bufdec = (LPBYTE)bufsrc;
  794. len = wavespec.size;
  795. }
  796. //
  797. // Build the audio converter and create conversion buffers
  798. //
  799. if (SDL_BuildAudioCVT(&wavecvt, wavespec.format, wavespec.channels, wavespec.freq,
  800. gSndPlayer.spec.format, gSndPlayer.spec.channels, gSndPlayer.spec.freq) < 0)
  801. {
  802. free(buf);
  803. return;
  804. }
  805. wavecvt.len = len & ~((SDL_AUDIO_BITSIZE(wavespec.format) >> 3) * wavespec.channels - 1);
  806. wavecvt.buf = (LPBYTE)malloc(wavecvt.len * wavecvt.len_mult);
  807. if (wavecvt.buf == NULL)
  808. {
  809. free(buf);
  810. return;
  811. }
  812. memcpy(wavecvt.buf, bufdec, len);
  813. free(buf);
  814. //
  815. // Run the audio converter
  816. //
  817. if (SDL_ConvertAudio(&wavecvt) < 0)
  818. {
  819. free(wavecvt.buf);
  820. return;
  821. }
  822. SDL_mutexP(gSndPlayer.mtx);
  823. if (gSndPlayer.buf[iChannel] != NULL)
  824. {
  825. free(gSndPlayer.buf[iChannel]);
  826. gSndPlayer.buf[iChannel] = NULL;
  827. }
  828. gSndPlayer.buf[iChannel] = wavecvt.buf;
  829. gSndPlayer.audio_len[iChannel] = wavecvt.len * wavecvt.len_mult;
  830. gSndPlayer.pos[iChannel] = wavecvt.buf;
  831. SDL_mutexV(gSndPlayer.mtx);
  832. }
  833. VOID
  834. SOUND_PlayMUS(
  835. INT iNumRIX,
  836. BOOL fLoop,
  837. FLOAT flFadeTime
  838. )
  839. {
  840. SDL_mutexP(gSndPlayer.mtx);
  841. #ifdef PAL_HAS_NATIVEMIDI
  842. if (gpGlobals->eMusicType == MUSIC_MIDI)
  843. {
  844. MIDI_Play(iNumRIX, fLoop);
  845. return;
  846. }
  847. #endif
  848. if (gSndPlayer.pMusPlayer)
  849. {
  850. gSndPlayer.pMusPlayer->Play(gSndPlayer.pMusPlayer, iNumRIX, fLoop, flFadeTime);
  851. }
  852. SDL_mutexV(gSndPlayer.mtx);
  853. }
  854. BOOL
  855. SOUND_PlayCDA(
  856. INT iNumTrack
  857. )
  858. /*++
  859. Purpose:
  860. Play a CD Audio Track.
  861. Parameters:
  862. [IN] iNumTrack - number of the CD Audio Track.
  863. Return value:
  864. TRUE if the track can be played, FALSE if not.
  865. --*/
  866. {
  867. BOOL ret = FALSE;
  868. #if PAL_HAS_SDLCD
  869. if (gSndPlayer.pCD != NULL)
  870. {
  871. if (CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  872. {
  873. SDL_CDStop(gSndPlayer.pCD);
  874. if (iNumTrack != -1)
  875. {
  876. SOUND_PlayMUS(-1, FALSE, 0);
  877. if (SDL_CDPlayTracks(gSndPlayer.pCD, iNumTrack - 1, 0, 1, 0) == 0)
  878. {
  879. return TRUE;
  880. }
  881. }
  882. }
  883. }
  884. #endif
  885. SDL_mutexP(gSndPlayer.mtx);
  886. if (gSndPlayer.pCDPlayer)
  887. {
  888. if (iNumTrack != -1)
  889. {
  890. SOUND_PlayMUS(-1, FALSE, 0);
  891. ret = gSndPlayer.pCDPlayer->Play(gSndPlayer.pCDPlayer, PAL_CDTRACK_BASE + iNumTrack, TRUE, 0);
  892. }
  893. else
  894. {
  895. ret = gSndPlayer.pCDPlayer->Play(gSndPlayer.pCDPlayer, -1, FALSE, 0);
  896. }
  897. }
  898. SDL_mutexV(gSndPlayer.mtx);
  899. return ret;
  900. }
  901. #ifdef PSP
  902. void
  903. SOUND_Reload(
  904. void
  905. )
  906. {
  907. fclose(gSndPlayer.mkf);
  908. SOUND_LoadMKF();
  909. }
  910. #endif