music_mad.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.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef MP3_MAD_MUSIC
  19. #include <string.h>
  20. #include "music_mad.h"
  21. mad_data *
  22. mad_openFile(const char *filename, SDL_AudioSpec *mixer) {
  23.   SDL_RWops *rw;
  24.   mad_data *mp3_mad;
  25.   rw = SDL_RWFromFile(filename, "rb");
  26.   if (rw == NULL) {
  27. return NULL;
  28.   }
  29.   mp3_mad = mad_openFileRW(rw, mixer);
  30.   if (mp3_mad == NULL) {
  31. SDL_FreeRW(rw);
  32. return NULL;
  33.   }
  34.   mp3_mad->freerw = SDL_TRUE;
  35.   return mp3_mad;
  36. }
  37. mad_data *
  38. mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer) {
  39.   mad_data *mp3_mad;
  40.   mp3_mad = (mad_data *)malloc(sizeof(mad_data));
  41.   if (mp3_mad) {
  42. mp3_mad->rw = rw;
  43. mp3_mad->freerw = SDL_FALSE;
  44. mad_stream_init(&mp3_mad->stream);
  45. mad_frame_init(&mp3_mad->frame);
  46. mad_synth_init(&mp3_mad->synth);
  47. mp3_mad->frames_read = 0;
  48. mad_timer_reset(&mp3_mad->next_frame_start);
  49. mp3_mad->volume = MIX_MAX_VOLUME;
  50. mp3_mad->status = 0;
  51. mp3_mad->output_begin = 0;
  52. mp3_mad->output_end = 0;
  53. mp3_mad->mixer = *mixer;
  54.   }
  55.   return mp3_mad;
  56. }
  57. void
  58. mad_closeFile(mad_data *mp3_mad) {
  59.   mad_stream_finish(&mp3_mad->stream);
  60.   mad_frame_finish(&mp3_mad->frame);
  61.   mad_synth_finish(&mp3_mad->synth);
  62.   if (mp3_mad->freerw) {
  63. SDL_FreeRW(mp3_mad->rw);
  64.   }
  65.   free(mp3_mad);
  66. }
  67. /* Starts the playback. */
  68. void
  69. mad_start(mad_data *mp3_mad) {
  70.   mp3_mad->status |= MS_playing;
  71. }
  72. /* Stops the playback. */
  73. void 
  74. mad_stop(mad_data *mp3_mad) {
  75.   mp3_mad->status &= ~MS_playing;
  76. }
  77. /* Returns true if the playing is engaged, false otherwise. */
  78. int
  79. mad_isPlaying(mad_data *mp3_mad) {
  80.   return ((mp3_mad->status & MS_playing) != 0);
  81. }
  82. /* Reads the next frame from the file.  Returns true on success or
  83.    false on failure. */
  84. static int
  85. read_next_frame(mad_data *mp3_mad) {
  86.   if (mp3_mad->stream.buffer == NULL || 
  87.   mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
  88. size_t read_size;
  89. size_t remaining;
  90. unsigned char *read_start;
  91. /* There might be some bytes in the buffer left over from last
  92.    time.  If so, move them down and read more bytes following
  93.    them. */
  94. if (mp3_mad->stream.next_frame != NULL) {
  95.   remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
  96.   memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
  97.   read_start = mp3_mad->input_buffer + remaining;
  98.   read_size = MAD_INPUT_BUFFER_SIZE - remaining;
  99.   
  100. } else {
  101.   read_size = MAD_INPUT_BUFFER_SIZE;
  102.   read_start = mp3_mad->input_buffer;
  103.   remaining = 0;
  104. }
  105. /* Now read additional bytes from the input file. */
  106. read_size = SDL_RWread(mp3_mad->rw, read_start, 1, read_size);
  107. if (read_size <= 0) {
  108.   if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
  109. if (read_size == 0) {
  110.   mp3_mad->status |= MS_input_eof;
  111. } else {
  112.   mp3_mad->status |= MS_input_error;
  113. }
  114. /* At the end of the file, we must stuff MAD_BUFFER_GUARD
  115.    number of 0 bytes. */
  116. memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
  117. read_size += MAD_BUFFER_GUARD;
  118.   }
  119. }
  120. /* Now feed those bytes into the libmad stream. */
  121. mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
  122.   read_size + remaining);
  123. mp3_mad->stream.error = MAD_ERROR_NONE;
  124.   }
  125.   
  126.   /* Now ask libmad to extract a frame from the data we just put in
  127.  its buffer. */
  128.   if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
  129. if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
  130.   return 0;
  131.   
  132. } else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
  133.   return 0;
  134.   
  135. } else {
  136.   mp3_mad->status |= MS_decode_error;
  137.   return 0;
  138. }
  139.   }
  140.   
  141.   mp3_mad->frames_read++;
  142.   mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
  143.   return 1;
  144. }
  145. /* Scale a MAD sample to 16 bits for output. */
  146. static signed int
  147. scale(mad_fixed_t sample) {
  148.   /* round */
  149.   sample += (1L << (MAD_F_FRACBITS - 16));
  150.   /* clip */
  151.   if (sample >= MAD_F_ONE)
  152.     sample = MAD_F_ONE - 1;
  153.   else if (sample < -MAD_F_ONE)
  154.     sample = -MAD_F_ONE;
  155.   /* quantize */
  156.   return sample >> (MAD_F_FRACBITS + 1 - 16);
  157. }
  158. /* Once the frame has been read, copies its samples into the output
  159.    buffer. */
  160. static void
  161. decode_frame(mad_data *mp3_mad) {
  162.   struct mad_pcm *pcm;
  163.   unsigned int nchannels, nsamples;
  164.   mad_fixed_t const *left_ch, *right_ch;
  165.   unsigned char *out;
  166.   int ret;
  167.   mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
  168.   pcm = &mp3_mad->synth.pcm;
  169.   out = mp3_mad->output_buffer + mp3_mad->output_end;
  170.   if ((mp3_mad->status & MS_cvt_decoded) == 0) {
  171. mp3_mad->status |= MS_cvt_decoded;
  172. /* The first frame determines some key properties of the stream.
  173.    In particular, it tells us enough to set up the convert
  174.    structure now. */
  175. SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels, mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);
  176.   }
  177.   /* pcm->samplerate contains the sampling frequency */
  178.   nchannels = pcm->channels;
  179.   nsamples  = pcm->length;
  180.   left_ch   = pcm->samples[0];
  181.   right_ch  = pcm->samples[1];
  182.   while (nsamples--) {
  183.     signed int sample;
  184.     /* output sample(s) in 16-bit signed little-endian PCM */
  185.     sample = scale(*left_ch++);
  186.     *out++ = ((sample >> 0) & 0xff);
  187.     *out++ = ((sample >> 8) & 0xff);
  188.     if (nchannels == 2) {
  189.       sample = scale(*right_ch++);
  190.       *out++ = ((sample >> 0) & 0xff);
  191.       *out++ = ((sample >> 8) & 0xff);
  192.     }
  193.   }
  194.   mp3_mad->output_end = out - mp3_mad->output_buffer;
  195.   /*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
  196. }
  197. int
  198. mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len) {
  199.   int bytes_remaining;
  200.   int num_bytes;
  201.   Uint8 *out;
  202.   if ((mp3_mad->status & MS_playing) == 0) {
  203. /* We're not supposed to be playing, so send silence instead. */
  204. memset(stream, 0, len);
  205. return;
  206.   }
  207.   out = stream;
  208.   bytes_remaining = len;
  209.   while (bytes_remaining > 0) {
  210. if (mp3_mad->output_end == mp3_mad->output_begin) {
  211.   /* We need to get a new frame. */
  212.   mp3_mad->output_begin = 0;
  213.   mp3_mad->output_end = 0;
  214.   if (!read_next_frame(mp3_mad)) {
  215. if ((mp3_mad->status & MS_error_flags) != 0) {
  216.   /* Couldn't read a frame; either an error condition or
  217.  end-of-file.  Stop. */
  218.   memset(out, 0, bytes_remaining);
  219.   mp3_mad->status &= ~MS_playing;
  220.   return bytes_remaining;
  221. }
  222.   } else {
  223. decode_frame(mp3_mad);
  224. /* Now convert the frame data to the appropriate format for
  225.    output. */
  226. mp3_mad->cvt.buf = mp3_mad->output_buffer;
  227. mp3_mad->cvt.len = mp3_mad->output_end;
  228. mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
  229. /*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
  230. SDL_ConvertAudio(&mp3_mad->cvt);
  231.   }
  232. }
  233. num_bytes = mp3_mad->output_end - mp3_mad->output_begin;
  234. if (bytes_remaining < num_bytes) {
  235.   num_bytes = bytes_remaining;
  236. }
  237. if (mp3_mad->volume == MIX_MAX_VOLUME) {
  238.   memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
  239. } else {
  240.   SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
  241.    num_bytes, mp3_mad->volume);
  242. }
  243. out += num_bytes;
  244. mp3_mad->output_begin += num_bytes;
  245. bytes_remaining -= num_bytes;
  246.   }
  247.   return 0;
  248. }
  249. void
  250. mad_seek(mad_data *mp3_mad, double position) {
  251.   mad_timer_t target;
  252.   int int_part;
  253.   int_part = (int)position;
  254.   mad_timer_set(&target, int_part, 
  255. (int)((position - int_part) * 1000000), 1000000);
  256.   if (mad_timer_compare(mp3_mad->next_frame_start, target) > 0) {
  257. /* In order to seek backwards in a VBR file, we have to rewind and
  258.    start again from the beginning.  This isn't necessary if the
  259.    file happens to be CBR, of course; in that case we could seek
  260.    directly to the frame we want.  But I leave that little
  261.    optimization for the future developer who discovers she really
  262.    needs it. */
  263. mp3_mad->frames_read = 0;
  264. mad_timer_reset(&mp3_mad->next_frame_start);
  265. mp3_mad->status &= ~MS_error_flags;
  266. mp3_mad->output_begin = 0;
  267. mp3_mad->output_end = 0;
  268. SDL_RWseek(mp3_mad->rw, 0, RW_SEEK_SET);
  269.   }
  270.   /* Now we have to skip frames until we come to the right one.
  271.  Again, only truly necessary if the file is VBR. */
  272.   while (mad_timer_compare(mp3_mad->next_frame_start, target) < 0) {
  273. if (!read_next_frame(mp3_mad)) {
  274.   if ((mp3_mad->status & MS_error_flags) != 0) {
  275. /* Couldn't read a frame; either an error condition or
  276.    end-of-file.  Stop. */
  277. mp3_mad->status &= ~MS_playing;
  278. return;
  279.   }
  280. }
  281.   }
  282.   /* Here we are, at the beginning of the frame that contains the
  283.  target time.  Ehh, I say that's close enough.  If we wanted to,
  284.  we could get more precise by decoding the frame now and counting
  285.  the appropriate number of samples out of it. */
  286. }
  287. void
  288. mad_setVolume(mad_data *mp3_mad, int volume) {
  289.   mp3_mad->volume = volume;
  290. }
  291. #endif  /* MP3_MAD_MUSIC */