123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "music_mad.h"
- #include "../resampler.h"
- mad_data *
- mad_openFile(const char *filename, SDL_AudioSpec *mixer, int resampler_quality) {
- SDL_RWops *rw;
- rw = SDL_RWFromFile(filename, "rb");
- if (rw == NULL) {
- return NULL;
- }
- return mad_openFileRW(rw, mixer, resampler_quality);
- }
- mad_data *
- mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int resampler_quality) {
- mad_data *mp3_mad;
- mp3_mad = (mad_data *)malloc(sizeof(mad_data));
- mp3_mad->rw = rw;
- mad_stream_init(&mp3_mad->stream);
- mad_frame_init(&mp3_mad->frame);
- mad_synth_init(&mp3_mad->synth);
- mp3_mad->frames_read = 0;
- mad_timer_reset(&mp3_mad->next_frame_start);
- mp3_mad->volume = 128;
- mp3_mad->status = 0;
- mp3_mad->output_begin = 0;
- mp3_mad->output_end = 0;
- mp3_mad->mixer = *mixer;
- mp3_mad->upsample = 0;
- mp3_mad->resampler_quality = resampler_quality;
- memset(mp3_mad->resampler, 0, sizeof(mp3_mad->resampler));
- return mp3_mad;
- }
- void
- mad_closeFile(mad_data *mp3_mad) {
- SDL_FreeRW(mp3_mad->rw);
- mad_stream_finish(&mp3_mad->stream);
- mad_frame_finish(&mp3_mad->frame);
- mad_synth_finish(&mp3_mad->synth);
- free(mp3_mad);
- }
- void
- mad_start(mad_data *mp3_mad) {
- mp3_mad->status |= MS_playing;
- }
- void
- mad_stop(mad_data *mp3_mad) {
- mp3_mad->status &= ~MS_playing;
- }
- int
- mad_isPlaying(mad_data *mp3_mad) {
- return ((mp3_mad->status & MS_playing) != 0);
- }
- static int
- read_next_frame(mad_data *mp3_mad) {
- if (mp3_mad->stream.buffer == NULL ||
- mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
- size_t read_size;
- size_t remaining;
- unsigned char *read_start;
-
-
- if (mp3_mad->stream.next_frame != NULL) {
- remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
- memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
- read_start = mp3_mad->input_buffer + remaining;
- read_size = MAD_INPUT_BUFFER_SIZE - remaining;
-
- } else {
- read_size = MAD_INPUT_BUFFER_SIZE;
- read_start = mp3_mad->input_buffer;
- remaining = 0;
- }
-
- read_size = SDL_RWread(mp3_mad->rw, read_start, 1, read_size);
-
- if (read_size <= 0) {
- if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
- if (read_size == 0) {
- mp3_mad->status |= MS_input_eof;
- } else {
- mp3_mad->status |= MS_input_error;
- }
-
-
- memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
- read_size += MAD_BUFFER_GUARD;
- }
- }
-
-
- mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
- read_size + remaining);
- mp3_mad->stream.error = MAD_ERROR_NONE;
- }
-
-
- if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
- if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
- return 0;
-
- } else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
- return 0;
-
- } else {
- mp3_mad->status |= MS_decode_error;
- return 0;
- }
- }
-
- mp3_mad->frames_read++;
- mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
- return 1;
- }
- static signed int
- scale(mad_fixed_t sample) {
-
- sample += (1L << (MAD_F_FRACBITS - 16));
-
- if (sample >= MAD_F_ONE)
- sample = MAD_F_ONE - 1;
- else if (sample < -MAD_F_ONE)
- sample = -MAD_F_ONE;
-
- return sample >> (MAD_F_FRACBITS + 1 - 16);
- }
- static void
- decode_frame(mad_data *mp3_mad) {
- struct mad_pcm *pcm;
- unsigned int nchannels, nsamples;
- mad_fixed_t const *left_ch, *right_ch;
- unsigned char *out;
- mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
- pcm = &mp3_mad->synth.pcm;
- out = mp3_mad->output_buffer + mp3_mad->output_end;
- if ((mp3_mad->status & MS_cvt_decoded) == 0) {
- int hi, lo;
- mp3_mad->status |= MS_cvt_decoded;
-
-
- hi = (int)mp3_mad->frame.header.samplerate > mp3_mad->mixer.freq ? mp3_mad->frame.header.samplerate : mp3_mad->mixer.freq;
- lo = (int)mp3_mad->frame.header.samplerate < mp3_mad->mixer.freq ? mp3_mad->frame.header.samplerate : mp3_mad->mixer.freq;
- if (hi != lo) {
-
- if (mp3_mad->resampler[0] = resampler_create()) {
- if (mp3_mad->mixer.channels == 2) {
- if ((mp3_mad->resampler[1] = resampler_create())) {
- resampler_set_quality(mp3_mad->resampler[1], (hi % lo == 0) ? RESAMPLER_QUALITY_MIN : mp3_mad->resampler_quality);
- resampler_set_rate(mp3_mad->resampler[1], (double)mp3_mad->frame.header.samplerate / (double)mp3_mad->mixer.freq);
- }
- else {
- resampler_delete(mp3_mad->resampler[0]);
- mp3_mad->resampler[0] = NULL;
- }
- }
- }
- if (mp3_mad->resampler[0]) {
- resampler_set_quality(mp3_mad->resampler[0], mp3_mad->resampler_quality);
- resampler_set_rate(mp3_mad->resampler[0], (double)mp3_mad->frame.header.samplerate / (double)mp3_mad->mixer.freq);
-
- mp3_mad->upsample = mp3_mad->mixer.freq > (int)mp3_mad->frame.header.samplerate;
- mp3_mad->mixer.freq = mp3_mad->frame.header.samplerate;
- }
- }
-
- SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, (Uint8)pcm->channels, mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);
- }
-
- nchannels = pcm->channels;
- nsamples = pcm->length;
- left_ch = pcm->samples[0];
- right_ch = pcm->samples[1];
- while (nsamples--) {
- signed int sample;
-
- sample = scale(*left_ch++);
- *out++ = ((sample >> 0) & 0xff);
- *out++ = ((sample >> 8) & 0xff);
- if (nchannels == 2) {
- sample = scale(*right_ch++);
- *out++ = ((sample >> 0) & 0xff);
- *out++ = ((sample >> 8) & 0xff);
- }
- }
- mp3_mad->output_end = out - mp3_mad->output_buffer;
-
- }
- void
- mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len) {
- int bytes_remaining;
- int num_bytes;
- Uint8 *out;
- if ((mp3_mad->status & MS_playing) == 0) {
-
- memset(stream, 0, len);
- return;
- }
- out = stream;
- bytes_remaining = len;
- while (bytes_remaining > 0) {
- if (mp3_mad->output_end == mp3_mad->output_begin) {
-
- mp3_mad->output_begin = 0;
- mp3_mad->output_end = 0;
- if (!read_next_frame(mp3_mad)) {
- if ((mp3_mad->status & MS_error_flags) != 0) {
-
- memset(out, 0, bytes_remaining);
- mp3_mad->status &= ~MS_playing;
- return;
- }
- } else {
- decode_frame(mp3_mad);
-
- mp3_mad->cvt.buf = mp3_mad->output_buffer;
- mp3_mad->cvt.len = mp3_mad->output_end;
-
- mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
-
- SDL_ConvertAudio(&mp3_mad->cvt);
-
- if (mp3_mad->resampler[0]) {
- int dst_samples = 0, pos = 0, i;
- if (mp3_mad->upsample) {
-
- pos = sizeof(mp3_mad->output_buffer) - mp3_mad->output_end;
- memmove(mp3_mad->output_buffer + pos, mp3_mad->output_buffer, mp3_mad->output_end);
- }
-
- for (i = 0; i < mp3_mad->mixer.channels; i++) {
- short *src = (short *)(mp3_mad->output_buffer + pos) + i;
- short *dst = (short *)mp3_mad->output_buffer + i;
- int src_samples = 1152;
- while(src_samples > 0) {
- int to_write = resampler_get_free_count(mp3_mad->resampler[i]), j;
- for (j = 0; j < to_write; j++) {
- resampler_write_sample(mp3_mad->resampler[i], SDL_SwapLE16(*src));
- src += mp3_mad->mixer.channels;
- }
- src_samples -= to_write;
- while (resampler_get_sample_count(mp3_mad->resampler[i]) > 0) {
- *dst = SDL_SwapLE16(resampler_get_and_remove_sample(mp3_mad->resampler[i]));
- dst += mp3_mad->mixer.channels; dst_samples++;
- }
- }
- }
- mp3_mad->output_end = dst_samples * (SDL_AUDIO_BITSIZE(mp3_mad->mixer.format) >> 3);
- }
-
- }
- }
- num_bytes = mp3_mad->output_end - mp3_mad->output_begin;
- if (bytes_remaining < num_bytes) {
- num_bytes = bytes_remaining;
- }
- if (mp3_mad->volume == 128) {
- memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
- } else {
- SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
- num_bytes, mp3_mad->volume);
- }
- out += num_bytes;
- mp3_mad->output_begin += num_bytes;
- bytes_remaining -= num_bytes;
- }
- }
- void
- mad_seek(mad_data *mp3_mad, double position) {
- mad_timer_t target;
- int int_part;
- int_part = (int)position;
- mad_timer_set(&target, int_part,
- (int)((position - int_part) * 1000000), 1000000);
- if (mad_timer_compare(mp3_mad->next_frame_start, target) > 0) {
-
- mp3_mad->frames_read = 0;
- mad_timer_reset(&mp3_mad->next_frame_start);
- mp3_mad->status &= ~MS_error_flags;
- mp3_mad->output_begin = 0;
- mp3_mad->output_end = 0;
- SDL_RWseek(mp3_mad->rw, 0, SEEK_SET);
- }
-
- while (mad_timer_compare(mp3_mad->next_frame_start, target) < 0) {
- if (!read_next_frame(mp3_mad)) {
- if ((mp3_mad->status & MS_error_flags) != 0) {
-
- mp3_mad->status &= ~MS_playing;
- return;
- }
- }
- }
-
- }
- void
- mad_setVolume(mad_data *mp3_mad, int volume) {
- mp3_mad->volume = volume;
- }
|