/project/jni/sdl_mixer/load_voc.c

https://github.com/aichunyu/FFPlayer · C · 460 lines · 323 code · 79 blank · 58 comment · 111 complexity · 193765f7231d30caea50eb24bfff7978 MD5 · raw file

  1. /*
  2. SDL_mixer: An audio mixer library based on the SDL library
  3. Copyright (C) 1997-2009 Sam Lantinga
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. This is the source needed to decode a Creative Labs VOC file into a
  16. waveform. It's pretty straightforward once you get going. The only
  17. externally-callable function is Mix_LoadVOC_RW(), which is meant to
  18. act as identically to SDL_LoadWAV_RW() as possible.
  19. This file by Ryan C. Gordon (icculus@icculus.org).
  20. Heavily borrowed from sox v12.17.1's voc.c.
  21. (http://www.freshmeat.net/projects/sox/)
  22. */
  23. /* $Id: load_voc.c 5214 2009-11-08 17:11:09Z slouken $ */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "SDL_mutex.h"
  28. #include "SDL_endian.h"
  29. #include "SDL_timer.h"
  30. #include "SDL_mixer.h"
  31. #include "load_voc.h"
  32. /* Private data for VOC file */
  33. typedef struct vocstuff {
  34. Uint32 rest; /* bytes remaining in current block */
  35. Uint32 rate; /* rate code (byte) of this chunk */
  36. int silent; /* sound or silence? */
  37. Uint32 srate; /* rate code (byte) of silence */
  38. Uint32 blockseek; /* start of current output block */
  39. Uint32 samples; /* number of samples output */
  40. Uint32 size; /* word length of data */
  41. Uint8 channels; /* number of sound channels */
  42. int has_extended; /* Has an extended block been read? */
  43. } vs_t;
  44. /* Size field */
  45. /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
  46. #define ST_SIZE_BYTE 1
  47. #define ST_SIZE_8BIT 1
  48. #define ST_SIZE_WORD 2
  49. #define ST_SIZE_16BIT 2
  50. #define ST_SIZE_DWORD 4
  51. #define ST_SIZE_32BIT 4
  52. #define ST_SIZE_FLOAT 5
  53. #define ST_SIZE_DOUBLE 6
  54. #define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */
  55. /* Style field */
  56. #define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */
  57. #define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */
  58. #define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */
  59. #define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */
  60. #define ST_ENCODING_ADPCM 5 /* Compressed PCM */
  61. #define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */
  62. #define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */
  63. #define VOC_TERM 0
  64. #define VOC_DATA 1
  65. #define VOC_CONT 2
  66. #define VOC_SILENCE 3
  67. #define VOC_MARKER 4
  68. #define VOC_TEXT 5
  69. #define VOC_LOOP 6
  70. #define VOC_LOOPEND 7
  71. #define VOC_EXTENDED 8
  72. #define VOC_DATA_16 9
  73. static int voc_check_header(SDL_RWops *src)
  74. {
  75. /* VOC magic header */
  76. Uint8 signature[20]; /* "Creative Voice File\032" */
  77. Uint16 datablockofs;
  78. SDL_RWseek(src, 0, RW_SEEK_SET);
  79. if (SDL_RWread(src, signature, sizeof (signature), 1) != 1)
  80. return(0);
  81. if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) {
  82. SDL_SetError("Unrecognized file type (not VOC)");
  83. return(0);
  84. }
  85. /* get the offset where the first datablock is located */
  86. if (SDL_RWread(src, &datablockofs, sizeof (Uint16), 1) != 1)
  87. return(0);
  88. datablockofs = SDL_SwapLE16(datablockofs);
  89. if (SDL_RWseek(src, datablockofs, RW_SEEK_SET) != datablockofs)
  90. return(0);
  91. return(1); /* success! */
  92. } /* voc_check_header */
  93. /* Read next block header, save info, leave position at start of data */
  94. static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
  95. {
  96. Uint8 bits24[3];
  97. Uint8 uc, block;
  98. Uint32 sblen;
  99. Uint16 new_rate_short;
  100. Uint32 new_rate_long;
  101. Uint8 trash[6];
  102. Uint16 period;
  103. unsigned int i;
  104. v->silent = 0;
  105. while (v->rest == 0)
  106. {
  107. if (SDL_RWread(src, &block, sizeof (block), 1) != 1)
  108. return 1; /* assume that's the end of the file. */
  109. if (block == VOC_TERM)
  110. return 1;
  111. if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1)
  112. return 1; /* assume that's the end of the file. */
  113. /* Size is an 24-bit value. Ugh. */
  114. sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) );
  115. switch(block)
  116. {
  117. case VOC_DATA:
  118. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  119. return 0;
  120. /* When DATA block preceeded by an EXTENDED */
  121. /* block, the DATA blocks rate value is invalid */
  122. if (!v->has_extended)
  123. {
  124. if (uc == 0)
  125. {
  126. SDL_SetError("VOC Sample rate is zero?");
  127. return 0;
  128. }
  129. if ((v->rate != -1) && (uc != v->rate))
  130. {
  131. SDL_SetError("VOC sample rate codes differ");
  132. return 0;
  133. }
  134. v->rate = uc;
  135. spec->freq = (Uint16)(1000000.0/(256 - v->rate));
  136. v->channels = 1;
  137. }
  138. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  139. return 0;
  140. if (uc != 0)
  141. {
  142. SDL_SetError("VOC decoder only interprets 8-bit data");
  143. return 0;
  144. }
  145. v->has_extended = 0;
  146. v->rest = sblen - 2;
  147. v->size = ST_SIZE_BYTE;
  148. return 1;
  149. case VOC_DATA_16:
  150. if (SDL_RWread(src, &new_rate_long, sizeof (new_rate_long), 1) != 1)
  151. return 0;
  152. new_rate_long = SDL_SwapLE32(new_rate_long);
  153. if (new_rate_long == 0)
  154. {
  155. SDL_SetError("VOC Sample rate is zero?");
  156. return 0;
  157. }
  158. if ((v->rate != -1) && (new_rate_long != v->rate))
  159. {
  160. SDL_SetError("VOC sample rate codes differ");
  161. return 0;
  162. }
  163. v->rate = new_rate_long;
  164. spec->freq = new_rate_long;
  165. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  166. return 0;
  167. switch (uc)
  168. {
  169. case 8: v->size = ST_SIZE_BYTE; break;
  170. case 16: v->size = ST_SIZE_WORD; break;
  171. default:
  172. SDL_SetError("VOC with unknown data size");
  173. return 0;
  174. }
  175. if (SDL_RWread(src, &v->channels, sizeof (Uint8), 1) != 1)
  176. return 0;
  177. if (SDL_RWread(src, trash, sizeof (Uint8), 6) != 6)
  178. return 0;
  179. v->rest = sblen - 12;
  180. return 1;
  181. case VOC_CONT:
  182. v->rest = sblen;
  183. return 1;
  184. case VOC_SILENCE:
  185. if (SDL_RWread(src, &period, sizeof (period), 1) != 1)
  186. return 0;
  187. period = SDL_SwapLE16(period);
  188. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  189. return 0;
  190. if (uc == 0)
  191. {
  192. SDL_SetError("VOC silence sample rate is zero");
  193. return 0;
  194. }
  195. /*
  196. * Some silence-packed files have gratuitously
  197. * different sample rate codes in silence.
  198. * Adjust period.
  199. */
  200. if ((v->rate != -1) && (uc != v->rate))
  201. period = (Uint16)((period * (256 - uc))/(256 - v->rate));
  202. else
  203. v->rate = uc;
  204. v->rest = period;
  205. v->silent = 1;
  206. return 1;
  207. case VOC_LOOP:
  208. case VOC_LOOPEND:
  209. for(i = 0; i < sblen; i++) /* skip repeat loops. */
  210. {
  211. if (SDL_RWread(src, trash, sizeof (Uint8), 1) != 1)
  212. return 0;
  213. }
  214. break;
  215. case VOC_EXTENDED:
  216. /* An Extended block is followed by a data block */
  217. /* Set this byte so we know to use the rate */
  218. /* value from the extended block and not the */
  219. /* data block. */
  220. v->has_extended = 1;
  221. if (SDL_RWread(src, &new_rate_short, sizeof (new_rate_short), 1) != 1)
  222. return 0;
  223. new_rate_short = SDL_SwapLE16(new_rate_short);
  224. if (new_rate_short == 0)
  225. {
  226. SDL_SetError("VOC sample rate is zero");
  227. return 0;
  228. }
  229. if ((v->rate != -1) && (new_rate_short != v->rate))
  230. {
  231. SDL_SetError("VOC sample rate codes differ");
  232. return 0;
  233. }
  234. v->rate = new_rate_short;
  235. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  236. return 0;
  237. if (uc != 0)
  238. {
  239. SDL_SetError("VOC decoder only interprets 8-bit data");
  240. return 0;
  241. }
  242. if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  243. return 0;
  244. if (uc)
  245. spec->channels = 2; /* Stereo */
  246. /* Needed number of channels before finishing
  247. compute for rate */
  248. spec->freq = (256000000L/(65536L - v->rate))/spec->channels;
  249. /* An extended block must be followed by a data */
  250. /* block to be valid so loop back to top so it */
  251. /* can be grabed. */
  252. continue;
  253. case VOC_MARKER:
  254. if (SDL_RWread(src, trash, sizeof (Uint8), 2) != 2)
  255. return 0;
  256. /* Falling! Falling! */
  257. default: /* text block or other krapola. */
  258. for(i = 0; i < sblen; i++)
  259. {
  260. if (SDL_RWread(src, &trash, sizeof (Uint8), 1) != 1)
  261. return 0;
  262. }
  263. if (block == VOC_TEXT)
  264. continue; /* get next block */
  265. }
  266. }
  267. return 1;
  268. }
  269. static int voc_read(SDL_RWops *src, vs_t *v, Uint8 *buf, SDL_AudioSpec *spec)
  270. {
  271. int done = 0;
  272. Uint8 silence = 0x80;
  273. if (v->rest == 0)
  274. {
  275. if (!voc_get_block(src, v, spec))
  276. return 0;
  277. }
  278. if (v->rest == 0)
  279. return 0;
  280. if (v->silent)
  281. {
  282. if (v->size == ST_SIZE_WORD)
  283. silence = 0x00;
  284. /* Fill in silence */
  285. memset(buf, silence, v->rest);
  286. done = v->rest;
  287. v->rest = 0;
  288. }
  289. else
  290. {
  291. done = SDL_RWread(src, buf, 1, v->rest);
  292. v->rest -= done;
  293. if (v->size == ST_SIZE_WORD)
  294. {
  295. #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
  296. Uint16 *samples = (Uint16 *)buf;
  297. for (; v->rest > 0; v->rest -= 2)
  298. {
  299. *samples = SDL_SwapLE16(*samples);
  300. samples++;
  301. }
  302. #endif
  303. done >>= 1;
  304. }
  305. }
  306. return done;
  307. } /* voc_read */
  308. /* don't call this directly; use Mix_LoadWAV_RW() for now. */
  309. SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
  310. SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
  311. {
  312. vs_t v;
  313. int was_error = 1;
  314. int samplesize;
  315. Uint8 *fillptr;
  316. void *ptr;
  317. if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */
  318. goto done;
  319. if ( !voc_check_header(src) )
  320. goto done;
  321. v.rate = -1;
  322. v.rest = 0;
  323. v.has_extended = 0;
  324. *audio_buf = NULL;
  325. *audio_len = 0;
  326. memset(spec, '\0', sizeof (SDL_AudioSpec));
  327. if (!voc_get_block(src, &v, spec))
  328. goto done;
  329. if (v.rate == -1)
  330. {
  331. SDL_SetError("VOC data had no sound!");
  332. goto done;
  333. }
  334. spec->format = ((v.size == ST_SIZE_WORD) ? AUDIO_S16 : AUDIO_U8);
  335. if (spec->channels == 0)
  336. spec->channels = v.channels;
  337. *audio_len = v.rest;
  338. *audio_buf = malloc(v.rest);
  339. if (*audio_buf == NULL)
  340. goto done;
  341. fillptr = *audio_buf;
  342. while (voc_read(src, &v, fillptr, spec) > 0)
  343. {
  344. if (!voc_get_block(src, &v, spec))
  345. goto done;
  346. *audio_len += v.rest;
  347. ptr = realloc(*audio_buf, *audio_len);
  348. if (ptr == NULL)
  349. {
  350. free(*audio_buf);
  351. *audio_buf = NULL;
  352. *audio_len = 0;
  353. goto done;
  354. }
  355. *audio_buf = ptr;
  356. fillptr = ((Uint8 *) ptr) + (*audio_len - v.rest);
  357. }
  358. spec->samples = (Uint16)(*audio_len / v.size);
  359. was_error = 0; /* success, baby! */
  360. /* Don't return a buffer that isn't a multiple of samplesize */
  361. samplesize = ((spec->format & 0xFF)/8)*spec->channels;
  362. *audio_len &= ~(samplesize-1);
  363. done:
  364. if (src)
  365. {
  366. if (freesrc)
  367. SDL_RWclose(src);
  368. else
  369. SDL_RWseek(src, 0, RW_SEEK_SET);
  370. }
  371. if ( was_error )
  372. spec = NULL;
  373. return(spec);
  374. } /* Mix_LoadVOC_RW */
  375. /* end of load_voc.c ... */