load_flac.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:9k
源码类别:

多媒体编程

开发平台:

DOS

  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 FLAC into a waveform.
  16.      ~ Austen Dicken (admin@cvpcs.org).
  17. */
  18. #ifdef FLAC_MUSIC
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "SDL_mutex.h"
  23. #include "SDL_endian.h"
  24. #include "SDL_timer.h"
  25. #include "SDL_mixer.h"
  26. #include "dynamic_flac.h"
  27. #include "load_flac.h"
  28. #include <FLAC/stream_decoder.h>
  29. typedef struct {
  30. SDL_RWops* sdl_src;
  31. SDL_AudioSpec* sdl_spec;
  32. Uint8** sdl_audio_buf;
  33. Uint32* sdl_audio_len;
  34. int sdl_audio_read;
  35. FLAC__uint64 flac_total_samples;
  36. unsigned flac_bps;
  37. } FLAC_SDL_Data;
  38. static FLAC__StreamDecoderReadStatus flac_read_load_cb(
  39. const FLAC__StreamDecoder *decoder,
  40. FLAC__byte buffer[],
  41. size_t *bytes,
  42. void *client_data)
  43. {
  44. // make sure there is something to be reading
  45. if (*bytes > 0) {
  46. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  47. *bytes = SDL_RWread (data->sdl_src, buffer, sizeof (FLAC__byte),
  48. *bytes);
  49. if(*bytes < 0) { // error in read
  50. return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
  51. }
  52. else if(*bytes == 0) { // no data was read (EOF)
  53. return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
  54. }
  55. else { // data was read, continue
  56. return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
  57. }
  58. }
  59. else {
  60. return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
  61. }
  62. }
  63. static FLAC__StreamDecoderSeekStatus flac_seek_load_cb(
  64. const FLAC__StreamDecoder *decoder,
  65. FLAC__uint64 absolute_byte_offset,
  66. void *client_data)
  67. {
  68. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  69. if (SDL_RWseek (data->sdl_src, absolute_byte_offset, RW_SEEK_SET) < 0) {
  70. return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
  71. }
  72. else {
  73. return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
  74. }
  75. }
  76. static FLAC__StreamDecoderTellStatus flac_tell_load_cb(
  77. const FLAC__StreamDecoder *decoder,
  78. FLAC__uint64 *absolute_byte_offset,
  79. void *client_data)
  80. {
  81. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  82. int pos = SDL_RWtell (data->sdl_src);
  83. if (pos < 0) {
  84. return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
  85. }
  86. else {
  87. *absolute_byte_offset = (FLAC__uint64)pos;
  88. return FLAC__STREAM_DECODER_TELL_STATUS_OK;
  89. }
  90. }
  91. static FLAC__StreamDecoderLengthStatus flac_length_load_cb(
  92. const FLAC__StreamDecoder *decoder,
  93. FLAC__uint64 *stream_length,
  94. void *client_data)
  95. {
  96. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  97. int pos = SDL_RWtell (data->sdl_src);
  98. int length = SDL_RWseek (data->sdl_src, 0, RW_SEEK_END);
  99. if (SDL_RWseek (data->sdl_src, pos, RW_SEEK_SET) != pos || length < 0) {
  100. /* there was an error attempting to return the stream to the original
  101.  * position, or the length was invalid. */
  102. return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
  103. }
  104. else {
  105. *stream_length = (FLAC__uint64)length;
  106. return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
  107. }
  108. }
  109. static FLAC__bool flac_eof_load_cb(const FLAC__StreamDecoder *decoder,
  110. void *client_data)
  111. {
  112. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  113. int pos = SDL_RWtell (data->sdl_src);
  114. int end = SDL_RWseek (data->sdl_src, 0, RW_SEEK_END);
  115. // was the original position equal to the end (a.k.a. the seek didn't move)?
  116. if (pos == end) {
  117. // must be EOF
  118. return true;
  119. }
  120. else {
  121. // not EOF, return to the original position
  122. SDL_RWseek (data->sdl_src, pos, RW_SEEK_SET);
  123. return false;
  124. }
  125. }
  126. static FLAC__StreamDecoderWriteStatus flac_write_load_cb(
  127. const FLAC__StreamDecoder *decoder,
  128. const FLAC__Frame *frame,
  129. const FLAC__int32 *const buffer[],
  130. void *client_data)
  131. {
  132. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  133. size_t i;
  134. Uint8 *buf;
  135. if (data->flac_total_samples == 0) {
  136. SDL_SetError ("Given FLAC file does not specify its sample count.");
  137. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  138. }
  139. if (data->sdl_spec->channels != 2 || data->flac_bps != 16) {
  140. SDL_SetError ("Current FLAC support is only for 16 bit Stereo files.");
  141. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  142. }
  143. // check if it is the first audio frame so we can initialize the output
  144. // buffer
  145. if (frame->header.number.sample_number == 0) {
  146. *(data->sdl_audio_len) = data->sdl_spec->size;
  147. data->sdl_audio_read = 0;
  148.      *(data->sdl_audio_buf) = malloc (*(data->sdl_audio_len));
  149.      if (*(data->sdl_audio_buf) == NULL) {
  150.      SDL_SetError
  151. ("Unable to allocate memory to store the FLAC stream.");
  152.      return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  153.      }
  154. }
  155. buf = *(data->sdl_audio_buf);
  156. for (i = 0; i < frame->header.blocksize; i++) {
  157. FLAC__int16 i16;
  158. FLAC__uint16 ui16;
  159. i16 = (FLAC__int16)buffer[0][i];
  160. ui16 = (FLAC__uint16)i16;
  161. *(buf + (data->sdl_audio_read++)) = (char)(ui16);
  162. *(buf + (data->sdl_audio_read++)) = (char)(ui16 >> 8);
  163. i16 = (FLAC__int16)buffer[1][i];
  164. ui16 = (FLAC__uint16)i16;
  165. *(buf + (data->sdl_audio_read++)) = (char)(ui16);
  166. *(buf + (data->sdl_audio_read++)) = (char)(ui16 >> 8);
  167. }
  168. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  169. }
  170. static void flac_metadata_load_cb(
  171. const FLAC__StreamDecoder *decoder,
  172. const FLAC__StreamMetadata *metadata,
  173. void *client_data)
  174. {
  175. FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
  176. FLAC__uint64 total_samples;
  177. unsigned bps;
  178. if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
  179. // save the metadata right now for use later on
  180. *(data->sdl_audio_buf) = NULL;
  181. *(data->sdl_audio_len) = 0;
  182. memset (data->sdl_spec, '', sizeof (SDL_AudioSpec));
  183. data->sdl_spec->format = AUDIO_S16;
  184. data->sdl_spec->freq = (int)(metadata->data.stream_info.sample_rate);
  185. data->sdl_spec->channels = (Uint8)(metadata->data.stream_info.channels);
  186. data->sdl_spec->samples = 8192; /* buffer size */
  187. total_samples = metadata->data.stream_info.total_samples;
  188. bps = metadata->data.stream_info.bits_per_sample;
  189. data->sdl_spec->size = total_samples * data->sdl_spec->channels *
  190. (bps / 8);
  191. data->flac_total_samples = total_samples;
  192. data->flac_bps = bps;
  193. }
  194. }
  195. static void flac_error_load_cb(
  196. const FLAC__StreamDecoder *decoder,
  197. FLAC__StreamDecoderErrorStatus status,
  198. void *client_data)
  199. {
  200. // print an SDL error based on the error status
  201. switch (status) {
  202. case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
  203. SDL_SetError ("Error processing the FLAC file [LOST_SYNC].");
  204. break;
  205. case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
  206. SDL_SetError ("Error processing the FLAC file [BAD_HEADER].");
  207. break;
  208. case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
  209. SDL_SetError ("Error processing the FLAC file [CRC_MISMATCH].");
  210. break;
  211. case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
  212. SDL_SetError ("Error processing the FLAC file [UNPARSEABLE].");
  213. break;
  214. default:
  215. SDL_SetError ("Error processing the FLAC file [UNKNOWN].");
  216. break;
  217. }
  218. }
  219. /* don't call this directly; use Mix_LoadWAV_RW() for now. */
  220. SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc,
  221.         SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
  222. {
  223. FLAC__StreamDecoder *decoder = 0;
  224. FLAC__StreamDecoderInitStatus init_status;
  225. int was_error = 1;
  226. int was_init = 0;
  227. Uint32 samplesize;
  228. // create the client data passing information
  229. FLAC_SDL_Data* client_data;
  230. client_data = (FLAC_SDL_Data *)malloc (sizeof (FLAC_SDL_Data));
  231. if ((!src) || (!audio_buf) || (!audio_len))   /* sanity checks. */
  232. goto done;
  233. if (!Mix_Init(MIX_INIT_FLAC))
  234. goto done;
  235. if ((decoder = flac.FLAC__stream_decoder_new ()) == NULL) {
  236. SDL_SetError ("Unable to allocate FLAC decoder.");
  237. goto done;
  238. }
  239. init_status = flac.FLAC__stream_decoder_init_stream (decoder,
  240. flac_read_load_cb, flac_seek_load_cb,
  241. flac_tell_load_cb, flac_length_load_cb,
  242. flac_eof_load_cb, flac_write_load_cb,
  243. flac_metadata_load_cb, flac_error_load_cb,
  244. client_data);
  245. if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
  246. SDL_SetError ("Unable to initialize FLAC stream decoder.");
  247. goto done;
  248. }
  249. was_init = 1;
  250. client_data->sdl_src = src;
  251. client_data->sdl_spec = spec;
  252. client_data->sdl_audio_buf = audio_buf;
  253. client_data->sdl_audio_len = audio_len;
  254. if (!flac.FLAC__stream_decoder_process_until_end_of_stream (decoder)) {
  255. SDL_SetError ("Unable to process FLAC file.");
  256. goto done;
  257. }
  258. was_error = 0;
  259.     /* Don't return a buffer that isn't a multiple of samplesize */
  260.     samplesize = ((spec->format & 0xFF) / 8) * spec->channels;
  261.     *audio_len &= ~(samplesize - 1);
  262. done:
  263. if (was_init && decoder) {
  264. flac.FLAC__stream_decoder_finish (decoder);
  265. }
  266. if (decoder) {
  267. flac.FLAC__stream_decoder_delete (decoder);
  268. }
  269. if (src) {
  270. if (freesrc)
  271. SDL_RWclose (src);
  272. else
  273. SDL_RWseek (src, 0, RW_SEEK_SET);
  274. }
  275. if (was_error)
  276. spec = NULL;
  277.     return spec;
  278. }
  279. #endif // FLAC_MUSIC