int GetMADSamples(MFAudioStream *pStream, void *pBuffer, uint32 bytes) { MFMADDecoder *pDecoder = (MFMADDecoder*)pStream->pStreamData; int written = 0; if(pDecoder->overflowBytes) { // grab from the overflow until we run out... uint32 numBytes = MFMin(pDecoder->overflowBytes - pDecoder->overflowOffset, bytes); MFCopyMemory(pBuffer, pDecoder->overflow + pDecoder->overflowOffset, numBytes); pDecoder->overflowOffset += numBytes; if(pDecoder->overflowOffset == pDecoder->overflowBytes) pDecoder->overflowBytes = 0; // increment timer mad_timer_t t = { 0, MAD_TIMER_RESOLUTION / pDecoder->firstHeader.samplerate }; mad_timer_multiply(&t, numBytes >> 2); mad_timer_add(&pDecoder->timer, t); if(bytes == numBytes) return numBytes; bytes -= numBytes; (char*&)pBuffer += numBytes; written = (int)numBytes; }
void MP3Stream::readHeader() { if (_state != MP3_STATE_READY) return; // If necessary, load more data into the stream decoder if (_stream.error == MAD_ERROR_BUFLEN) readMP3Data(); while (_state != MP3_STATE_EOS) { _stream.error = MAD_ERROR_NONE; // Decode the next header. Note: mad_frame_decode would do this for us, too. // However, for seeking we don't want to decode the full frame (else it would // be far too slow). Hence we perform this explicitly in a separate step. if (mad_header_decode(&_frame.header, &_stream) == -1) { if (_stream.error == MAD_ERROR_BUFLEN) { readMP3Data(); // Read more data continue; } else if (MAD_RECOVERABLE(_stream.error)) { //status("MP3Stream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); continue; } else { warning("MP3Stream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); break; } } // Sum up the total playback time so far mad_timer_add(&_totalTime, _frame.header.duration); break; } if (_stream.error != MAD_ERROR_NONE) _state = MP3_STATE_EOS; }
static int mp3_read (song_s *song, char *buffer) { static int i; static int ret; static struct audio_dither dither; static char buffer2[BUF_SIZE]; static char *out_ptr = buffer2; static char *out_buf_end = buffer2 + BUF_SIZE; mp3_s *mp3 = song->songlib->mp3; mad_timer_add (&mp3->timer, mp3->frame.header.duration); mad_synth_frame (&mp3->synth, &mp3->frame); mp3->elapsed_time = ((float)mad_timer_count (mp3->timer, MAD_UNITS_MILLISECONDS))/1000.0; for (i = 0; i < mp3->synth.pcm.length; i++) { signed int sample; sample = (signed int)audio_linear_dither (16, mp3->synth.pcm.samples[0][i], &dither); *(out_ptr++) = sample & 0xff; *(out_ptr++) = sample >> 8; if (MAD_NCHANNELS (&(mp3->frame).header) == 2) { sample = (signed int) audio_linear_dither (16, mp3->synth.pcm.samples[1][i], &dither); *(out_ptr++) = sample & 0xff; *(out_ptr++) = sample >> 8; } if (out_ptr == out_buf_end) { memcpy (buffer, buffer2, BUF_SIZE); bossao_play_chunk (song, buffer, BUF_SIZE); out_ptr = buffer2; } }
static void mp3_update_timer_next_frame(struct mp3_data *data) { if (data->current_frame >= data->highest_frame) { /* record this frame's properties in data->frame_offsets (for seeking) and data->times */ data->bit_rate = (data->frame).header.bitrate; if (data->current_frame >= data->max_frames) /* cap data->current_frame */ data->current_frame = data->max_frames - 1; else data->highest_frame++; data->frame_offsets[data->current_frame] = mp3_this_frame_offset(data); mad_timer_add(&data->timer, (data->frame).header.duration); data->times[data->current_frame] = data->timer; } else /* get the new timer value from data->times */ data->timer = data->times[data->current_frame]; data->current_frame++; data->elapsed_time = mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS) / 1000.0; }
// Seek in the stream, finding the next valid header void Mp3PspStream::findValidHeader() { DEBUG_ENTER_FUNC(); if (_state != MP3_STATE_READY) return; // If necessary, load more data into the stream decoder if (_stream.error == MAD_ERROR_BUFLEN) readMP3DataIntoBuffer(); while (_state != MP3_STATE_EOS) { _stream.error = MAD_ERROR_NONE; // Decode the next header. if (mad_header_decode(&_header, &_stream) == -1) { if (_stream.error == MAD_ERROR_BUFLEN) { readMP3DataIntoBuffer(); // Read more data continue; } else if (MAD_RECOVERABLE(_stream.error)) { debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); continue; } else { warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); break; } } // Sum up the total playback time so far mad_timer_add(&_totalTime, _header.duration); break; } if (_stream.error != MAD_ERROR_NONE) _state = MP3_STATE_EOS; }
size_t MadDecoder::start(FILE* handle) { handle_ = handle; decodeBuffer_.resize(bufferSize_, false); ASSERT(decodeBuffer_.size() == bufferSize_); unsigned char* buffer = decodeBuffer_.getHead(); int64 durationMsec = getDurationMs(buffer, bufferSize_); mad_stream_init(&madStream_); mad_frame_init(&madFrame_); mad_synth_init(&madSynth_); mad_timer_reset(&madTimer_); // Decode at least one valid frame to find out the input format. // The decoded frame will be saved off so that it can be processed later. // size_t bytesRead = fread(buffer, (size_t)1, bufferSize_, handle_); if (bytesRead != bufferSize_ && ferror(handle_)) THROW(std::exception, "%s", strerror(errno)); mad_stream_buffer(&madStream_, buffer, bytesRead); // Find a valid frame before starting up. // This make sure that we have a valid MP3 // and also skips past ID3v2 tags at the beginning of the audio file. // madStream_.error = MAD_ERROR_NONE; while (mad_frame_decode(&madFrame_, &madStream_)) { // check whether input buffer needs a refill if (madStream_.error == MAD_ERROR_BUFLEN) { if (readMpgFile() == false) break; // eof else continue; } consumeId3Tag(); // consume any ID3 tags // FIXME: We should probably detect when we've read // a bunch of non-ID3 data and still haven't found a // frame. In that case we can abort early without // scanning the whole file. // madStream_.error = MAD_ERROR_NONE; } if (madStream_.error) { THROW(std::exception, "No valid MP3 frame found"); } mad_timer_add(&madTimer_, madFrame_.header.duration); mad_synth_frame(&madSynth_, &madFrame_); //unsigned int precision_ = 16; currentFrame_ = 0; numMpegFrames_ = 0; initialized_ = true; return (size_t)(durationMsec * .001 * getSampleRate() + .5); // number of sample frames }
// // Read up samples from madSynth_ // If needed, read some more MP3 data, decode them and synth them // Place in audioBuffer_. // Return number of samples read. // size_t MadDecoder::decode(size_t numPendingTotal, AudioBuffer* buffer) { size_t numProcessedTotal = 0; int numChannels = getNumChannels(); mad_fixed_t sample; do { size_t numPendingFrame = (madSynth_.pcm.length - currentFrame_) * numChannels; numPendingFrame = std::min(numPendingTotal, numPendingFrame); size_t numProcessedFrame = 0; while (numProcessedFrame < numPendingFrame) { for (int channel = 0; channel < numChannels; channel++) { sample = madSynth_.pcm.samples[channel][currentFrame_]; if (sample < -MAD_F_ONE) sample = -MAD_F_ONE; else if (sample >= MAD_F_ONE) sample = MAD_F_ONE - 1; float fSample = (float)(sample / (float)(1L << MAD_F_FRACBITS)); float* pos = buffer->getHead() + numProcessedTotal; *pos = fSample; numProcessedFrame++; numProcessedTotal++; } currentFrame_++; } numPendingTotal -= numProcessedFrame; if (numPendingTotal == 0) break; if (madStream_.error == MAD_ERROR_BUFLEN) { // check whether input buffer needs a refill if (readMpgFile() == false) // eof break; } if (mad_frame_decode(&madFrame_, &madStream_)) { if (MAD_RECOVERABLE(madStream_.error)) { consumeId3Tag(); continue; } else { if (madStream_.error == MAD_ERROR_BUFLEN) continue; else THROW(std::exception, "unrecoverable frame level error (%s).", mad_stream_errorstr(&madStream_)); } } mad_timer_add(&madTimer_, madFrame_.header.duration); mad_synth_frame(&madSynth_, &madFrame_); currentFrame_ = 0; numMpegFrames_++; } while (true); return numProcessedTotal; }
int TrackDuration::duration(const QFileInfo &fileinfo) { QString fn = fileinfo.absoluteFilePath(); if (fn.isEmpty()) return 0; QFile file(fn); if (!file.open(QFile::ReadOnly)) return 0; mad_stream infostream; mad_header infoheader; mad_timer_t infotimer; mad_stream_init(&infostream); mad_header_init(&infoheader); mad_timer_reset(&infotimer); qint64 r; qint64 l = 0; unsigned char* buf = new unsigned char[INPUT_BUFFER_SIZE]; while (!file.atEnd()) { if (l < INPUT_BUFFER_SIZE) { r = file.read(reinterpret_cast<char*>(buf) + l, INPUT_BUFFER_SIZE - l); l += r; } mad_stream_buffer(&infostream, buf, l); for (;;) { if (mad_header_decode(&infoheader, &infostream)) { if (!MAD_RECOVERABLE(infostream.error)) break; if (infostream.error == MAD_ERROR_LOSTSYNC) { TagLib::ID3v2::Header header; uint size = (uint)(infostream.bufend - infostream.this_frame); if (size >= header.size()) { header.setData(TagLib::ByteVector(reinterpret_cast<const char*>(infostream.this_frame), size)); uint tagsize = header.tagSize(); if (tagsize > 0) { mad_stream_skip(&infostream, qMin(tagsize, size)); continue; } } } qDebug() << "header decode error while getting file info" << infostream.error; continue; } mad_timer_add(&infotimer, infoheader.duration); } if (infostream.error != MAD_ERROR_BUFLEN && infostream.error != MAD_ERROR_BUFPTR) break; memmove(buf, infostream.next_frame, &(buf[l]) - infostream.next_frame); l -= (infostream.next_frame - buf); } mad_stream_finish(&infostream); mad_header_finish(&infoheader); delete[] buf; return timerToMs(&infotimer); }
void decode() { // While we need to fill the buffer... while ( (mad_frame_decode(&frame, &stream) == -1) && ((stream.error == MAD_ERROR_BUFLEN) || (stream.error == MAD_ERROR_BUFPTR)) ) { // Fill up the remainder of the file buffer. int tmp; tmp = fillFileBuffer(); if (tmp==2) { endofstream = 1; //MusicPlayerNextSong(); /*! * * Put here the function that does something when the file has ended. * */ } // Give new buffer to the stream. mad_stream_buffer(&stream, fileBuffer, sizeof(fileBuffer)); } // Add to the timer the stream duration mad_timer_add(&timer, frame.header.duration); // Synth the frame. mad_synth_frame(&synth, &frame); }
static void scan_file (FILE * fd, int *length, int *bitrate) { struct mad_stream stream; struct mad_header header; mad_timer_t timer; unsigned char buffer[8192]; unsigned int buflen = 0; mad_stream_init (&stream); mad_header_init (&header); timer = mad_timer_zero; while (1) { if (buflen < 8192) { int bytes = 0; bytes = fread (buffer + buflen, 1, 8192 - buflen, fd); if (bytes <= 0) break; buflen += bytes; } mad_stream_buffer (&stream, buffer, buflen); while (1) { if (mad_header_decode (&header, &stream) == -1) { if (!MAD_RECOVERABLE (stream.error)) break; continue; } if (length) mad_timer_add (&timer, header.duration); } if (stream.error != MAD_ERROR_BUFLEN) break; memmove (buffer, stream.next_frame, &buffer[buflen] - stream.next_frame); buflen -= stream.next_frame - &buffer[0]; SDL_Delay(1); } mad_header_finish (&header); mad_stream_finish (&stream); if (length) *length = mad_timer_count (timer, MAD_UNITS_MILLISECONDS); }
void MADTranscode::onSeek( int seconds ) { mad_timer_t t; t.seconds = seconds; t.fraction = 0; timer = mad_timer_zero; mad_timer_add( &timer, t ); m_encodedBuffer.clear(); m_decodedBuffer.clear(); }
/* * NAME: timer->multiply() * DESCRIPTION: multiply a timer by a scalar value */ void mad_timer_multiply(mad_timer_t *timer, s32 scalar) { mad_timer_t addend; u32 factor; factor = scalar; if (scalar < 0) { factor = -scalar; mad_timer_negate(timer); } addend = *timer; *timer = mad_timer_zero; while (factor) { if (factor & 1) mad_timer_add(timer, addend); mad_timer_add(&addend, addend); factor >>= 1; } }
/* * NAME: timer->multiply() * DESCRIPTION: multiply a timer by a scalar value */ void ICACHE_FLASH_ATTR mad_timer_multiply(mad_timer_t *timer, signed long scalar) { mad_timer_t addend; unsigned long factor; factor = scalar; if (scalar < 0) { factor = -scalar; mad_timer_negate(timer); } addend = *timer; *timer = mad_timer_zero; while (factor) { if (factor & 1) mad_timer_add(timer, addend); mad_timer_add(&addend, addend); factor >>= 1; } }
int RageSoundReader_MP3::GetLengthInternal( bool fast ) { if( mad->has_xing && mad->length != -1 ) return mad->length; /* should be accurate */ /* Check to see if a frame in the middle of the file is the same * bitrate as the first frame. If it is, assume the file is really CBR. */ seek_stream_to_byte( mad->filesize / 2 ); /* XXX use mad_header_decode and check more than one frame */ if(mad->length != -1 && do_mad_frame_decode() && mad->bitrate == (int) mad->Frame.header.bitrate) { return mad->length; } if( !MADLIB_rewind() ) return 0; /* Worst-case: vbr && !xing. We've made a guess at the length, but let's actually * scan the size, since the guess is probably wrong. */ if( fast ) { SetError("Can't estimate file length"); return -1; } MADLIB_rewind(); while(1) { int ret = do_mad_frame_decode( true ); if( ret == -1 ) return -1; /* it set the error */ if( ret == 0 ) /* EOF */ break; } /* mad->Timer is the timestamp of the current frame; find the timestamp of * the very end. */ mad_timer_t end = mad->Timer; mad_timer_add( &end, mad->framelength ); /* Count milliseconds. */ return mad_timer_count( end, MAD_UNITS_MILLISECONDS ); }
/* Do a seek based on the bitrate. */ int RageSoundReader_MP3::SetPosition_estimate( int iFrame ) { /* This doesn't leave us accurate. */ mad->timer_accurate = 0; mad_timer_t seekamt; mad_timer_set( &seekamt, 0, iFrame, mad->Frame.header.samplerate ); { /* We're going to skip ahead two samples below, so seek earlier than * we were asked to. */ mad_timer_t back_len = mad->framelength; mad_timer_multiply(&back_len, -2); mad_timer_add(&seekamt, back_len); if( mad_timer_compare(seekamt, mad_timer_zero) < 0 ) seekamt = mad_timer_zero; } int seekpos = mad_timer_count( seekamt, MAD_UNITS_MILLISECONDS ) * (mad->bitrate / 8 / 1000); seekpos += mad->header_bytes; seek_stream_to_byte( seekpos ); /* We've jumped across the file, so the decoder is currently desynced. * Don't use resync(); it's slow. Just decode a few frames. */ for( int i = 0; i < 2; ++i ) { int ret = do_mad_frame_decode(); if( ret <= 0 ) return ret; } /* Throw out one synth. */ synth_output(); mad->outleft = 0; /* Find out where we really seeked to. */ int ms = (get_this_frame_byte(mad) - mad->header_bytes) / (mad->bitrate / 8 / 1000); mad_timer_set(&mad->Timer, 0, ms, 1000); return 1; }
/* Following two functions are adapted from mad_timer, from the libmad distribution */ void scan(void const *ptr, ssize_t len, buffer *buf) { struct mad_stream stream; struct mad_header header; struct xing xing; unsigned long bitrate = 0; int has_xing = 0; int is_vbr = 0; mad_stream_init(&stream); mad_header_init(&header); mad_stream_buffer(&stream, ptr, len); buf->num_frames = 0; /* There are three ways of calculating the length of an mp3: 1) Constant bitrate: One frame can provide the information needed: # of frames and duration. Just see how long it is and do the division. 2) Variable bitrate: Xing tag. It provides the number of frames. Each frame has the same number of samples, so just use that. 3) All: Count up the frames and duration of each frames by decoding each one. We do this if we've no other choice, i.e. if it's a VBR file with no Xing tag. */ while (1) { if (mad_header_decode(&header, &stream) == -1) { if (MAD_RECOVERABLE(stream.error)) continue; else break; } /* Limit xing testing to the first frame header */ if (!buf->num_frames++) { if(parse_xing(&xing, stream.anc_ptr, stream.anc_bitlen)) { is_vbr = 1; if (xing.flags & XING_FRAMES) { /* We use the Xing tag only for frames. If it doesn't have that information, it's useless to us and we have to treat it as a normal VBR file */ has_xing = 1; buf->num_frames = xing.frames; break; } } } /* Test the first n frames to see if this is a VBR file */ if (!is_vbr && !(buf->num_frames > 20)) { if (bitrate && header.bitrate != bitrate) { is_vbr = 1; } else { bitrate = header.bitrate; } } /* We have to assume it's not a VBR file if it hasn't already been marked as one and we've checked n frames for different bitrates */ else if (!is_vbr) { break; } mad_timer_add(&buf->duration, header.duration); } if (!is_vbr) { double time = (len * 8.0) / (header.bitrate); /* time in seconds */ double timefrac = (double)time - ((long)(time)); long nsamples = 32 * MAD_NSBSAMPLES(&header); /* samples per frame */ /* samplerate is a constant */ buf->num_frames = (long) (time * header.samplerate / nsamples); mad_timer_set(&buf->duration, (long)time, (long)(timefrac*100), 100); } else if (has_xing) { /* modify header.duration since we don't need it anymore */ mad_timer_multiply(&header.duration, buf->num_frames); buf->duration = header.duration; } else { /* the durations have been added up, and the number of frames counted. We do nothing here. */ } mad_header_finish(&header); mad_stream_finish(&stream); }
enum mad_flow read_header(void *data, struct mad_header const * header) { char long_currenttime_str[14]; /* this *will* fill if you're using 100000+ minute mp3s */ char long_remaintime_str[14]; static int frames_played = 0; buffer *playbuf = (buffer *)data; mad_timer_t time_remaining; char *ao_time; if (stop_playing_file) { stop_playing_file = 0; status = MPG321_STOPPED; return MAD_FLOW_STOP; } if(options.opt & MPG321_REMOTE_PLAY) { enum mad_flow mf; /* We might have to stop if the user inputs something */ if ((mf = remote_get_input_nowait(playbuf))) return mf; } /* Stop playing if -n is used, and we're at the frame specified. */ if ((playbuf->max_frames != -1) && (frames_played++ > playbuf->max_frames)) { frames_played = 0; status = MPG321_STOPPED; if(options.opt & MPG321_ENABLE_BUFFER) Decoded_Frames->done = 1; //fprintf(stderr,"Total D: %d\n",Decoded_Frames->total_decoded_frames); return MAD_FLOW_STOP; } current_frame++; mad_timer_add(¤t_time, header->duration); if(options.opt & MPG321_USE_SCROBBLER && scrobbler_time > 0 && scrobbler_time < current_time.seconds) { scrobbler_time = -1; scrobbler_report(); } if(options.opt & (MPG321_VERBOSE_PLAY | MPG321_REMOTE_PLAY)) { mad_timer_string(current_time, long_currenttime_str, "%.2u:%.2u.%.2u", MAD_UNITS_MINUTES, MAD_UNITS_CENTISECONDS, 0); if (mad_timer_compare(playbuf->duration, mad_timer_zero) == 0) time_remaining = current_time; else time_remaining = playbuf->duration; mad_timer_negate(¤t_time); mad_timer_add(&time_remaining, current_time); mad_timer_negate(¤t_time); mad_timer_string(time_remaining, long_remaintime_str, "%.2u:%.2u.%.2u", MAD_UNITS_MINUTES, MAD_UNITS_CENTISECONDS, 0); } /* update cached table of frames & times */ if (current_frame <= playbuf->num_frames) /* we only allocate enough for our estimate. */ { playbuf->frames[current_frame] = playbuf->frames[current_frame-1] + (header->bitrate / 8 / 1000) * mad_timer_count(header->duration, MAD_UNITS_MILLISECONDS); playbuf->times[current_frame] = current_time; } if (file_change) { file_change = 0; if (options.opt & MPG321_REMOTE_PLAY) { printf("@S %s %d %d %s %d %ld %d %d %d %d %ld %d\n",versionstring(header->flags), header->layer, header->samplerate, modestringucase(header->mode), header->mode_extension, (header->bitrate / 8 / 100) * mad_timer_count(header->duration, MAD_UNITS_CENTISECONDS), MAD_NCHANNELS(header), header->flags & MAD_FLAG_COPYRIGHT ? 1 : 0, header->flags & MAD_FLAG_PROTECTION ? 1 : 0, header->emphasis, header->bitrate/1000, header->mode_extension); } else if (options.opt & MPG321_VERBOSE_PLAY)/*zip it good*/ { fprintf(stderr, "MPEG %s, Layer: %s, Freq: %d, mode: %s, modext: %d, BPF : %ld\n" "Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n" "Bitrate: %ld Kbits/s, Extension value: %d\n" "Audio: 1:1 conversion, rate: %d, encoding: signed 16 bit, channels: %d\n", versionstring(header->flags),layerstring(header->layer), header->samplerate, modestringucase(header->mode), header->mode_extension, (header->bitrate / 100) * mad_timer_count(header->duration, MAD_UNITS_CENTISECONDS), MAD_NCHANNELS(header), header->flags & MAD_FLAG_COPYRIGHT ? "Yes" : "No", header->flags & MAD_FLAG_ORIGINAL ? "Yes" : "No", header->flags & MAD_FLAG_PROTECTION ? "Yes" : "No", header->emphasis, header->bitrate/1000, header->mode_extension, header->samplerate, MAD_NCHANNELS(header)); } else if (!(options.opt & MPG321_QUIET_PLAY))/*I love Joey*/ { fprintf(stderr, "MPEG %s layer %s, %ld kbit/s, %d Hz %s\n", versionstring(header->flags),layerstring(header->layer), header->bitrate/1000, header->samplerate, modestring(header->mode)); } } if (status == MPG321_SEEKING && options.seek) { if (!--options.seek) status = MPG321_PLAYING; return MAD_FLOW_IGNORE; } else { status = MPG321_PLAYING; } if(!(options.opt & MPG321_ENABLE_BUFFER)) { if(count > 0) { count++; if(count > 40) { if(!(options.opt & MPG321_VERBOSE_PLAY)) fprintf(stderr," \r"); count = -1; fflush(stderr); } } } if(options.opt & MPG321_ENABLE_BUFFER) { ao_time = (Output_Queue+mad_decoder_position)->time; (Output_Queue+mad_decoder_position)->num_frames = playbuf->num_frames - current_frame; if(Decoded_Frames->is_file) (Output_Queue+mad_decoder_position)->seconds = time_remaining.seconds; } if (options.opt & MPG321_VERBOSE_PLAY) { if (!options.skip_printing_frames || (options.skip_printing_frames && !(current_frame % options.skip_printing_frames))) if(count > 0) { /* if(options.opt & MPG321_ENABLE_BUFFER) { sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame, playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); //sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame, // playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); //sprintf(ao_time, "Volume: %d%% Frame# %5lu [%5lu], Time: %s [%s], \r",volume, current_frame, // playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); }else*/ { fprintf(stderr, "Volume: %d%% Frame# %5lu [%5lu], Time: %s [%s], \r",volume, current_frame, playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); } } else if(count < 0) { if(options.opt & MPG321_ENABLE_BUFFER) { // sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame, sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame, playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); } else { fprintf(stderr, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame, playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str); } } } else if (options.opt & MPG321_REMOTE_PLAY) { if (!options.skip_printing_frames || (options.skip_printing_frames && !(current_frame % options.skip_printing_frames))) { if(options.opt & MPG321_ENABLE_BUFFER) { sprintf(ao_time,"@F %ld %ld %.2f %.2f\n", current_frame, playbuf->num_frames - current_frame, ((double)mad_timer_count(current_time, MAD_UNITS_CENTISECONDS)/100.0), ((double)mad_timer_count(time_remaining, MAD_UNITS_CENTISECONDS)/100.0)); } else { fprintf(stderr,"@F %ld %ld %.2f %.2f\n", current_frame, playbuf->num_frames - current_frame, ((double)mad_timer_count(current_time, MAD_UNITS_CENTISECONDS)/100.0), ((double)mad_timer_count(time_remaining, MAD_UNITS_CENTISECONDS)/100.0)); } } } return MAD_FLOW_CONTINUE; }
int Mp3Decoder::Read(u8 * buffer, int buffer_size, int pos UNUSED) { if(!file_fd) return -1; if(Format == VOICE_STEREO_16BIT) buffer_size &= ~0x0003; else buffer_size &= ~0x0001; u8 * write_pos = buffer; u8 * write_end = buffer+buffer_size; while(1) { while(SynthPos < Synth.pcm.length) { if(write_pos >= write_end) return write_pos-buffer; *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]); write_pos += 2; if(MAD_NCHANNELS(&Frame.header) == 2) { *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]); write_pos += 2; } SynthPos++; } if(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN) { u8 * ReadStart = ReadBuffer; int ReadSize = SoundBlockSize*SoundBlocks; int Remaining = 0; if(Stream.next_frame != NULL) { Remaining = Stream.bufend - Stream.next_frame; memmove(ReadBuffer, Stream.next_frame, Remaining); ReadStart += Remaining; ReadSize -= Remaining; } ReadSize = file_fd->read(ReadStart, ReadSize); if(ReadSize <= 0) { GuardPtr = ReadStart; memset(GuardPtr, 0, MAD_BUFFER_GUARD); ReadSize = MAD_BUFFER_GUARD; } CurPos += ReadSize; mad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize); } if(mad_frame_decode(&Frame,&Stream)) { if(MAD_RECOVERABLE(Stream.error)) { if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr) continue; } else { if(Stream.error != MAD_ERROR_BUFLEN) return -1; else if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr) return -1; } } mad_timer_add(&Timer,Frame.header.duration); mad_synth_frame(&Synth,&Frame); SynthPos = 0; } return 0; }
/* Read up to len samples from p->Synth * If needed, read some more MP3 data, decode them and synth them * Place in buf[]. * Return number of samples read. */ static int mp3_decode(snd_stream_t *stream, byte *buf, int len) { mp3_priv_t *p = (mp3_priv_t *) stream->priv; int donow, i, done = 0; mad_fixed_t sample; int chan, x; do { x = (p->Synth.pcm.length - p->cursamp) * stream->info.channels; donow = min(len, x); i = 0; while (i < donow) { for (chan = 0; chan < stream->info.channels; chan++) { sample = p->Synth.pcm.samples[chan][p->cursamp]; /* convert from fixed to short, * write in host-endian format. */ if (sample <= -MAD_F_ONE) sample = -0x7FFF; else if (sample >= MAD_F_ONE) sample = 0x7FFF; else sample >>= (MAD_F_FRACBITS + 1 - 16); if (host_bigendian) { *buf++ = (sample >> 8) & 0xFF; *buf++ = sample & 0xFF; } else /* assumed LITTLE_ENDIAN. */ { *buf++ = sample & 0xFF; *buf++ = (sample >> 8) & 0xFF; } i++; } p->cursamp++; } len -= donow; done += donow; if (len == 0) break; /* check whether input buffer needs a refill */ if (p->Stream.error == MAD_ERROR_BUFLEN) { if (mp3_inputdata(stream) == -1) { /* check feof() ?? */ Con_DPrintf("mp3 EOF\n"); break; } } if (mad_frame_decode(&p->Frame, &p->Stream)) { if (MAD_RECOVERABLE(p->Stream.error)) { mp3_inputtag(stream); continue; } else { if (p->Stream.error == MAD_ERROR_BUFLEN) continue; else { Con_Printf("MP3: unrecoverable frame level error (%s)\n", mad_stream_errorstr(&p->Stream)); break; } } } p->FrameCount++; mad_timer_add(&p->Timer, p->Frame.header.duration); mad_synth_frame(&p->Synth, &p->Frame); p->cursamp = 0; } while (1);
static int MP3Callback_22k(void *_buf2, unsigned int numSamples, void *pdata) { int i; short *_buf = (short *)_buf2; unsigned long samplesOut = 0; numSamples /= 2; // Playing , so mix up a buffer if (samplesInOutput > 0) { if (samplesInOutput > numSamples) { write22k_buf((short *) _buf, (short *) OutputBuffer, numSamples * 2); samplesOut = numSamples; samplesInOutput -= numSamples; } else { write22k_buf((short *) _buf, (short *) OutputBuffer, samplesInOutput * 2); samplesOut = samplesInOutput; samplesInOutput = 0; } } while (samplesOut < numSamples) { if (Stream.buffer == NULL) { Stream.error = 0; mad_stream_buffer(&Stream, mp3_data, size); } if (Stream.error == MAD_ERROR_BUFLEN) { Stream.error = 0; if (isRepeatMode) { MP3_Restart(); mad_stream_buffer(&Stream, mp3_data, size); samplesInOutput = 0; } else { MP3_Stop(); return 0; } } if (mad_frame_decode(&Frame, &Stream)) { if (MAD_RECOVERABLE(Stream.error)) { return 0; } else if (Stream.error == MAD_ERROR_BUFLEN) { if (! isRepeatMode) { MP3_Stop(); return 0; } } else { MP3_Stop(); } } FrameCount++; mad_timer_add(&Timer, Frame.header.duration); mad_synth_frame(&Synth, &Frame); for (i = 0; i < Synth.pcm.length; i++) { signed short Sample; if (samplesOut < numSamples) { /* Left channel */ Sample = MadFixedToSshort(Synth.pcm.samples[0][i]); _buf[((samplesOut * 2) * 2) ] = Sample; _buf[((samplesOut * 2) * 2) + 1] = Sample; /* Right channel. If the decoded stream is monophonic then * the right output channel is the same as the left one. */ if (MAD_NCHANNELS(&Frame.header) == 2) { Sample = MadFixedToSshort(Synth.pcm.samples[1][i]); } _buf[(((samplesOut * 2) + 1) * 2) ] = Sample; _buf[(((samplesOut * 2) + 1) * 2) + 1] = Sample; samplesOut++; } else { Sample = MadFixedToSshort(Synth.pcm.samples[0][i]); OutputBuffer[samplesInOutput * 2] = Sample; if (MAD_NCHANNELS(&Frame.header) == 2) { Sample = MadFixedToSshort(Synth.pcm.samples[1][i]); } OutputBuffer[samplesInOutput * 2 + 1] = Sample; samplesInOutput++; } } } return isPlaying; }
unsigned int mpgDecoder::decode( float *** data, int count ) { #ifdef HAVE_MAD if(data) *data=returnBuffer; while( mad_outputBuffer[0].canWrite(1152) ) // well letts refill the Input buffer.......... { if( madStream->buffer == NULL || madStream->error == MAD_ERROR_BUFLEN) // well letts refill the Input buffer.......... { size_t readSize, remaining; unsigned char* readStart; unsigned char* guardPtr; if( madFile->atEnd() ) return(0); if(madStream->next_frame) // move remaining bytes to start wich has not been decoded yet... { remaining = mad_inputBuffer + 163840 - madStream->next_frame; memmove( mad_inputBuffer, madStream->next_frame, remaining ); readStart = mad_inputBuffer + remaining; readSize = 163840 - remaining; } else { readSize = 163840; readStart = mad_inputBuffer; remaining = 0; } // get some more Byte from File... unsigned int readCnt = 0; while( !madFile->atEnd() && readCnt < readSize) { readStart[readCnt] = madFile->read(1).at(0); readCnt++; } //bei EOF ein paar GUARD 0Bytes anhaengen die MAD benötigt.. if( madFile->atEnd() ) { guardPtr = readStart + readCnt; memset( guardPtr, 0, MAD_BUFFER_GUARD); readCnt += MAD_BUFFER_GUARD; } mad_stream_buffer( madStream, mad_inputBuffer, readCnt+remaining); madStream->error = MAD_ERROR_NONE; } // well lets decode the buffer and get some Music out of it :-) mad_frame_decode( madFrame, madStream ); frameCounter++; // first MPeg Frame isnt Played cause it contains noisy Metadata if we Play it :D // frame is also not played if we could not decode the whole MPeg frame in case of end of input buffer if(madStream->error==MAD_ERROR_BUFLEN || frameCounter ==1) continue; mad_timer_add( currentPositionTimer, madFrame->header.duration ); mad_synth_frame( madSynth, madFrame ); // decoding done.. convert sampletype... for( unsigned int j=0; j<channels; j++ ) for(unsigned int i=0; i<madSynth->pcm.length; i++ ) { float temp = scale( madSynth->pcm.samples[j][i]); mad_outputBuffer[j].write( &temp, 1 ); } } //nice little workarround so the buffer never gets so much back it wants to.... int dataAvailable = mad_outputBuffer[0].canRead(count*.95)?count*.95:mad_outputBuffer[0].getAvailable()-8; // ensure the return buffer is clean... memset(returnBuffer[0], 0, 8192*sizeof(float)); memset(returnBuffer[1], 0, 8192*sizeof(float)); for( unsigned int j=0; j<channels; j++ ) mad_outputBuffer[j].read( returnBuffer[j], dataAvailable ); return dataAvailable; #endif }
static void MP3Update(void) { int flip; UINT8 *GuardPtr; INT16 *OutputPtr, *OutputEnd; struct mad_stream Stream; struct mad_frame Frame; struct mad_synth Synth; mad_timer_t Timer; mad_stream_init(&Stream); mad_frame_init(&Frame); mad_synth_init(&Synth); mad_timer_reset(&Timer); OutputPtr = (INT16 *)mp3_out[0]; OutputEnd = (INT16 *)(mp3_out[0] + MP3_BUFFER_SIZE); GuardPtr = NULL; mp3_filepos = 0; mp3_frame = 0; flip = 0; cdda_command_ack = 1; while (mp3_active && mp3_status != MP3_STOP) { if (Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN) { UINT32 ReadSize, Remaining; UINT8 *ReadStart; if (Stream.next_frame != NULL) { Remaining = Stream.bufend - Stream.next_frame; ReadStart = mp3_in + Remaining; ReadSize = (2 * MP3_BUFFER_SIZE) - Remaining; memmove(mp3_in, Stream.next_frame, Remaining); } else { ReadSize = 2 * MP3_BUFFER_SIZE; ReadStart = mp3_in; Remaining = 0; } if (MP3SleepCheck()) break; ReadSize = sceIoRead(mp3_fd, ReadStart, ReadSize); mp3_filepos += ReadSize; if (mp3_filepos == mp3_fsize) { if (cdda_autoloop) { mp3_filepos = 0; sceIoLseek(mp3_fd, 0, PSP_SEEK_SET); } else { cdda_playing = CDDA_STOP; mp3_status = MP3_STOP; } } if (mp3_filepos == mp3_fsize) { GuardPtr = ReadStart + ReadSize; memset(GuardPtr, 0, MAD_BUFFER_GUARD); ReadSize += MAD_BUFFER_GUARD; } mad_stream_buffer(&Stream, mp3_in, ReadSize + Remaining); Stream.error = 0; } if (mad_frame_decode(&Frame, &Stream)) { if (MAD_RECOVERABLE(Stream.error)) { // if (Stream.error != MAD_ERROR_LOSTSYNC || Stream.this_frame != GuardPtr) continue; } else if (Stream.error == MAD_ERROR_BUFLEN) { continue; } else { ui_popup(TEXT(MP3_DECODE_ERROR)); mp3_status = MP3_STOP; break; } } mp3_frame++; mad_timer_add(&Timer, Frame.header.duration); mad_synth_frame(&Synth, &Frame); if (mp3_status == MP3_PLAY) { int i; for (i = 0; i < Synth.pcm.length; i++) { if (MAD_NCHANNELS(&Frame.header) == 2) { *OutputPtr++ = MP3Limit(Synth.pcm.samples[0][i]); *OutputPtr++ = MP3Limit(Synth.pcm.samples[1][i]); } else { INT16 data = MP3Limit(Synth.pcm.samples[0][i]); *OutputPtr++ = data; *OutputPtr++ = data; } if (OutputPtr == OutputEnd) { sceAudioOutputPannedBlocking(mp3_handle, mp3_volume, mp3_volume, mp3_out[flip]); flip ^= 1; OutputPtr = (INT16 *)mp3_out[flip]; OutputEnd = (INT16 *)(mp3_out[flip] + MP3_BUFFER_SIZE); } } } else if (mp3_status == MP3_SEEK) { if (mp3_frame >= mp3_start_frame) { mp3_start_frame = 0; mp3_status = MP3_SLEEP; sceKernelSleepThread(); } } } mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); if (mp3_fd >= 0) { sceIoClose(mp3_fd); mp3_fd = -1; } }
bool Mp3AudioFileReader::run(AudioProcessor& processor) { if (file_ == nullptr) { return false; } enum { STATUS_OK, STATUS_INIT_ERROR, STATUS_READ_ERROR, STATUS_PROCESS_ERROR } status = STATUS_OK; unsigned char input_buffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD]; unsigned char* guard_ptr = nullptr; unsigned long frame_count = 0; short output_buffer[OUTPUT_BUFFER_SIZE]; short* output_ptr = output_buffer; const short* const output_buffer_end = output_buffer + OUTPUT_BUFFER_SIZE; int channels = 0; // Decoding options can here be set in the options field of the stream // structure. // {1} When decoding from a file we need to know when the end of the file is // reached at the same time as the last bytes are read (see also the comment // marked {3} below). Neither the standard C fread() function nor the POSIX // read() system call provides this feature. We thus need to perform our // reads through an interface having this feature, this is implemented here // by the bstdfile.c module. BStdFile bstd_file(file_); // Initialize the structures used by libmad. MadStream stream; MadFrame frame; MadSynth synth; mad_timer_t timer; mad_timer_reset(&timer); // This is the decoding loop. for (;;) { // The input bucket must be filled if it becomes empty or if it's the // first execution of the loop. if (stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) { size_t read_size; size_t remaining; unsigned char* read_start; // {2} libmad may not consume all bytes of the input buffer. If the // last frame in the buffer is not wholly contained by it, then that // frame's start is pointed by the next_frame member of the stream // structure. This common situation occurs when mad_frame_decode() // fails, sets the stream error code to MAD_ERROR_BUFLEN, and sets // the next_frame pointer to a non-NULL value. (See also the comment // marked {4} below.) // // When this occurs, the remaining unused bytes must be put back at // the beginning of the buffer and taken in account before refilling // the buffer. This means that the input buffer must be large enough // to hold a whole frame at the highest observable bit-rate // (currently 448 kb/s). XXX=XXX Is 2016 bytes the size of the // largest frame? (448000*(1152/32000))/8 if (stream.next_frame != nullptr) { remaining = stream.bufend - stream.next_frame; memmove(input_buffer, stream.next_frame, remaining); read_start = input_buffer + remaining; read_size = INPUT_BUFFER_SIZE - remaining; } else { read_size = INPUT_BUFFER_SIZE; read_start = input_buffer; remaining = 0; } // Fill-in the buffer. If an error occurs print a message and leave // the decoding loop. If the end of stream is reached we also leave // the loop but the return status is left untouched. read_size = bstd_file.read(read_start, 1, read_size); if (read_size <= 0) { if (ferror(file_)) { error_stream << "\nRead error on bit-stream: " << strerror(errno) << '\n'; status = STATUS_READ_ERROR; } break; } // {3} When decoding the last frame of a file, it must be followed // by MAD_BUFFER_GUARD zero bytes if one wants to decode that last // frame. When the end of file is detected we append that quantity // of bytes at the end of the available data. Note that the buffer // can't overflow as the guard size was allocated but not used the // the buffer management code. (See also the comment marked {1}.) // // In a message to the mad-dev mailing list on May 29th, 2001, Rob // Leslie explains the guard zone as follows: // // "The reason for MAD_BUFFER_GUARD has to do with the way // decoding is performed. In Layer III, Huffman decoding may // inadvertently read a few bytes beyond the end of the buffer in // the case of certain invalid input. This is not detected until // after the fact. To prevent this from causing problems, and // also to ensure the next frame's main_data_begin pointer is // always accessible, MAD requires MAD_BUFFER_GUARD (currently 8) // bytes to be present in the buffer past the end of the current // frame in order to decode the frame." if (bstd_file.eof()) { guard_ptr = read_start + read_size; memset(guard_ptr, 0, MAD_BUFFER_GUARD); read_size += MAD_BUFFER_GUARD; } // Pipe the new buffer content to libmad's stream decoder facility. mad_stream_buffer(&stream, input_buffer, read_size + remaining); stream.error = MAD_ERROR_NONE; } // Decode the next MPEG frame. The streams is read from the buffer, its // constituents are break down and stored the the frame structure, ready // for examination/alteration or PCM synthesis. Decoding options are // carried in the frame structure from the stream structure. // // Error handling: mad_frame_decode() returns a non zero value when an // error occurs. The error condition can be checked in the error member // of the stream structure. A mad error is recoverable or fatal, the // error status is checked with the MAD_RECOVERABLE macro. // // {4} When a fatal error is encountered all decoding activities shall // be stopped, except when a MAD_ERROR_BUFLEN is signaled. This // condition means that the mad_frame_decode() function needs more input // to complete its work. One shall refill the buffer and repeat the // mad_frame_decode() call. Some bytes may be left unused at the end of // the buffer if those bytes forms an incomplete frame. Before // refilling, the remaining bytes must be moved to the beginning of the // buffer and used for input for the next mad_frame_decode() invocation. // (See the comments marked {2} earlier for more details.) // // Recoverable errors are caused by malformed bit-streams, in this case // one can call again mad_frame_decode() in order to skip the faulty // part and re-sync to the next frame. if (mad_frame_decode(&frame, &stream)) { if (MAD_RECOVERABLE(stream.error)) { // Do not print a message if the error is a loss of // synchronization and this loss is due to the end of stream // guard bytes. (See the comment marked {3} above for more // information about guard bytes.) if (stream.error != MAD_ERROR_LOSTSYNC || stream.this_frame != guard_ptr) { // For any MP3 file we typically see two errors in the // first frame processed: // - lost synchronization // - reserved header layer value // This seems to be OK, so don't print these if (frame_count != 0) { error_stream << "\nRecoverable frame level error: " << mad_stream_errorstr(&stream) << '\n'; } } continue; } else { if (stream.error == MAD_ERROR_BUFLEN) { continue; } else { error_stream << "\nUnrecoverable frame level error: " << mad_stream_errorstr(&stream) << '\n'; status = STATUS_READ_ERROR; break; } } } // Display the characteristics of the stream's first frame. The first // frame is representative of the entire stream. if (frame_count == 0) { const int sample_rate = frame.header.samplerate; channels = MAD_NCHANNELS(&frame.header); dumpInfo(output_stream, frame.header); if (!processor.init(sample_rate, channels, OUTPUT_BUFFER_SIZE)) { status = STATUS_PROCESS_ERROR; break; } showProgress(0, file_size_); } // Accounting. The computed frame duration is in the frame header // structure. It is expressed as a fixed point number whole data type is // mad_timer_t. It is different from the samples fixed point format and // unlike it, it can't directly be added or subtracted. The timer module // provides several functions to operate on such numbers. Be careful // there, as some functions of libmad's timer module receive some of // their mad_timer_t arguments by value! frame_count++; mad_timer_add(&timer, frame.header.duration); // Once decoded the frame is synthesized to PCM samples. No errors are // reported by mad_synth_frame(); mad_synth_frame(&synth, &frame); // Synthesized samples must be converted from libmad's fixed point // number to the consumer format. Here we use signed 16 bit integers on // two channels. Integer samples are temporarily stored in a buffer that // is flushed when full. for (int i = 0; i < synth.pcm.length; i++) { // Left channel short sample = MadFixedToSshort(synth.pcm.samples[0][i]); *output_ptr++ = sample; // Right channel. If the decoded stream is monophonic then the right // output channel is the same as the left one. if (MAD_NCHANNELS(&frame.header) == 2) { sample = MadFixedToSshort(synth.pcm.samples[1][i]); *output_ptr++ = sample; } // Flush the output buffer if it is full if (output_ptr == output_buffer_end) { long pos = ftell(file_); showProgress(pos, file_size_); bool success = processor.process( output_buffer, OUTPUT_BUFFER_SIZE / channels ); if (!success) { status = STATUS_PROCESS_ERROR; break; } output_ptr = output_buffer; } } } // If the output buffer is not empty and no error occurred during the last // write, then flush it. if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) { int buffer_size = static_cast<int>(output_ptr - output_buffer); bool success = processor.process(output_buffer, buffer_size / channels); if (!success) { status = STATUS_PROCESS_ERROR; } } // Accounting report if no error occurred. if (status == STATUS_OK) { // Report 100% done. showProgress(file_size_, file_size_); char buffer[80]; // The duration timer is converted to a human readable string with the // versatile, but still constrained mad_timer_string() function, in a // fashion not unlike strftime(). The main difference is that the timer // is broken into several values according some of its arguments. The // units and fracunits arguments specify the intended conversion to be // executed. // // The conversion unit (MAD_UNIT_MINUTES in our example) also specify // the order and kind of conversion specifications that can be used in // the format string. // // It is best to examine libmad's timer.c source-code for details of the // available units, fraction of units, their meanings, the format // arguments, etc. mad_timer_string(timer, buffer, "%lu:%02lu.%03u", MAD_UNITS_MINUTES, MAD_UNITS_MILLISECONDS, 0); output_stream << "\nFrames decoded: " << frame_count << " (" << buffer << ")\n"; } processor.done(); close(); return status == STATUS_OK; }
/* * NAME: parse_time() * DESCRIPTION: parse a time specification string */ static int parse_time(mad_timer_t *timer, char const *str) { mad_timer_t time, accum = mad_timer_zero; signed long decimal; unsigned long seconds, fraction, fracpart; int minus; while (isspace((unsigned char) *str)) ++str; do { seconds = fraction = fracpart = 0; switch (*str) { case '-': ++str; minus = 1; break; case '+': ++str; default: minus = 0; } do { decimal = strtol(str, (char **) &str, 10); if (decimal < 0) return -1; seconds += decimal; if (*str == ':') { seconds *= 60; ++str; } } while (*str >= '0' && *str <= '9'); if (*str == '.' # if defined(HAVE_LOCALECONV) || *str == *localeconv()->decimal_point # endif ) { char const *ptr; decimal = strtol(++str, (char **) &ptr, 10); if (decimal < 0) return -1; fraction = decimal; for (fracpart = 1; str != ptr; ++str) fracpart *= 10; } else if (*str == '/') { ++str; decimal = strtol(str, (char **) &str, 10); if (decimal < 0) return -1; fraction = seconds; fracpart = decimal; seconds = 0; } mad_timer_set(&time, seconds, fraction, fracpart); if (minus) mad_timer_negate(&time); mad_timer_add(&accum, time); } while (*str == '-' || *str == '+'); while (isspace((unsigned char) *str)) ++str; if (*str != 0) return -1; *timer = accum; return 0; }
/* Reads the next frame from the file. Returns true on success or false on failure. */ 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; /* There might be some bytes in the buffer left over from last time. If so, move them down and read more bytes following them. */ 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; } /* Now read additional bytes from the input file. */ read_size = SDL_RWread(mp3_mad->src, 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; } /* At the end of the file, we must stuff MAD_BUFFER_GUARD number of 0 bytes. */ SDL_memset(read_start + read_size, 0, MAD_BUFFER_GUARD); read_size += MAD_BUFFER_GUARD; } } /* Now feed those bytes into the libmad stream. */ mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer, read_size + remaining); mp3_mad->stream.error = MAD_ERROR_NONE; } /* Now ask libmad to extract a frame from the data we just put in its buffer. */ 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 void MP3_getInfo() { int FrameCount = 0; struct mad_stream stream; struct mad_header header; mad_stream_init (&stream); mad_header_init (&header); MP3_info.fileSize = size; mad_timer_reset(&MP3_info.length); mad_stream_buffer (&stream, mp3_data, size); while (1){ if (mad_header_decode (&header, &stream) == -1){ if (MAD_RECOVERABLE(stream.error)){ continue; }else{ break; } } //Informazioni solo dal primo frame: if (FrameCount == 0){ switch (header.layer) { case MAD_LAYER_I: strcpy(MP3_info.layer,"I"); break; case MAD_LAYER_II: strcpy(MP3_info.layer,"II"); break; case MAD_LAYER_III: strcpy(MP3_info.layer,"III"); break; default: strcpy(MP3_info.layer,"unknown"); break; } MP3_info.kbit = header.bitrate / 1000; MP3_info.hz = header.samplerate; switch (header.mode) { case MAD_MODE_SINGLE_CHANNEL: strcpy(MP3_info.mode, "single channel"); break; case MAD_MODE_DUAL_CHANNEL: strcpy(MP3_info.mode, "dual channel"); break; case MAD_MODE_JOINT_STEREO: strcpy(MP3_info.mode, "joint (MS/intensity) stereo"); break; case MAD_MODE_STEREO: strcpy(MP3_info.mode, "normal LR stereo"); break; default: strcpy(MP3_info.mode, "unknown"); break; } switch (header.emphasis) { case MAD_EMPHASIS_NONE: strcpy(MP3_info.emphasis,"no"); break; case MAD_EMPHASIS_50_15_US: strcpy(MP3_info.emphasis,"50/15 us"); break; case MAD_EMPHASIS_CCITT_J_17: strcpy(MP3_info.emphasis,"CCITT J.17"); break; case MAD_EMPHASIS_RESERVED: strcpy(MP3_info.emphasis,"reserved(!)"); break; default: strcpy(MP3_info.emphasis,"unknown"); break; } } FrameCount++; mad_timer_add (&MP3_info.length, header.duration); } mad_header_finish (&header); mad_stream_finish (&stream); MP3_info.frames = FrameCount; mad_timer_string(MP3_info.length, MP3_info.strLength, "%02lu:%02u:%02u", MAD_UNITS_HOURS, MAD_UNITS_MILLISECONDS, 0); }
/* * NAME: main() * DESCRIPTION: program entry point */ int main(int argc, char *argv[]) { struct player player; int result = 0; argv0 = argv[0]; /* ensure binary standard I/O */ # if defined(_WIN32) _setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY); # endif /* internationalization support */ # if defined(ENABLE_NLS) setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); # endif /* initialize and get options */ player_init(&player); # if !defined(__CYGWIN__) /* Cygwin support for this is currently buggy */ /* check for default tty control */ if (isatty(STDIN_FILENO)) player.options |= PLAYER_OPTION_TTYCONTROL; # endif get_options(argc, argv, &player); /* main processing */ if (player.verbosity >= 0) ver_banner(stderr); if (player.options & PLAYER_OPTION_CROSSFADE) { if (!(player.options & PLAYER_OPTION_GAP)) warn(_("cross-fade ignored without gap")); else if (mad_timer_sign(player.gap) >= 0) warn(_("cross-fade ignored without negative gap")); } if (player.output.replay_gain & PLAYER_RGAIN_ENABLED) { if (player.options & PLAYER_OPTION_IGNOREVOLADJ) warn(_("volume adjustment ignored with Replay Gain enabled")); else player.options |= PLAYER_OPTION_IGNOREVOLADJ; } if ((player.options & PLAYER_OPTION_SHOWTAGSONLY) && player.repeat != 1) { warn(_("ignoring repeat")); player.repeat = 1; } /* make stop time absolute */ if (player.options & PLAYER_OPTION_TIMED) mad_timer_add(&player.global_stop, player.global_start); /* get default audio output module */ if (player.output.command == 0 && !(player.options & PLAYER_OPTION_SHOWTAGSONLY)) player.output.command = audio_output(0); # if defined(EXPERIMENTAL) if (external_mix) { player.options |= PLAYER_OPTION_EXTERNALMIX; player.output.command = 0; } if (experimental) player.options |= PLAYER_OPTION_EXPERIMENTAL; # endif /* run the player */ if (player_run(&player, argc - optind, (char const **) &argv[optind]) == -1) result = 4; /* finish up */ player_finish(&player); return result; }
static int mp3_startread(snd_stream_t *stream) { mp3_priv_t *p = (mp3_priv_t *) stream->priv; size_t ReadSize; mad_stream_init(&p->Stream); mad_frame_init(&p->Frame); mad_synth_init(&p->Synth); mad_timer_reset(&p->Timer); /* Decode at least one valid frame to find out the input * format. The decoded frame will be saved off so that it * can be processed later. */ ReadSize = FS_fread(p->mp3_buffer, 1, MP3_BUFFER_SIZE, &stream->fh); if (ReadSize != MP3_BUFFER_SIZE) { if (FS_feof(&stream->fh) || FS_ferror(&stream->fh)) return -1; } mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize); /* Find a valid frame before starting up. This makes sure * that we have a valid MP3 and also skips past ID3v2 tags * at the beginning of the audio file. */ p->Stream.error = MAD_ERROR_NONE; while (mad_frame_decode(&p->Frame,&p->Stream)) { /* check whether input buffer needs a refill */ if (p->Stream.error == MAD_ERROR_BUFLEN) { if (mp3_inputdata(stream) == -1) return -1; continue; } /* Consume any ID3 tags */ mp3_inputtag(stream); /* FIXME: We should probably detect when we've read * a bunch of non-ID3 data and still haven't found a * frame. In that case we can abort early without * scanning the whole file. */ p->Stream.error = MAD_ERROR_NONE; } if (p->Stream.error) { Con_Printf("MP3: No valid MP3 frame found\n"); return -1; } switch(p->Frame.header.mode) { case MAD_MODE_SINGLE_CHANNEL: case MAD_MODE_DUAL_CHANNEL: case MAD_MODE_JOINT_STEREO: case MAD_MODE_STEREO: stream->info.channels = MAD_NCHANNELS(&p->Frame.header); break; default: Con_Printf("MP3: Cannot determine number of channels\n"); return -1; } p->FrameCount = 1; mad_timer_add(&p->Timer,p->Frame.header.duration); mad_synth_frame(&p->Synth,&p->Frame); stream->info.width = MP3_MAD_SAMPLEWIDTH; stream->info.rate = p->Synth.pcm.samplerate; p->cursamp = 0; return 0; }
bool madaudiofile::getNextAudioFrame() { #ifdef HAVE_MAD_H #ifdef MADAUDIO_PRINT_DEBUG printf("Now in getNextAudioFrame()\n"); #endif u_int8_t *OutputPtr = OutputBuffer; u_int8_t *GuardPtr = NULL; while(OutputPtr < OutputBufferEnd) { /* The input bucket must be filled if it becomes empty or if * it's the first execution of the loop. */ if(Stream->buffer==NULL || Stream->error==MAD_ERROR_BUFLEN || frame_count == 0) { size_t ReadSize,Remaining; unsigned char *ReadStart; /* {2} libmad may not consume all bytes of the input * buffer. If the last frame in the buffer is not wholly * contained by it, then that frame's start is pointed by * the next_frame member of the Stream structure. This * common situation occurs when mad_frame_decode() fails, * sets the stream error code to MAD_ERROR_BUFLEN, and * sets the next_frame pointer to a non NULL value. (See * also the comment marked {4} bellow.) * * When this occurs, the remaining unused bytes must be * put back at the beginning of the buffer and taken in * account before refilling the buffer. This means that * the input buffer must be large enough to hold a whole * frame at the highest observable bit-rate (currently 448 * kb/s). XXX=XXX Is 2016 bytes the size of the largest * frame? (448000*(1152/32000))/8 */ if(Stream->next_frame!=NULL) { Remaining=Stream->bufend-Stream->next_frame; memmove(InputBuffer,Stream->next_frame,Remaining); ReadStart=InputBuffer+Remaining; ReadSize=INPUT_BUFFER_SIZE-Remaining; } else ReadSize=INPUT_BUFFER_SIZE, ReadStart=InputBuffer, Remaining=0; /* Fill-in the buffer. If an error occurs print a message * and leave the decoding loop. If the end of stream is * reached we also leave the loop but the return status is * left untouched. */ ReadSize=readData(ReadStart,1,ReadSize,file); if(ReadSize<=0) { break; // probably end of file reached and nothing was read } /* {3} When decoding the last frame of a file, it must be * followed by MAD_BUFFER_GUARD zero bytes if one wants to * decode that last frame. When the end of file is * detected we append that quantity of bytes at the end of * the available data. Note that the buffer can't overflow * as the guard size was allocated but not used the the * buffer management code. (See also the comment marked * {1}.) * * In a message to the mad-dev mailing list on May 29th, * 2001, Rob Leslie explains the guard zone as follows: * * "The reason for MAD_BUFFER_GUARD has to do with the * way decoding is performed. In Layer III, Huffman * decoding may inadvertently read a few bytes beyond * the end of the buffer in the case of certain invalid * input. This is not detected until after the fact. To * prevent this from causing problems, and also to * ensure the next frame's main_data_begin pointer is * always accessible, MAD requires MAD_BUFFER_GUARD * (currently 8) bytes to be present in the buffer past * the end of the current frame in order to decode the * frame." */ if(reachedEOF) { GuardPtr=ReadStart+ReadSize; memset(GuardPtr,0,MAD_BUFFER_GUARD); ReadSize+=MAD_BUFFER_GUARD; } /* Pipe the new buffer content to libmad's stream decoder * facility. */ mad_stream_buffer(Stream,InputBuffer,ReadSize+Remaining); Stream->error=(mad_error)0; } /* Decode the next MPEG frame. The streams is read from the * buffer, its constituents are break down and stored the the * Frame structure, ready for examination/alteration or PCM * synthesis. Decoding options are carried in the Frame * structure from the Stream structure. * * Error handling: mad_frame_decode() returns a non zero value * when an error occurs. The error condition can be checked in * the error member of the Stream structure. A mad error is * recoverable or fatal, the error status is checked with the * MAD_RECOVERABLE macro. * * {4} When a fatal error is encountered all decoding * activities shall be stopped, except when a MAD_ERROR_BUFLEN * is signaled. This condition means that the * mad_frame_decode() function needs more input to complete * its work. One shall refill the buffer and repeat the * mad_frame_decode() call. Some bytes may be left unused at * the end of the buffer if those bytes forms an incomplete * frame. Before refilling, the remaining bytes must be moved * to the beginning of the buffer and used for input for the * next mad_frame_decode() invocation. (See the comments * marked {2} earlier for more details.) * * Recoverable errors are caused by malformed bit-streams, in * this case one can call again mad_frame_decode() in order to * skip the faulty part and re-sync to the next frame. */ if(mad_frame_decode(Frame,Stream)) { if(MAD_RECOVERABLE(Stream->error)) { /* Do not print a message if the error is a loss of * synchronization and this loss is due to the end of * stream guard bytes. (See the comments marked {3} * supra for more informations about guard bytes.) */ if(Stream->error!=MAD_ERROR_LOSTSYNC || Stream->this_frame!=GuardPtr) { } continue; } else if(Stream->error==MAD_ERROR_BUFLEN) continue; // end of buffer reached --> read more from the file else { fprintf(stderr, "madaudiofile: unrecoverable frame level error (%i).\n", Stream->error); break; } } if(frame_count == 0) { samplerate = Frame->header.samplerate; #ifdef MADAUDIO_PRINT_DEBUG printf("Initially setting samplerate to %i\n",samplerate); #endif } #ifdef MADAUDIO_PRINT_DEBUG if(Frame->header.samplerate != samplerate) printf("Obs: samplerate changed to %i!\n",Frame->header.samplerate); #endif /* Accounting. The computed frame duration is in the frame * header structure. It is expressed as a fixed point number * whole data type is mad_timer_t. It is different from the * samples fixed point format and unlike it, it can't directly * be added or subtracted. The timer module provides several * functions to operate on such numbers. Be careful there, as * some functions of libmad's timer module receive some of * their mad_timer_t arguments by value! */ frame_count++; mad_timer_add(Timer,Frame->header.duration); /* Once decoded the frame is synthesized to PCM samples. No errors * are reported by mad_synth_frame(); */ mad_synth_frame(Synth,Frame); /* Synthesized samples must be converted from libmad's fixed * point number to the consumer format. Here we use unsigned * 16 bit big endian integers on two channels. Integer samples * are temporarily stored in a buffer that is flushed when * full. */ int unsigned sr = 0; for(int i=0;i<Synth->pcm.length;i++) { signed short Sample; u_int8_t left[2]; u_int8_t right[2]; /* Left channel */ Sample=MadFixedToSshort(Synth->pcm.samples[0][i]); left[0]=Sample>>8; left[1]=Sample&0xff; /* Right channel. If the decoded stream is monophonic then * the right output channel is the same as the left one. */ if(MAD_NCHANNELS(&Frame->header)==2) Sample=MadFixedToSshort(Synth->pcm.samples[1][i]); right[0]=Sample>>8; right[1]=Sample&0xff; while(sr < samplerate) { /* Left channel */ *(OutputPtr++)=left[1]; *(OutputPtr++)=left[0]; /* Right channel. If the decoded stream is monophonic then * the right output channel is the same as the left one. */ *(OutputPtr++)=right[1]; *(OutputPtr++)=right[0]; sr += Synth->pcm.samplerate; } sr -= samplerate; } if (OutputPtr>=OutputBufferEnd+OUTPUT_BUFFER_SAFETY) { char cstr[200]; sprintf(cstr,"getNextAudioFrame() writing outside of OutputBuffer:" " %p >= %p VERY BAD!!!\n", OutputPtr, OutputBufferEnd+OUTPUT_BUFFER_SAFETY); throw(string(cstr)); } } // while(OutputPtr < OutputBufferEnd) outputLength = OutputPtr-OutputBuffer; outputPosition = 0; if (outputLength == 0) reachedEOF = true; // If we have breaked out of the loop, but it wasn't because of EOF, // return false. if (OutputPtr < OutputBufferEnd && !reachedEOF) return false; return true; #else cerr << "libmad not available" << endl; return false; #endif // HAVE_MAD_H }
static OMX_ERRORTYPE decode_buffer (const void * ap_obj) { mp3d_prc_t * p_obj = (mp3d_prc_t *) ap_obj; unsigned char * p_guardzone = NULL; int status = 0; assert (p_obj->p_outhdr_); /* Check if there is any remaining PCM data from a previous run of the * decoding loop that needs to be synthesised */ if ((0 != p_obj->next_synth_sample_ && p_obj->next_synth_sample_ < p_obj->synth_.pcm.length) && (p_obj->p_outhdr_->nFilledLen < p_obj->p_outhdr_->nAllocLen)) { p_obj->next_synth_sample_ = synthesize_samples (p_obj, p_obj->next_synth_sample_); } while (p_obj->p_outhdr_) { /* The input bucket must be filled if it becomes empty or if * it's the first execution of the loop. */ if ((NULL == p_obj->stream_.buffer || MAD_ERROR_BUFLEN == p_obj->stream_.error) && p_obj->p_inhdr_ != NULL) { size_t read_size = 0; unsigned char * p_read_start = NULL; p_obj->remaining_ = 0; if (p_obj->stream_.next_frame != NULL) { p_obj->remaining_ = p_obj->stream_.bufend - p_obj->stream_.next_frame; memmove (p_obj->in_buff_, p_obj->stream_.next_frame, p_obj->remaining_); p_read_start = p_obj->in_buff_ + p_obj->remaining_; read_size = INPUT_BUFFER_SIZE - p_obj->remaining_; } else { read_size = INPUT_BUFFER_SIZE; p_read_start = p_obj->in_buff_; p_obj->remaining_ = 0; } /* Fill-in the buffer. If an error occurs print a message * and leave the decoding loop. If the end of stream is * reached we also leave the loop but the return status is * left untouched. */ read_size = read_from_omx_buffer (p_obj, p_read_start, read_size, p_obj->p_inhdr_); if (read_size == 0) { if ((p_obj->p_inhdr_->nFlags & OMX_BUFFERFLAG_EOS) != 0) { TIZ_TRACE (handleOf (p_obj), "end of input stream"); status = 2; } else { TIZ_TRACE (handleOf (p_obj), "read_size <= 0"); status = 1; } break; } /* TODO */ /* if(BstdFileEofP (BstdFile)) */ /* { */ /* p_guardzone = p_read_start + read_size; */ /* memset (p_guardzone, 0, MAD_BUFFER_GUARD); */ /* read_size += MAD_BUFFER_GUARD; */ /* } */ /* Pipe the new buffer content to libmad's stream decoder * facility. */ mad_stream_buffer (&p_obj->stream_, p_obj->in_buff_, read_size + p_obj->remaining_); p_obj->stream_.error = 0; } if (mad_frame_decode (&p_obj->frame_, &p_obj->stream_) == -1) { if (MAD_RECOVERABLE (p_obj->stream_.error)) { if (p_obj->stream_.error != MAD_ERROR_LOSTSYNC || p_obj->stream_.this_frame != p_guardzone) { TIZ_TRACE (handleOf (p_obj), "recoverable frame level error (%s)", mad_stream_errorstr (&p_obj->stream_)); } continue; } else { if (p_obj->stream_.error == MAD_ERROR_BUFLEN) { if (!p_obj->p_inhdr_) { TIZ_TRACE (handleOf (p_obj), "p_obj->stream_.error==MAD_ERROR_BUFLEN " "p_obj->p_inhdr_=[NULL]"); break; } else { TIZ_TRACE (handleOf (p_obj), "p_obj->stream_.error==MAD_ERROR_BUFLEN " "p_obj->p_inhdr_=[%p] nFilledLen [%d]", p_obj->p_inhdr_, p_obj->p_inhdr_->nFilledLen); continue; } } else { TIZ_TRACE (handleOf (p_obj), "unrecoverable frame level error (%s).", mad_stream_errorstr (&p_obj->stream_)); status = 2; break; } } } /* The characteristics of the stream's first frame is printed The first * frame is representative of the entire stream. */ if (0 == p_obj->frame_count_) { store_stream_metadata (p_obj, &(p_obj->frame_.header)); } p_obj->frame_count_++; mad_timer_add (&p_obj->timer_, p_obj->frame_.header.duration); /* Once decoded the frame is synthesized to PCM samples. No errors * are reported by mad_synth_frame(); */ mad_synth_frame (&p_obj->synth_, &p_obj->frame_); p_obj->next_synth_sample_ = synthesize_samples (p_obj, p_obj->next_synth_sample_); } (void) status; /* TODO */ /* if (p_obj->p_outhdr_ != NULL */ /* && p_obj->p_outhdr_->nFilledLen != 0 */ /* && status == 2) */ /* { */ /* const tiz_srv_t *p_parent = ap_obj; */ /* void *p_krn = tiz_get_krn (p_parent->p_hdl_); */ /* p_obj->eos_ = true; */ /* p_obj->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; */ /* TIZ_LOG (TIZ_PRIORITY_TRACE, handleOf (p_obj), */ /* "Releasing output buffer [%p] ..." */ /* "nFilledLen = [%d] OMX_BUFFERFLAG_EOS", */ /* p_obj->p_outhdr_, p_obj->p_outhdr_->nFilledLen); */ /* tiz_krn_release_buffer (tiz_get_krn (handleOf (ap_obj)), 1, * p_obj->p_outhdr_); */ /* /\* p_obj->p_outhdr_ = NULL; *\/ */ /* } */ return OMX_ErrorNone; }