sound.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  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. if (gSndOpened)
  477. {
  478. //
  479. // Already opened
  480. //
  481. return -1;
  482. }
  483. gSndOpened = FALSE;
  484. //
  485. // Load the MKF file.
  486. //
  487. SOUND_LoadMKF();
  488. if (gSndPlayer.mkf == NULL)
  489. {
  490. return -2;
  491. }
  492. //
  493. // Initialize the resampler
  494. //
  495. resampler_init();
  496. gSndPlayer.resampler = resampler_create();
  497. //
  498. // Open the sound subsystem.
  499. //
  500. gSndPlayer.spec.freq = gpGlobals->iSampleRate;
  501. gSndPlayer.spec.format = AUDIO_S16;
  502. gSndPlayer.spec.channels = gpGlobals->iAudioChannels;
  503. gSndPlayer.spec.samples = gpGlobals->wAudioBufferSize;
  504. gSndPlayer.spec.callback = SOUND_FillAudio;
  505. if (SDL_OpenAudio(&gSndPlayer.spec, &spec) < 0)
  506. {
  507. //
  508. // Failed
  509. //
  510. return -3;
  511. }
  512. memcpy(&gSndPlayer.spec, &spec, sizeof(SDL_AudioSpec));
  513. gSndPlayer.buf[0] = NULL;
  514. gSndPlayer.pos[0] = NULL;
  515. gSndPlayer.audio_len[0] = 0;
  516. gSndPlayer.buf[1] = NULL;
  517. gSndPlayer.pos[1] = NULL;
  518. gSndPlayer.audio_len[1] = 0;
  519. gSndPlayer.mtx = SDL_CreateMutex();
  520. gSndOpened = TRUE;
  521. //
  522. // Initialize the music subsystem.
  523. //
  524. switch (gpGlobals->eMusicType)
  525. {
  526. case MUSIC_RIX:
  527. if (!(gSndPlayer.pMusPlayer = RIX_Init(va("%s%s", PAL_PREFIX, "mus.mkf"))))
  528. {
  529. gSndPlayer.pMusPlayer = RIX_Init(va("%s%s", PAL_PREFIX, "MUS.MKF"));
  530. }
  531. break;
  532. case MUSIC_MP3:
  533. #if PAL_HAS_MP3
  534. gSndPlayer.pMusPlayer = MP3_Init(NULL);
  535. #else
  536. gSndPlayer.pMusPlayer = NULL;
  537. #endif
  538. break;
  539. case MUSIC_OGG:
  540. #if PAL_HAS_OGG
  541. gSndPlayer.pMusPlayer = OGG_Init(NULL);
  542. #else
  543. gSndPlayer.pMusPlayer = NULL;
  544. #endif
  545. break;
  546. case MUSIC_MIDI:
  547. gSndPlayer.pMusPlayer = NULL;
  548. break;
  549. }
  550. //
  551. // Initialize the CD audio.
  552. //
  553. switch (gpGlobals->eCDType)
  554. {
  555. case MUSIC_SDLCD:
  556. {
  557. #if PAL_HAS_SDLCD
  558. int i;
  559. gSndPlayer.pCD = NULL;
  560. for (i = 0; i < SDL_CDNumDrives(); i++)
  561. {
  562. gSndPlayer.pCD = SDL_CDOpen(i);
  563. if (gSndPlayer.pCD != NULL)
  564. {
  565. if (!CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  566. {
  567. SDL_CDClose(gSndPlayer.pCD);
  568. gSndPlayer.pCD = NULL;
  569. }
  570. else
  571. {
  572. break;
  573. }
  574. }
  575. }
  576. #endif
  577. gSndPlayer.pCDPlayer = NULL;
  578. break;
  579. }
  580. case MUSIC_MP3:
  581. #if PAL_HAS_MP3
  582. gSndPlayer.pCDPlayer = MP3_Init(NULL);
  583. #else
  584. gSndPlayer.pCDPlayer = NULL;
  585. #endif
  586. break;
  587. case MUSIC_OGG:
  588. #if PAL_HAS_OGG
  589. gSndPlayer.pCDPlayer = OGG_Init(NULL);
  590. #else
  591. gSndPlayer.pCDPlayer = NULL;
  592. #endif
  593. break;
  594. }
  595. //
  596. // Let the callback function run so that musics will be played.
  597. //
  598. SDL_PauseAudio(0);
  599. return 0;
  600. }
  601. VOID
  602. SOUND_CloseAudio(
  603. VOID
  604. )
  605. /*++
  606. Purpose:
  607. Close the audio subsystem.
  608. Parameters:
  609. None.
  610. Return value:
  611. None.
  612. --*/
  613. {
  614. SDL_mutexP(gSndPlayer.mtx);
  615. SDL_CloseAudio();
  616. if (gSndPlayer.buf[0] != NULL)
  617. {
  618. free(gSndPlayer.buf[0]);
  619. gSndPlayer.buf[0] = NULL;
  620. }
  621. if (gSndPlayer.buf[1] != NULL)
  622. {
  623. free(gSndPlayer.buf[1]);
  624. gSndPlayer.buf[1] = NULL;
  625. }
  626. if (gSndPlayer.mkf != NULL)
  627. {
  628. fclose(gSndPlayer.mkf);
  629. gSndPlayer.mkf = NULL;
  630. }
  631. if (gSndPlayer.pMusPlayer)
  632. {
  633. gSndPlayer.pMusPlayer->Shutdown(gSndPlayer.pMusPlayer);
  634. gSndPlayer.pMusPlayer = NULL;
  635. }
  636. if (gSndPlayer.pCDPlayer)
  637. {
  638. gSndPlayer.pCDPlayer->Shutdown(gSndPlayer.pCDPlayer);
  639. gSndPlayer.pCDPlayer = NULL;
  640. }
  641. #if PAL_HAS_SDLCD
  642. if (gSndPlayer.pCD != NULL)
  643. {
  644. SOUND_PlayCDA(-1);
  645. SDL_CDClose(gSndPlayer.pCD);
  646. }
  647. #endif
  648. #ifdef PAL_HAS_NATIVEMIDI
  649. MIDI_Play(0, FALSE);
  650. #endif
  651. if (gSndPlayer.resampler)
  652. {
  653. resampler_delete(gSndPlayer.resampler);
  654. gSndPlayer.resampler = NULL;
  655. }
  656. SDL_DestroyMutex(gSndPlayer.mtx);
  657. }
  658. SDL_AudioSpec*
  659. SOUND_GetAudioSpec(
  660. VOID
  661. )
  662. {
  663. return &gSndPlayer.spec;
  664. }
  665. #ifdef __SYMBIAN32__
  666. VOID
  667. SOUND_AdjustVolume(
  668. INT iDirectory
  669. )
  670. /*++
  671. Purpose:
  672. SDL sound volume adjust function.
  673. Parameters:
  674. [IN] iDirectory - value, Increase (>0) or decrease (<=0) 3% volume.
  675. Return value:
  676. None.
  677. --*/
  678. {
  679. if (iDirectory > 0)
  680. {
  681. if (g_iVolume <= SDL_MIX_MAXVOLUME)
  682. {
  683. g_iVolume += SDL_MIX_MAXVOLUME * 0.03;
  684. }
  685. else
  686. {
  687. g_iVolume = SDL_MIX_MAXVOLUME;
  688. }
  689. }
  690. else
  691. {
  692. if (g_iVolume > 0)
  693. {
  694. g_iVolume -= SDL_MIX_MAXVOLUME * 0.03;
  695. }
  696. else
  697. {
  698. g_iVolume = 0;
  699. }
  700. }
  701. }
  702. #endif
  703. VOID
  704. SOUND_PlayChannel(
  705. INT iSoundNum,
  706. INT iChannel
  707. )
  708. /*++
  709. Purpose:
  710. Play a sound in voc.mkf file.
  711. Parameters:
  712. [IN] iSoundNum - number of the sound.
  713. [IN] iChannel - the number of channel (0 or 1).
  714. Return value:
  715. None.
  716. --*/
  717. {
  718. SDL_AudioCVT wavecvt;
  719. SDL_AudioSpec wavespec;
  720. LPBYTE buf, bufdec;
  721. LPCBYTE bufsrc;
  722. int len;
  723. if (!gSndOpened || g_fNoSound)
  724. {
  725. return;
  726. }
  727. //
  728. // Stop playing current sound.
  729. //
  730. SDL_mutexP(gSndPlayer.mtx);
  731. if (gSndPlayer.buf[iChannel] != NULL)
  732. {
  733. free(gSndPlayer.buf[iChannel]);
  734. gSndPlayer.buf[iChannel] = NULL;
  735. }
  736. SDL_mutexV(gSndPlayer.mtx);
  737. if (iSoundNum < 0)
  738. {
  739. return;
  740. }
  741. //
  742. // Get the length of the sound file.
  743. //
  744. len = PAL_MKFGetChunkSize(iSoundNum, gSndPlayer.mkf);
  745. if (len <= 0)
  746. {
  747. return;
  748. }
  749. buf = (LPBYTE)malloc(len);
  750. if (buf == NULL)
  751. {
  752. return;
  753. }
  754. //
  755. // Read the sound file from the MKF archive.
  756. //
  757. PAL_MKFReadChunk(buf, len, iSoundNum, gSndPlayer.mkf);
  758. bufsrc = gSndPlayer.LoadSoundData(buf, len, &wavespec);
  759. if (bufsrc == NULL)
  760. {
  761. free(buf);
  762. return;
  763. }
  764. if (wavespec.freq != gSndPlayer.spec.freq)
  765. {
  766. /* Resampler is needed */
  767. resampler_set_quality(gSndPlayer.resampler, SOUND_IsIntegerConversion(wavespec.freq) ? RESAMPLER_QUALITY_MIN : gpGlobals->iResampleQuality);
  768. resampler_set_rate(gSndPlayer.resampler, (double)wavespec.freq / (double)gSndPlayer.spec.freq);
  769. len = (int)ceil(wavespec.size * (double)gSndPlayer.spec.freq / (double)wavespec.freq) * (SDL_AUDIO_BITSIZE(AUDIO_S16) / SDL_AUDIO_BITSIZE(wavespec.format));
  770. if (len >= wavespec.channels * 2)
  771. {
  772. bufdec = malloc(len);
  773. if (wavespec.format == AUDIO_S16)
  774. SOUND_ResampleS16(bufsrc, &wavespec, bufdec, len, gSndPlayer.resampler);
  775. else
  776. SOUND_ResampleU8(bufsrc, &wavespec, bufdec, len, gSndPlayer.resampler);
  777. /* Free the original buffer and reset the pointer for simpler later operations */
  778. free(buf); buf = bufdec;
  779. wavespec.format = AUDIO_S16;
  780. wavespec.freq = gSndPlayer.spec.freq;
  781. }
  782. else
  783. {
  784. free(buf);
  785. return;
  786. }
  787. }
  788. else
  789. {
  790. bufdec = (LPBYTE)bufsrc;
  791. len = wavespec.size;
  792. }
  793. //
  794. // Build the audio converter and create conversion buffers
  795. //
  796. if (SDL_BuildAudioCVT(&wavecvt, wavespec.format, wavespec.channels, wavespec.freq,
  797. gSndPlayer.spec.format, gSndPlayer.spec.channels, gSndPlayer.spec.freq) < 0)
  798. {
  799. free(buf);
  800. return;
  801. }
  802. wavecvt.len = len & ~((SDL_AUDIO_BITSIZE(wavespec.format) >> 3) * wavespec.channels - 1);
  803. wavecvt.buf = (LPBYTE)malloc(wavecvt.len * wavecvt.len_mult);
  804. if (wavecvt.buf == NULL)
  805. {
  806. free(buf);
  807. return;
  808. }
  809. memcpy(wavecvt.buf, bufdec, len);
  810. free(buf);
  811. //
  812. // Run the audio converter
  813. //
  814. if (SDL_ConvertAudio(&wavecvt) < 0)
  815. {
  816. free(wavecvt.buf);
  817. return;
  818. }
  819. SDL_mutexP(gSndPlayer.mtx);
  820. if (gSndPlayer.buf[iChannel] != NULL)
  821. {
  822. free(gSndPlayer.buf[iChannel]);
  823. gSndPlayer.buf[iChannel] = NULL;
  824. }
  825. gSndPlayer.buf[iChannel] = wavecvt.buf;
  826. gSndPlayer.audio_len[iChannel] = wavecvt.len * wavecvt.len_mult;
  827. gSndPlayer.pos[iChannel] = wavecvt.buf;
  828. SDL_mutexV(gSndPlayer.mtx);
  829. }
  830. VOID
  831. SOUND_PlayMUS(
  832. INT iNumRIX,
  833. BOOL fLoop,
  834. FLOAT flFadeTime
  835. )
  836. {
  837. SDL_mutexP(gSndPlayer.mtx);
  838. #ifdef PAL_HAS_NATIVEMIDI
  839. if (gpGlobals->eMusicType == MUSIC_MIDI)
  840. {
  841. MIDI_Play(iNumRIX, fLoop);
  842. return;
  843. }
  844. #endif
  845. if (gSndPlayer.pMusPlayer)
  846. {
  847. gSndPlayer.pMusPlayer->Play(gSndPlayer.pMusPlayer, iNumRIX, fLoop, flFadeTime);
  848. }
  849. SDL_mutexV(gSndPlayer.mtx);
  850. }
  851. BOOL
  852. SOUND_PlayCDA(
  853. INT iNumTrack
  854. )
  855. /*++
  856. Purpose:
  857. Play a CD Audio Track.
  858. Parameters:
  859. [IN] iNumTrack - number of the CD Audio Track.
  860. Return value:
  861. TRUE if the track can be played, FALSE if not.
  862. --*/
  863. {
  864. BOOL ret = FALSE;
  865. #if PAL_HAS_SDLCD
  866. if (gSndPlayer.pCD != NULL)
  867. {
  868. if (CD_INDRIVE(SDL_CDStatus(gSndPlayer.pCD)))
  869. {
  870. SDL_CDStop(gSndPlayer.pCD);
  871. if (iNumTrack != -1)
  872. {
  873. SOUND_PlayMUS(-1, FALSE, 0);
  874. if (SDL_CDPlayTracks(gSndPlayer.pCD, iNumTrack - 1, 0, 1, 0) == 0)
  875. {
  876. return TRUE;
  877. }
  878. }
  879. }
  880. }
  881. #endif
  882. SDL_mutexP(gSndPlayer.mtx);
  883. if (gSndPlayer.pCDPlayer)
  884. {
  885. if (iNumTrack != -1)
  886. {
  887. SOUND_PlayMUS(-1, FALSE, 0);
  888. ret = gSndPlayer.pCDPlayer->Play(gSndPlayer.pCDPlayer, PAL_CDTRACK_BASE + iNumTrack, TRUE, 0);
  889. }
  890. else
  891. {
  892. ret = gSndPlayer.pCDPlayer->Play(gSndPlayer.pCDPlayer, -1, FALSE, 0);
  893. }
  894. }
  895. SDL_mutexV(gSndPlayer.mtx);
  896. return ret;
  897. }
  898. #ifdef PSP
  899. void
  900. SOUND_Reload(
  901. void
  902. )
  903. {
  904. fclose(gSndPlayer.mkf);
  905. SOUND_LoadMKF();
  906. }
  907. #endif