oggplay.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /* -*- mode: c++; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2015, Lou Yihua <louyihua@21cn.com>.
  4. // All rights reserved.
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. //
  19. // This file is based on the decoder_example.c from libvorbis-1.3.4.
  20. #include "util.h"
  21. #include "global.h"
  22. #include "players.h"
  23. #include "sound.h"
  24. #include <math.h>
  25. #if PAL_HAS_OGG
  26. #include <vorbis\vorbisfile.h>
  27. #define USE_RESAMPLER 1
  28. #if USE_RESAMPLER
  29. #include "resampler.h"
  30. #endif
  31. #define FLAG_OY 0x01
  32. #define FLAG_VI 0x02
  33. #define FLAG_VC 0x04
  34. #define FLAG_OS 0x08
  35. #define FLAG_VD 0x10
  36. #define FLAG_VB 0x20
  37. #define STAGE_PAGEOUT 1
  38. #define STAGE_PACKETOUT 2
  39. #define STAGE_PCMOUT 3
  40. #define STAGE_REWIND 4
  41. #define OGG_BUFFER_LENGTH 4096
  42. typedef struct tagOGGPLAYER
  43. {
  44. MUSICPLAYER_FUNCTIONS;
  45. ogg_sync_state oy; /* sync and verify incoming physical bitstream */
  46. ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
  47. ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
  48. vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
  49. vorbis_comment vc; /* struct that stores all the bitstream user comments */
  50. vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  51. vorbis_block vb; /* local working space for packet->PCM decode */
  52. FILE *fp;
  53. #if USE_RESAMPLER
  54. void *resampler[2];
  55. #endif
  56. INT iFlags;
  57. INT iMusic;
  58. INT iStage;
  59. BOOL fLoop;
  60. BOOL fReady;
  61. } OGGPLAYER, *LPOGGPLAYER;
  62. static SDL_FORCE_INLINE ogg_int16_t OGG_GetSample(float pcm, int volume)
  63. {
  64. int val = floor(pcm * 32767.f + .5f) * volume / SDL_MIX_MAXVOLUME;
  65. /* might as well guard against clipping */
  66. if (val > 32767) {
  67. val = 32767;
  68. }
  69. else if (val < -32768) {
  70. val = -32768;
  71. }
  72. return SWAP16((ogg_int16_t)val);
  73. }
  74. #if USE_RESAMPLER
  75. static SDL_FORCE_INLINE void OGG_FillResample(LPOGGPLAYER player, ogg_int16_t* stream)
  76. {
  77. int i;
  78. if (player->vi.channels >= gpGlobals->iAudioChannels) {
  79. for (i = 0; i < gpGlobals->iAudioChannels; i++) {
  80. stream[i] = resampler_get_and_remove_sample(player->resampler[i]);
  81. }
  82. }
  83. else {
  84. ogg_int16_t val = resampler_get_and_remove_sample(player->resampler[0]);
  85. for (i = 0; i < gpGlobals->iAudioChannels; i++) {
  86. stream[i] = val;
  87. }
  88. }
  89. }
  90. #endif
  91. static void OGG_Cleanup(LPOGGPLAYER player)
  92. {
  93. #if USE_RESAMPLER
  94. int i;
  95. for (i = 0; i < gpGlobals->iAudioChannels; i++) resampler_clear(player->resampler[0]);
  96. #endif
  97. /* Do various cleanups */
  98. if (player->iFlags & FLAG_VB) vorbis_block_clear(&player->vb);
  99. if (player->iFlags & FLAG_VD) vorbis_dsp_clear(&player->vd);
  100. if (player->iFlags & FLAG_OS) ogg_stream_clear(&player->os);
  101. if (player->iFlags & FLAG_VC) vorbis_comment_clear(&player->vc);
  102. if (player->iFlags & FLAG_VI) vorbis_info_clear(&player->vi); /* must be called last */
  103. if (player->iFlags & FLAG_OY) ogg_sync_clear(&player->oy);
  104. player->iFlags = player->iStage = 0;
  105. player->fReady = FALSE;
  106. }
  107. static BOOL OGG_Rewind(LPOGGPLAYER player)
  108. {
  109. ogg_packet op; /* one raw packet of data for decode */
  110. char *buffer;
  111. int i, bytes;
  112. OGG_Cleanup(player);
  113. fseek(player->fp, 0, SEEK_SET);
  114. ogg_sync_init(&player->oy); player->iFlags = FLAG_OY;
  115. /* grab some data at the head of the stream. We want the first page
  116. (which is guaranteed to be small and only contain the Vorbis
  117. stream initial header) We need the first page to get the stream
  118. serialno. */
  119. /* submit a 4k block to libvorbis' Ogg layer */
  120. buffer = ogg_sync_buffer(&player->oy, OGG_BUFFER_LENGTH);
  121. bytes = fread(buffer, 1, OGG_BUFFER_LENGTH, player->fp);
  122. ogg_sync_wrote(&player->oy, bytes);
  123. /* Get the first page. */
  124. if (ogg_sync_pageout(&player->oy, &player->og) != 1) {
  125. /* have we simply run out of data? If so, we're done. */
  126. /* error case. Must not be Vorbis data */
  127. OGG_Cleanup(player);
  128. return (player->fReady = FALSE);
  129. }
  130. /* Get the serial number and set up the rest of decode. */
  131. /* serialno first; use it to set up a logical stream */
  132. ogg_stream_init(&player->os, ogg_page_serialno(&player->og));
  133. player->iFlags |= FLAG_OS;
  134. /* extract the initial header from the first page and verify that the
  135. Ogg bitstream is in fact Vorbis data */
  136. /* I handle the initial header first instead of just having the code
  137. read all three Vorbis headers at once because reading the initial
  138. header is an easy way to identify a Vorbis bitstream and it's
  139. useful to see that functionality seperated out. */
  140. vorbis_info_init(&player->vi); player->iFlags |= FLAG_VI;
  141. vorbis_comment_init(&player->vc); player->iFlags |= FLAG_VC;
  142. if (ogg_stream_pagein(&player->os, &player->og)<0) {
  143. /* error; stream version mismatch perhaps */
  144. OGG_Cleanup(player);
  145. return (player->fReady = FALSE);
  146. }
  147. if (ogg_stream_packetout(&player->os, &op) != 1) {
  148. /* no page? must not be vorbis */
  149. OGG_Cleanup(player);
  150. return (player->fReady = FALSE);
  151. }
  152. if (vorbis_synthesis_headerin(&player->vi, &player->vc, &op)<0) {
  153. /* error case; not a vorbis header */
  154. OGG_Cleanup(player);
  155. return (player->fReady = FALSE);
  156. }
  157. /* At this point, we're sure we're Vorbis. We've set up the logical
  158. (Ogg) bitstream decoder. Get the comment and codebook headers and
  159. set up the Vorbis decoder */
  160. /* The next two packets in order are the comment and codebook headers.
  161. They're likely large and may span multiple pages. Thus we read
  162. and submit data until we get our two packets, watching that no
  163. pages are missing. If a page is missing, error out; losing a
  164. header page is the only place where missing data is fatal. */
  165. i = 0;
  166. while (i < 2) {
  167. while (i < 2) {
  168. int result = ogg_sync_pageout(&player->oy, &player->og);
  169. if (result == 0)break; /* Need more data */
  170. /* Don't complain about missing or corrupt data yet. We'll
  171. catch it at the packet output phase */
  172. if (result == 1) {
  173. ogg_stream_pagein(&player->os, &player->og); /* we can ignore any errors here
  174. as they'll also become apparent
  175. at packetout */
  176. while (i < 2) {
  177. result = ogg_stream_packetout(&player->os, &op);
  178. if (result == 0)break;
  179. if (result < 0) {
  180. /* Uh oh; data at some point was corrupted or missing!
  181. We can't tolerate that in a header. Die. */
  182. OGG_Cleanup(player);
  183. return (player->fReady = FALSE);
  184. }
  185. result = vorbis_synthesis_headerin(&player->vi, &player->vc, &op);
  186. if (result < 0) {
  187. OGG_Cleanup(player);
  188. return (player->fReady = FALSE);
  189. }
  190. i++;
  191. }
  192. }
  193. }
  194. /* no harm in not checking before adding more */
  195. buffer = ogg_sync_buffer(&player->oy, OGG_BUFFER_LENGTH);
  196. bytes = fread(buffer, 1, OGG_BUFFER_LENGTH, player->fp);
  197. if (bytes == 0 && i < 2) {
  198. OGG_Cleanup(player);
  199. return (player->fReady = FALSE);
  200. }
  201. ogg_sync_wrote(&player->oy, bytes);
  202. }
  203. if (vorbis_synthesis_init(&player->vd, &player->vi) == 0) { /* central decode state */
  204. vorbis_block_init(&player->vd, &player->vb); /* local state for most of the decode
  205. so multiple block decodes can
  206. proceed in parallel. We could init
  207. multiple vorbis_block structures
  208. for vd here */
  209. player->iStage = STAGE_PAGEOUT;
  210. player->iFlags |= FLAG_VD | FLAG_VB;
  211. #if USE_RESAMPLER
  212. if (player->vi.rate != gpGlobals->iSampleRate) {
  213. for (i = 0; i < gpGlobals->iAudioChannels; i++) {
  214. resampler_set_rate(player->resampler[i], player->vi.rate / (double)gpGlobals->iSampleRate);
  215. }
  216. }
  217. #endif
  218. return (player->fReady = TRUE);
  219. }
  220. else {
  221. OGG_Cleanup(player);
  222. return (player->fReady = FALSE);
  223. }
  224. }
  225. static VOID
  226. OGG_FillBuffer(
  227. VOID *object,
  228. LPBYTE stream,
  229. INT len
  230. )
  231. {
  232. LPOGGPLAYER player = (LPOGGPLAYER)object;
  233. #ifdef __SYMBIAN32__
  234. int volume = g_iVolume / 2;
  235. #else
  236. int volume = SDL_MIX_MAXVOLUME / 2;
  237. #endif
  238. if (player->fReady) {
  239. ogg_packet op; /* one raw packet of data for decode */
  240. int total_bytes = 0, stage = player->iStage;
  241. while (total_bytes < len) {
  242. float **pcm;
  243. int samples, result;
  244. switch (stage)
  245. {
  246. case STAGE_PAGEOUT: /* PAGEOUT stage */
  247. result = ogg_sync_pageout(&player->oy, &player->og);
  248. if (result > 0) {
  249. /* can safely ignore errors at this point */
  250. ogg_stream_pagein(&player->os, &player->og);
  251. stage = STAGE_PACKETOUT;
  252. }
  253. else {
  254. if (result == 0) { /* need more data */
  255. char *buffer = ogg_sync_buffer(&player->oy, OGG_BUFFER_LENGTH);
  256. int bytes = fread(buffer, 1, OGG_BUFFER_LENGTH, player->fp);
  257. ogg_sync_wrote(&player->oy, bytes);
  258. stage = (bytes > 0) ? STAGE_PAGEOUT : STAGE_REWIND;
  259. }
  260. break;
  261. }
  262. case STAGE_PACKETOUT:
  263. result = ogg_stream_packetout(&player->os, &op);
  264. if (result > 0) {
  265. /* we have a packet. Decode it */
  266. if (vorbis_synthesis(&player->vb, &op) == 0) { /* test for success! */
  267. vorbis_synthesis_blockin(&player->vd, &player->vb);
  268. }
  269. stage = STAGE_PCMOUT;
  270. }
  271. else {
  272. if (result == 0) { /* need more data */
  273. if (ogg_page_eos(&player->og)) {
  274. if (player->fLoop) {
  275. stage = STAGE_REWIND;
  276. }
  277. else {
  278. OGG_Cleanup(player);
  279. UTIL_CloseFile(player->fp);
  280. player->fp = NULL;
  281. return;
  282. }
  283. }
  284. else {
  285. stage = STAGE_PAGEOUT;
  286. }
  287. }
  288. break;
  289. }
  290. case STAGE_PCMOUT:
  291. if ((samples = vorbis_synthesis_pcmout(&player->vd, &pcm)) > 0) {
  292. int bout = (len - total_bytes) / gpGlobals->iAudioChannels / sizeof(ogg_int16_t);
  293. if (bout > samples) bout = samples;
  294. #if USE_RESAMPLER
  295. if (player->vi.rate != gpGlobals->iSampleRate) { /* Samplerate not same, use resampler */
  296. int i, j, to_write;
  297. while (samples > 0) { /* Fill as many samples into resampler as possible */
  298. to_write = resampler_get_free_count(player->resampler[0]);
  299. if (to_write >= samples) to_write = samples;
  300. samples -= to_write;
  301. for (i = 0; i < min(player->vi.channels, gpGlobals->iAudioChannels); i++) {
  302. float *mono = pcm[i];
  303. for (j = 0; j < to_write; j++) {
  304. resampler_write_sample(player->resampler[i], OGG_GetSample(mono[j], volume));
  305. }
  306. }
  307. /* Fetch resampled samples if available */
  308. while (total_bytes < len && resampler_get_sample_count(player->resampler[0])) {
  309. OGG_FillResample(player, (ogg_int16_t *)(stream + total_bytes));
  310. total_bytes += gpGlobals->iAudioChannels * sizeof(ogg_int16_t);
  311. }
  312. }
  313. }
  314. else
  315. #endif
  316. {
  317. int i, j;
  318. if (player->vi.channels >= gpGlobals->iAudioChannels)
  319. {
  320. /* convert floats to 16 bit signed ints (host order) and interleave */
  321. for (i = 0; i < gpGlobals->iAudioChannels; i++) {
  322. ogg_int16_t *ptr = (ogg_int16_t *)(stream + total_bytes) + i;
  323. float *mono = pcm[i];
  324. for (j = 0; j < bout; j++) {
  325. *ptr = OGG_GetSample(mono[j], volume);
  326. ptr += gpGlobals->iAudioChannels;
  327. }
  328. }
  329. }
  330. else
  331. {
  332. ogg_int16_t *ptr = (ogg_int16_t *)(stream + total_bytes);
  333. float *mono = pcm[0];
  334. for (j = 0; j < bout; j++) {
  335. ogg_int16_t val = OGG_GetSample(mono[j], volume);
  336. for (i = 0; i < gpGlobals->iAudioChannels; i++) {
  337. *ptr++ = val;
  338. }
  339. }
  340. }
  341. total_bytes += bout * gpGlobals->iAudioChannels * sizeof(ogg_int16_t);
  342. }
  343. /* tell libvorbis how many samples we actually consumed */
  344. vorbis_synthesis_read(&player->vd, bout);
  345. }
  346. else {
  347. stage = STAGE_PACKETOUT;
  348. }
  349. break;
  350. case STAGE_REWIND:
  351. #if USE_RESAMPLER
  352. if (player->vi.rate != gpGlobals->iSampleRate) { /* If there are samples in the resampler, fetch them first */
  353. while (total_bytes < len && resampler_get_sample_count(player->resampler[0])) {
  354. OGG_FillResample(player, (ogg_int16_t *)(stream + total_bytes));
  355. total_bytes += gpGlobals->iAudioChannels * sizeof(ogg_int16_t);
  356. }
  357. /* Break out if there are still samples in the resampler */
  358. if (resampler_get_sample_count(player->resampler[0])) break;
  359. }
  360. #endif
  361. OGG_Rewind(player);
  362. stage = player->iStage;
  363. break;
  364. default:
  365. return;
  366. }
  367. }
  368. player->iStage = stage;
  369. }
  370. }
  371. static VOID
  372. OGG_Shutdown(
  373. VOID *object
  374. )
  375. {
  376. if (object)
  377. {
  378. LPOGGPLAYER player = (LPOGGPLAYER)object;
  379. #if USE_RESAMPLER
  380. int i;
  381. #endif
  382. OGG_Cleanup(player);
  383. #if USE_RESAMPLER
  384. for (i = 0; i < gpGlobals->iAudioChannels; i++)
  385. resampler_delete(player->resampler[i]);
  386. #endif
  387. if (player->fp) UTIL_CloseFile(player->fp);
  388. free(player);
  389. }
  390. }
  391. static BOOL
  392. OGG_Play(
  393. VOID *object,
  394. INT iNum,
  395. BOOL fLoop,
  396. FLOAT flFadeTime
  397. )
  398. {
  399. char filename[256];
  400. LPOGGPLAYER player = (LPOGGPLAYER)object;
  401. //
  402. // Check for NULL pointer.
  403. //
  404. if (player == NULL)
  405. {
  406. return FALSE;
  407. }
  408. player->fLoop = fLoop;
  409. if (iNum == player->iMusic)
  410. {
  411. return TRUE;
  412. }
  413. player->fReady = FALSE;
  414. OGG_Cleanup(player);
  415. if (player->fp)
  416. {
  417. UTIL_CloseFile(player->fp);
  418. player->fp = NULL;
  419. }
  420. if (iNum == -1)
  421. {
  422. return TRUE;
  423. }
  424. player->fp = UTIL_OpenFile(strcpy(filename, va("ogg/%.2d.ogg", iNum)));
  425. if (player->fp == NULL)
  426. {
  427. return FALSE;
  428. }
  429. else
  430. {
  431. player->iMusic = iNum;
  432. }
  433. if (!OGG_Rewind(player))
  434. {
  435. UTIL_CloseFile(player->fp);
  436. player->fp = NULL;
  437. return FALSE;
  438. }
  439. return TRUE;
  440. }
  441. LPMUSICPLAYER
  442. OGG_Init(
  443. LPCSTR szFileName
  444. )
  445. {
  446. LPOGGPLAYER player;
  447. if (player = (LPOGGPLAYER)malloc(sizeof(OGGPLAYER)))
  448. {
  449. #if USE_RESAMPLER
  450. int i;
  451. #endif
  452. memset(player, 0, sizeof(LPOGGPLAYER));
  453. player->FillBuffer = OGG_FillBuffer;
  454. player->Play = OGG_Play;
  455. player->Shutdown = OGG_Shutdown;
  456. player->fp = NULL;
  457. player->iMusic = -1;
  458. player->iFlags = 0;
  459. player->iStage = 0;
  460. player->fLoop = FALSE;
  461. player->fReady = FALSE;
  462. #if USE_RESAMPLER
  463. for (i = 0; i < gpGlobals->iAudioChannels; i++)
  464. {
  465. player->resampler[i] = resampler_create();
  466. resampler_set_quality(player->resampler[i], RESAMPLER_QUALITY_MAX);
  467. }
  468. #endif
  469. return (LPMUSICPLAYER)player;
  470. }
  471. else
  472. {
  473. return NULL;
  474. }
  475. }
  476. #endif