/* * NAME: frame->init() * DESCRIPTION: initialize frame struct */ void mad_frame_init(struct mad_frame *frame) { mad_header_init(&frame->header); frame->options = 0; // frame->overlap = 0; mad_frame_mute(frame); }
static struct mp3_data *mp3_open_internal (const char *file, const int buffered) { struct mp3_data *data; data = (struct mp3_data *)xmalloc (sizeof(struct mp3_data)); data->ok = 0; decoder_error_init (&data->error); /* Reset information about the file */ data->freq = 0; data->channels = 0; data->skip_frames = 0; data->bitrate = -1; data->avg_bitrate = -1; /* Open the file */ data->io_stream = io_open (file, buffered); if (io_ok(data->io_stream)) { data->ok = 1; data->size = io_file_size (data->io_stream); mad_stream_init (&data->stream); mad_frame_init (&data->frame); mad_synth_init (&data->synth); if (options_get_int("Mp3IgnoreCRCErrors")) mad_stream_options (&data->stream, MAD_OPTION_IGNORECRC); data->duration = count_time_internal (data); mad_frame_mute (&data->frame); data->stream.next_frame = NULL; data->stream.sync = 0; data->stream.error = MAD_ERROR_NONE; if (io_seek(data->io_stream, SEEK_SET, 0) == (off_t)-1) { decoder_error (&data->error, ERROR_FATAL, 0, "seek failed"); io_close (data->io_stream); mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); data->ok = 0; } data->stream.error = MAD_ERROR_BUFLEN; } else { decoder_error (&data->error, ERROR_FATAL, 0, "Can't open: %s", io_strerror(data->io_stream)); io_close (data->io_stream); } return data; }
static void reset_stream_parameters (mp3d_prc_t * ap_prc) { assert (ap_prc); mad_frame_mute (&ap_prc->frame_); mad_synth_mute (&ap_prc->synth_); tiz_mem_set (ap_prc->in_buff_, 0, INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD); ap_prc->remaining_ = 0; ap_prc->frame_count_ = 0; ap_prc->next_synth_sample_ = 0; ap_prc->eos_ = false; }
static enum mad_flow error_default(void *data, struct mad_stream *stream, struct mad_frame *frame) { int *bad_last_frame = data; switch (stream->error) { case MAD_ERROR_BADCRC: if (*bad_last_frame) mad_frame_mute(frame); else *bad_last_frame = 1; return MAD_FLOW_IGNORE; default: return MAD_FLOW_CONTINUE; } }
RageSoundReader_MP3::RageSoundReader_MP3() { mad = new madlib_t; m_bAccurateSync = false; mad_stream_init( &mad->Stream ); mad_frame_init( &mad->Frame ); mad_synth_init( &mad->Synth ); mad_frame_mute( &mad->Frame ); mad_timer_reset( &mad->Timer ); mad->length = -1; mad->inbuf_filepos = 0; mad->header_bytes = 0; mad->has_xing = false; mad->timer_accurate = 1; mad->bitrate = -1; mad->first_frame = true; }
SINT SoundSourceMp3::restartDecoding( const SeekFrameType& seekFrame) { qDebug() << "restartDecoding @" << seekFrame.frameIndex; // Discard decoded output m_madSynthCount = 0; if (getMinFrameIndex() == seekFrame.frameIndex) { mad_frame_finish(&m_madFrame); mad_synth_finish(&m_madSynth); } mad_stream_finish(&m_madStream); mad_stream_init(&m_madStream); mad_stream_options(&m_madStream, MAD_OPTION_IGNORECRC); if (getMinFrameIndex() == seekFrame.frameIndex) { mad_synth_init(&m_madSynth); mad_frame_init(&m_madFrame); } // Fill input buffer mad_stream_buffer(&m_madStream, seekFrame.pInputData, m_fileSize - (seekFrame.pInputData - m_pFileData)); if (getMinFrameIndex() < seekFrame.frameIndex) { // Muting is done here to eliminate potential pops/clicks // from skipping Rob Leslie explains why here: // http://www.mars.org/mailman/public/mad-dev/2001-August/000321.html mad_frame_mute(&m_madFrame); mad_synth_mute(&m_madSynth); } if (!decodeFrameHeader(&m_madFrame.header, &m_madStream, false)) { if (!isStreamValid(m_madStream)) { // Failure -> Seek to EOF return getFrameCount(); } } return seekFrame.frameIndex; }
bool RageSoundReader_MP3::MADLIB_rewind() { m_pFile->Seek(0); mad_frame_mute(&mad->Frame); mad_synth_mute(&mad->Synth); mad_timer_reset(&mad->Timer); mad->outpos = mad->outleft = 0; mad_stream_finish(&mad->Stream); mad_stream_init(&mad->Stream); mad_stream_buffer(&mad->Stream, NULL, 0); mad->inbuf_filepos = 0; /* Be careful. We need to leave header_bytes alone, so if we try to SetPosition_estimate * immediately after this, we still know the header size. However, we need to set first_frame * to true, since the first frame is handled specially in do_mad_frame_decode; if we don't * set it, then we'll be desynced by a frame after an accurate seek. */ // mad->header_bytes = 0; mad->first_frame = true; mad->Stream.this_frame = NULL; return true; }
/* Seek to a byte in the file. If you're going to put the file position * back when you're done, and not going to read any data, you don't have * to use this. */ int RageSoundReader_MP3::seek_stream_to_byte( int byte ) { if( m_pFile->Seek(byte) == -1 ) { SetError( strerror(errno) ); return 0; } mad_frame_mute(&mad->Frame); mad_synth_mute(&mad->Synth); mad_stream_finish(&mad->Stream); mad_stream_init(&mad->Stream); mad->outleft = mad->outpos = 0; mad->inbuf_filepos = byte; /* If the position is <= the position of the first audio sample, then * we're at the beginning. */ if( !mad->tocmap.empty() ) mad->first_frame = ( byte <= mad->tocmap.begin()->second ); return 1; }
/* Handle first-stage decoding: extracting the MP3 frame data. */ int RageSoundReader_MP3::do_mad_frame_decode( bool headers_only ) { int bytes_read = 0; while(1) { int ret; /* Always actually decode the first packet, so we cleanly parse Xing tags. */ if( headers_only && !mad->first_frame ) ret=mad_header_decode( &mad->Frame.header,&mad->Stream ); else ret=mad_frame_decode( &mad->Frame,&mad->Stream ); if( ret == -1 && (mad->Stream.error == MAD_ERROR_BUFLEN || mad->Stream.error == MAD_ERROR_BUFPTR) ) { if( bytes_read > 25000 ) { /* We've read this much without actually getting a frame; error. */ SetError( "Can't find data" ); return -1; } ret = fill_buffer(); if( ret <= 0 ) return ret; bytes_read += ret; continue; } if( ret == -1 && mad->Stream.error == MAD_ERROR_LOSTSYNC ) { /* This might be an ID3V2 tag. */ const int tagsize = id3_tag_query(mad->Stream.this_frame, mad->Stream.bufend - mad->Stream.this_frame); if( tagsize ) { mad_stream_skip(&mad->Stream, tagsize); /* Don't count the tagsize against the max-read-per-call figure. */ bytes_read -= tagsize; continue; } } if( ret == -1 && mad->Stream.error == MAD_ERROR_BADDATAPTR ) { /* * Something's corrupt. One cause of this is cutting an MP3 in the middle * without reencoding; the first two frames will reference data from previous * frames that have been removed. The frame is valid--we can get a header from * it, we just can't synth useful data. * * BASS pretends the bad frames are silent. Emulate that, for compatibility. */ ret = 0; /* pretend success */ } if( !ret ) { /* OK. */ if( mad->first_frame ) { /* We're at the beginning. Is this a Xing tag? */ if(handle_first_frame()) { /* The first frame contained a header. Continue searching. */ continue; } /* We've decoded the first frame of data. * * We want mad->Timer to represent the timestamp of the first sample of the * currently decoded frame. Don't increment mad->Timer on the first frame, * or it'll be the time of the *next* frame. (All frames have the same * duration.) */ mad->first_frame = false; mad->Timer = mad_timer_zero; mad->header_bytes = get_this_frame_byte(mad); } else { mad_timer_add( &mad->Timer,mad->Frame.header.duration ); } fill_frame_index_cache( mad ); return 1; } if( mad->Stream.error == MAD_ERROR_BADCRC ) { /* XXX untested */ mad_frame_mute(&mad->Frame); mad_synth_mute(&mad->Synth); continue; } if( !MAD_RECOVERABLE(mad->Stream.error) ) { /* We've received an unrecoverable error. */ SetError( mad_stream_errorstr(&mad->Stream) ); return -1; } } }
static int mad_play_frame(input_object *obj, char *buf) { struct mad_local_data *data; struct mad_pcm *pcm; mad_fixed_t const *left_ch; mad_fixed_t const *right_ch; int16_t *output; int nsamples; int nchannels; if (!obj) return 0; data = (struct mad_local_data *)obj->local_data; if (!data) return 0; if (data->bytes_avail < 3072) { /* alsaplayer_error("Filling buffer = %d,%d", data->bytes_avail, data->map_offset + MAD_BUFSIZE - data->bytes_avail); */ fill_buffer(data, -1); /* data->map_offset + MAD_BUFSIZE - data->bytes_avail); */ mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail); } else { /* alsaplayer_error("bytes_avail = %d", data->bytes_avail); */ } if (mad_frame_decode(&data->frame, &data->stream) == -1) { if (!MAD_RECOVERABLE(data->stream.error)) { /* alsaplayer_error("MAD error: %s (%d). fatal", error_str(data->stream.error, data->str), data->bytes_avail); */ mad_frame_mute(&data->frame); return 0; } else { if (reader_eof(data->mad_fd)) { return 0; } //alsaplayer_error("MAD error: %s (not fatal)", error_str(data->stream.error, data->str)); memset(buf, 0, obj->frame_size); return 1; } } data->current_frame++; if (data->seekable && data->current_frame < (obj->nr_frames + FRAME_RESERVE)) { data->frames[data->current_frame] = data->map_offset + data->stream.this_frame - data->mad_map; if (data->current_frame > 3 && (data->frames[data->current_frame] - data->frames[data->current_frame-3]) < 6) { return 0; } if (data->highest_frame < data->current_frame) data->highest_frame = data->current_frame; } mad_synth_frame (&data->synth, &data->frame); { pcm = &data->synth.pcm; output = (int16_t *)buf; nsamples = pcm->length; nchannels = pcm->channels; if (nchannels != obj->nr_channels) { alsaplayer_error("ERROR: bad data stream! (channels: %d != %d, frame %d)", nchannels, obj->nr_channels, data->current_frame); mad_frame_mute(&data->frame); memset(buf, 0, obj->frame_size); return 1; } obj->nr_channels = nchannels; if (data->samplerate != data->frame.header.samplerate) { alsaplayer_error("ERROR: bad data stream! (samplerate: %d != %d, frame %d)", data->samplerate, data->frame.header.samplerate, data->current_frame); mad_frame_mute(&data->frame); memset(buf, 0, obj->frame_size); return 1; } data->samplerate = data->frame.header.samplerate; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; while (nsamples--) { *output++ = my_scale(*(left_ch++)); if (nchannels == 1) { *output++ = my_scale(*(left_ch-1)); } else { /* nchannels == 2 */ *output++ = my_scale(*(right_ch++)); } } } data->bytes_avail = data->stream.bufend - data->stream.next_frame; return 1; }