unsigned int SoundSourceFLAC::read(unsigned long size, const SAMPLE *destination) { if (!m_decoder) return 0; SAMPLE *destBuffer(const_cast<SAMPLE*>(destination)); unsigned int samplesWritten = 0; unsigned int i = 0; while (samplesWritten < size) { // if our buffer from libflac is empty (either because we explicitly cleared // it or because we've simply used all the samples), ask for a new buffer if (m_flacBufferLength == 0) { i = 0; if (!FLAC__stream_decoder_process_single(m_decoder)) { qWarning() << "SSFLAC: decoder_process_single returned false"; break; } else if (m_flacBufferLength == 0) { // EOF break; } } destBuffer[samplesWritten++] = m_flacBuffer[i++]; --m_flacBufferLength; } if (m_flacBufferLength != 0) { memcpy(m_leftoverBuffer, &m_flacBuffer[i], m_flacBufferLength * sizeof(m_flacBuffer[0])); // safe because leftoverBuffer // is as long as flacbuffer memcpy(m_flacBuffer, m_leftoverBuffer, m_flacBufferLength * sizeof(m_leftoverBuffer[0])); // this whole if block could go away if this just used a ring buffer but I'd // rather do that after I've gotten off the inital happiness of getting this right, // if I see SIGSEGV one more time I'll pop -- bkgood } return samplesWritten; }
int FLACInputStream::doRead(int frame_count, void* samples) { const int frame_size = m_channel_count * GetSampleSize(m_sample_format); u8* out = (u8*)samples; // we keep reading till we finish topping up! int frames_read = 0; while (frames_read < frame_count) { // if the buffer is empty, ask FLAC to fill it p if (m_buffer.getSize() < frame_size) { if (!FLAC__stream_decoder_process_single(m_decoder)) { return frames_read; } // if the buffer still has a size of 0, we are probably at the // end of the stream if (m_buffer.getSize() < frame_size) { return frames_read; } } // read what we've got! const int to_read = std::min( frame_count - frames_read, m_buffer.getSize() / frame_size); m_buffer.read(out, to_read * frame_size); out += to_read * frame_size; frames_read += to_read; } return frames_read; }
unsigned int FlacDecoder::fetch(Signal& outleft, Signal& outright) { outleft.reset(); outright.reset(); if (_opened) { unsigned int request_size=Signal::size; while (request_size > _bufferl.size() - _bufferpos) { if (!FLAC__stream_decoder_process_single(_streamdecoder) || (FLAC__stream_decoder_get_state(_streamdecoder) != FLAC__STREAM_DECODER_READ_FRAME && FLAC__stream_decoder_get_state(_streamdecoder) != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC && FLAC__stream_decoder_get_state(_streamdecoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(_streamdecoder) != FLAC__STREAM_DECODER_READ_METADATA )) { break; } } const unsigned int to_read=request_size >_bufferl.size() - _bufferpos ? _bufferl.size() - _bufferpos : request_size; for (unsigned int i=0; i < to_read; i++) { outleft.samples[i]=_bufferl.at(_bufferpos); outright.samples[i]=_bufferr.at(_bufferpos++); } if (to_read == 0) { _ended=true; } return to_read; } _ended=true; return 0; }
int read_flac_file (apr_pool_t* pool,void** file_struct, const char* file_path, encoding_options_t* enc_opt){ FLAC__StreamDecoderInitStatus status; FLAC__bool status2; flac_file_t* flac_file = *file_struct = (flac_file_t*) apr_pcalloc(pool, sizeof(flac_file_t)); flac_file->stream_decoder = FLAC__stream_decoder_new(); flac_file->channels = 0; flac_file->samples = 0; flac_file->total_samples = 0; flac_file->rate = 0; flac_file->buf = NULL; status = FLAC__stream_decoder_init_file(flac_file->stream_decoder, file_path, flac_write, flac_metadata, flac_errors, flac_file); if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK){ return -1; } status2 = FLAC__stream_decoder_process_until_end_of_metadata(flac_file->stream_decoder); if (status2 != true){ return -2; } FLAC__stream_decoder_process_single(flac_file->stream_decoder); if (status2 != true){ return -2; } enc_opt->channels = flac_file->channels; enc_opt->rate = flac_file->rate; enc_opt->total_samples_per_channel = flac_file->total_samples; enc_opt->samples_to_request = 1024; return 0; }
static bool flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, FLAC__uint64 duration) { data->total_frames = duration; if (!FLAC__stream_decoder_process_until_end_of_metadata(sd)) { g_warning("problem reading metadata"); return false; } if (data->initialized) { /* done */ decoder_initialized(data->decoder, &data->audio_format, data->input_stream->seekable, (float)data->total_frames / (float)data->audio_format.sample_rate); return true; } if (data->input_stream->seekable) /* allow the workaround below only for nonseekable streams*/ return false; /* no stream_info packet found; try to initialize the decoder from the first frame header */ FLAC__stream_decoder_process_single(sd); return data->initialized; }
static gint xmms_flac_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err) { FLAC__StreamDecoderState state; xmms_flac_data_t *data; gboolean ret; guint32 size; g_return_val_if_fail (xform, FALSE); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, FALSE); size = MIN (data->buffer->len, len); if (size <= 0) { ret = FLAC__stream_decoder_process_single (data->flacdecoder); } state = FLAC__stream_decoder_get_state (data->flacdecoder); if (state == FLAC__STREAM_DECODER_END_OF_STREAM) { return 0; } size = MIN (data->buffer->len, len); memcpy (buf, data->buffer->str, size); g_string_erase (data->buffer, 0, size); return size; }
static size_t read_samples(sox_format_t * const ft, sox_sample_t * sampleBuffer, size_t const requested) { priv_t * p = (priv_t *)ft->priv; size_t actual = 0; if (p->seek_pending) { p->seek_pending = sox_false; p->wide_sample_number = p->number_of_wide_samples = 0; if (!FLAC__stream_decoder_seek_absolute(p->decoder, (FLAC__uint64)(p->seek_offset / ft->signal.channels))) return 0; } while (!p->eof && actual < requested) { if (p->wide_sample_number >= p->number_of_wide_samples) FLAC__stream_decoder_process_single(p->decoder); if (p->wide_sample_number >= p->number_of_wide_samples) p->eof = sox_true; else { /* FIXME: this block should really be inside the decode callback */ unsigned channel; for (channel = 0; channel < p->channels; channel++, actual++) { FLAC__int32 d = p->decoded_wide_samples[channel][p->wide_sample_number]; switch (p->bits_per_sample) { case 8: *sampleBuffer++ = SOX_SIGNED_8BIT_TO_SAMPLE(d,); break; case 16: *sampleBuffer++ = SOX_SIGNED_16BIT_TO_SAMPLE(d,); break; case 24: *sampleBuffer++ = SOX_SIGNED_24BIT_TO_SAMPLE(d,); break; case 32: *sampleBuffer++ = SOX_SIGNED_32BIT_TO_SAMPLE(d,); break; } } ++p->wide_sample_number; } } return actual; }
long process_flac_file(void* in, float** buffer, int samples){ flac_file_t *flac = (flac_file_t *)in; long realsamples = 0; FLAC__bool ret; int i,j; while (realsamples < samples){ if (flac->buffer_sample_count > 0){ int copy = (flac->buffer_sample_count< (samples - realsamples)) ? flac->buffer_sample_count : (samples - realsamples); for (i = 0; i < flac->channels; i++){ int permute = wav_permute_matrix[flac->channels-1][i]; for (j = 0; j < copy; j++){ buffer[i][j+realsamples] = flac->buf[permute][j+flac->buffer_sample_seek]; } } flac->buffer_sample_seek += copy; flac->buffer_sample_count -= copy; realsamples += copy; }else if (!flac->eos){ ret = FLAC__stream_decoder_process_single(flac->stream_decoder); if (!ret || FLAC__stream_decoder_get_state(flac->stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM){ flac->eos = 1; /* Bail out! */ } }else{ break; } } return realsamples; }
FLAC__bool EasyFLAC__process_single(EasyFLAC__StreamDecoder *decoder) { if (decoder->is_oggflac) return OggFLAC__stream_decoder_process_single(decoder->oggflac); else return FLAC__stream_decoder_process_single(decoder->flac); }
static void flacdecode_play(struct xlplayer *xlplayer) { struct flacdecode_vars *self = xlplayer->dec_data; FLAC__stream_decoder_process_single(self->decoder); if (FLAC__stream_decoder_get_state(self->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) xlplayer->playmode = PM_EJECTING; }
SINT SoundSourceFLAC::seekSampleFrame(SINT frameIndex) { DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(isValidFrameIndex(frameIndex)); // Avoid unnecessary seeking // NOTE(uklotzde): Disabling this optimization might reveal rare // seek errors on certain FLAC files were the decoder loses sync! if (m_curFrameIndex == frameIndex) { return m_curFrameIndex; } // Discard decoded sample data before seeking m_sampleBuffer.reset(); // Seek to the new position if (FLAC__stream_decoder_seek_absolute(m_decoder, frameIndex)) { // Set the new position m_curFrameIndex = frameIndex; DEBUG_ASSERT(FLAC__STREAM_DECODER_SEEK_ERROR != FLAC__stream_decoder_get_state(m_decoder)); } else { qWarning() << "Seek error at" << frameIndex << "in" << m_file.fileName(); // Invalidate the current position m_curFrameIndex = getMaxFrameIndex(); if (FLAC__STREAM_DECODER_SEEK_ERROR == FLAC__stream_decoder_get_state(m_decoder)) { // Flush the input stream of the decoder according to the // documentation of FLAC__stream_decoder_seek_absolute() if (!FLAC__stream_decoder_flush(m_decoder)) { qWarning() << "Failed to flush input buffer of the FLAC decoder after seeking in" << m_file.fileName(); // Invalidate the current position... m_curFrameIndex = getMaxFrameIndex(); // ...and abort return m_curFrameIndex; } // Discard previously decoded sample data before decoding // the next block of samples m_sampleBuffer.reset(); // Trigger decoding of the next block to update the current position if (!FLAC__stream_decoder_process_single(m_decoder)) { qWarning() << "Failed to resync FLAC decoder after seeking in" << m_file.fileName(); // Invalidate the current position... m_curFrameIndex = getMaxFrameIndex(); // ...and abort return m_curFrameIndex; } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); if (m_curFrameIndex < frameIndex) { // Adjust the current position skipSampleFrames(frameIndex - m_curFrameIndex); } } } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); return m_curFrameIndex; }
MediaBuffer *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample) { mWriteRequested = true; mWriteCompleted = false; if (doSeek) { // We implement the seek callback, so this works without explicit flush if (!FLAC__stream_decoder_seek_absolute(mDecoder, sample)) { ALOGE("FLACParser::readBuffer seek to sample %lld failed", (long long)sample); return NULL; } ALOGV("FLACParser::readBuffer seek to sample %lld succeeded", (long long)sample); } else { if (!FLAC__stream_decoder_process_single(mDecoder)) { ALOGE("FLACParser::readBuffer process_single failed"); return NULL; } } if (!mWriteCompleted) { ALOGV("FLACParser::readBuffer write did not complete"); return NULL; } // verify that block header keeps the promises made by STREAMINFO unsigned blocksize = mWriteHeader.blocksize; if (blocksize == 0 || blocksize > getMaxBlockSize()) { ALOGE("FLACParser::readBuffer write invalid blocksize %u", blocksize); return NULL; } if (mWriteHeader.sample_rate != getSampleRate() || mWriteHeader.channels != getChannels() || mWriteHeader.bits_per_sample != getBitsPerSample()) { ALOGE("FLACParser::readBuffer write changed parameters mid-stream: %d/%d/%d -> %d/%d/%d", getSampleRate(), getChannels(), getBitsPerSample(), mWriteHeader.sample_rate, mWriteHeader.channels, mWriteHeader.bits_per_sample); return NULL; } // acquire a media buffer CHECK(mGroup != NULL); MediaBuffer *buffer; status_t err = mGroup->acquire_buffer(&buffer); if (err != OK) { return NULL; } size_t bufferSize = blocksize * getChannels() * sizeof(short); CHECK(bufferSize <= mMaxBufferSize); short *data = (short *) buffer->data(); buffer->set_range(0, bufferSize); // copy PCM from FLAC write buffer to our media buffer, with interleaving (*mCopy)(data, mWriteBuffer, blocksize, getChannels()); // fill in buffer metadata CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number; int64_t timeUs = (1000000LL * sampleNumber) / getSampleRate(); buffer->meta_data()->setInt64(kKeyTime, timeUs); buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); return buffer; }
static GstFlowReturn gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf) { GstFlacDec *dec; dec = GST_FLAC_DEC (audio_dec); /* drain remaining data? */ if (G_UNLIKELY (buf == NULL)) { gst_flac_dec_flush (audio_dec, FALSE); return GST_FLOW_OK; } GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, " "%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf)); /* drop any in-stream headers, we've processed those in set_format already */ if (G_UNLIKELY (!dec->got_headers)) { gboolean got_audio_frame; GstMapInfo map; /* check if this is a flac audio frame (rather than a header or junk) */ gst_buffer_map (buf, &map, GST_MAP_READ); got_audio_frame = gst_flac_dec_scan_got_frame (dec, map.data, map.size, NULL); gst_buffer_unmap (buf, &map); if (!got_audio_frame) { GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " " "bytes", map.size); gst_audio_decoder_finish_frame (audio_dec, NULL, 1); return GST_FLOW_OK; } GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now"); dec->got_headers = TRUE; } gst_adapter_push (dec->adapter, gst_buffer_ref (buf)); buf = NULL; dec->last_flow = GST_FLOW_OK; /* framed - there should always be enough data to decode something */ GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available", gst_adapter_available (dec->adapter)); if (!FLAC__stream_decoder_process_single (dec->decoder)) { GST_INFO_OBJECT (dec, "process_single failed"); } return dec->last_flow; }
static void _LongSound_FLAC_process (LongSound me, long firstSample, long numberOfSamples) { my compressedSamplesLeft = numberOfSamples - 1; if (! FLAC__stream_decoder_seek_absolute (my flacDecoder, firstSample)) Melder_throw (U"Cannot seek in FLAC file ", & my file, U"."); while (my compressedSamplesLeft > 0) { if (FLAC__stream_decoder_get_state (my flacDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM) Melder_throw (U"FLAC file ", & my file, U" too short."); if (! FLAC__stream_decoder_process_single (my flacDecoder)) Melder_throw (U"Error decoding FLAC file ", & my file, U"."); } }
static void flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec, FLAC__uint64 t_start, FLAC__uint64 t_end) { struct decoder *decoder = data->decoder; enum decoder_command cmd; data->first_frame = t_start; while (true) { if (data->tag != NULL && !tag_is_empty(data->tag)) { cmd = decoder_tag(data->decoder, data->input_stream, data->tag); tag_free(data->tag); data->tag = tag_new(); } else cmd = decoder_get_command(decoder); if (cmd == DECODE_COMMAND_SEEK) { FLAC__uint64 seek_sample = t_start + decoder_seek_where(decoder) * data->audio_format.sample_rate; if (seek_sample >= t_start && (t_end == 0 || seek_sample <= t_end) && FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) { data->next_frame = seek_sample; data->position = 0; decoder_command_finished(decoder); } else decoder_seek_error(decoder); } else if (cmd == DECODE_COMMAND_STOP || FLAC__stream_decoder_get_state(flac_dec) == FLAC__STREAM_DECODER_END_OF_STREAM) break; if (t_end != 0 && data->next_frame >= t_end) /* end of this sub track */ break; if (!FLAC__stream_decoder_process_single(flac_dec)) { cmd = decoder_get_command(decoder); if (cmd != DECODE_COMMAND_SEEK) break; } } if (cmd != DECODE_COMMAND_STOP) { flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec)); FLAC__stream_decoder_finish(flac_dec); } }
size_t clFLACDataProvider::StreamWaveData( size_t Size ) { m_BufferUsed = 0; auto State = FLAC__stream_decoder_get_state( m_StreamData->m_Decoder ); while( State < FLAC__STREAM_DECODER_END_OF_STREAM && m_BufferUsed < Size ) { FLAC__bool Result = FLAC__stream_decoder_process_single( m_StreamData->m_Decoder ); State = FLAC__stream_decoder_get_state( m_StreamData->m_Decoder ); } m_IsEndOfStream = State == FLAC__STREAM_DECODER_END_OF_STREAM; return m_BufferUsed; }
static void *flac_thread(void *arg) { FLAC_FEED *feed; feed = (FLAC_FEED *)arg; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&(feed->base.thread_lock)); if (feeds == NULL) feeds = new_unit(); link_unit((MASH_UNIT *)feed, feeds); feed->base.running = 1; while (feed->base.running) { FLAC__stream_decoder_process_single(feed->decoder); pthread_cond_wait(&(feed->base.data_ready), &(feed->base.thread_lock)); } pthread_mutex_unlock(&(feed->base.thread_lock)); return NULL; }
bool FlacDecoder::GetBuffer(IBuffer *buffer) { buffer->SetSampleRate(this->sampleRate); buffer->SetChannels(this->channels); /* read the next chunk */ if (FLAC__stream_decoder_process_single(this->decoder)) { if (this->outputBuffer && this->outputBufferUsed > 0) { buffer->SetSamples(this->outputBufferUsed); memcpy(buffer->BufferPointer(), this->outputBuffer, this->outputBufferUsed * sizeof(float)); this->outputBufferUsed = 0; /* mark consumed */ return true; } } this->exhausted = true; return false; }
FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_single(FLAC__SeekableStreamDecoder *decoder) { FLAC__bool ret; FLAC__ASSERT(0 != decoder); if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) return true; FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK); ret = FLAC__stream_decoder_process_single(decoder->private_->stream_decoder); if(!ret) decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return ret; }
Uint64 SoundFileReaderFlac::read(Int16* samples, Uint64 maxCount) { assert(m_decoder); // If there are leftovers from previous call, use it first Uint64 left = m_clientData.leftovers.size(); if (left > 0) { if (left > maxCount) { // There are more leftovers than needed std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.end(), samples); std::vector<Int16> leftovers(m_clientData.leftovers.begin() + maxCount, m_clientData.leftovers.end()); m_clientData.leftovers.swap(leftovers); return maxCount; } else { // We can use all the leftovers and decode new frames std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.end(), samples); } } // Reset the data that will be used in the callback m_clientData.buffer = samples + left; m_clientData.remaining = maxCount - left; m_clientData.leftovers.clear(); // Decode frames one by one until we reach the requested sample count, the end of file or an error while (m_clientData.remaining > 0) { // Everything happens in the "write" callback // This will break on any fatal error (does not include EOF) if (!FLAC__stream_decoder_process_single(m_decoder)) break; // Break on EOF if (FLAC__stream_decoder_get_state(m_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) break; } return maxCount - m_clientData.remaining; }
clFLACDataProvider::clFLACDataProvider( const std::shared_ptr<clBlob>& Data ) : m_Data( Data ) , m_Format() , m_StreamData( std::make_shared<sFLACStreamData>() ) , m_DecodingBuffer() , m_BufferUsed( 0 ) , m_IsEndOfStream( false ) { { FLAC__StreamDecoderInitStatus Status = FLAC__stream_decoder_init_stream( m_StreamData->m_Decoder, &flacRead, &flacSeek, &flacTell, &flacLength, &flacEof, &flacWrite, &flacMeta, &flacError, this ); } FLAC__bool Status = FLAC__stream_decoder_process_until_end_of_metadata( m_StreamData->m_Decoder ); if ( !Status ) return; if ( !FLAC__stream_decoder_process_single( m_StreamData->m_Decoder ) ) return; m_Format.m_NumChannels = FLAC__stream_decoder_get_channels( m_StreamData->m_Decoder ); m_Format.m_SamplesPerSecond = FLAC__stream_decoder_get_sample_rate( m_StreamData->m_Decoder ); m_Format.m_BitsPerSample = FLAC__stream_decoder_get_bits_per_sample( m_StreamData->m_Decoder ); int BufSize = FLAC__stream_decoder_get_blocksize( m_StreamData->m_Decoder ) * m_Format.m_BitsPerSample * 8 * m_Format.m_NumChannels; // store two blocks m_DecodingBuffer.resize( BufSize * 2 ); int TotalSamples = FLAC__stream_decoder_get_total_samples( m_StreamData->m_Decoder ); }
static int audiosourceflac_InitFLAC(struct audiosource* source) { struct audiosourceflac_internaldata* idata = source->internaldata; // open up FLAC decoder: idata->decoder = FLAC__stream_decoder_new(); if (!idata->decoder) { return 0; } idata->flacopened = 1; // initialise decoder: if (FLAC__stream_decoder_init_stream(idata->decoder, flacread, flacseek, flactell, flaclength, flaceof, flacwrite, flacmetadata, flacerror, source ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { return 0; } // run decoder up to first audio frame: while (idata->decodedbytes == 0) { FLAC__bool b; if ((b = FLAC__stream_decoder_process_single(idata->decoder)) == false || FLAC__stream_decoder_get_state(idata->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) { return 0; } } // we should have some information now return 1; }
/*Read more data for the encoder.*/ static long flac_read(void *client_data,float *buffer,int samples){ flacfile *flac; int channels; float *block_buf; long ret; flac=(flacfile *)client_data; channels=flac->channels; block_buf=flac->block_buf; ret=0; /*Keep reading until we get all the samples or hit an error/EOF. Short reads are not allowed.*/ while(samples>0){ opus_int32 block_buf_pos; opus_int32 block_buf_len; size_t samples_to_copy; block_buf_pos=flac->block_buf_pos; block_buf_len=flac->block_buf_len; if(block_buf_pos>=block_buf_len){ /*Read the next frame from the stream.*/ if(!FLAC__stream_decoder_process_single(flac->decoder))return ret; block_buf_pos=flac->block_buf_pos; block_buf_len=flac->block_buf_len; /*If we didn't get another block, we hit EOF. FLAC__stream_decoder_process_single still returns successfully in this case.*/ if(block_buf_pos>=block_buf_len)return ret; } block_buf_len-=block_buf_pos; samples_to_copy=samples<block_buf_len?samples:block_buf_len; memcpy(buffer,block_buf+block_buf_pos*channels, samples_to_copy*channels*sizeof(*buffer)); flac->block_buf_pos+=samples_to_copy; ret+=samples_to_copy; buffer+=samples_to_copy*channels; samples-=samples_to_copy; } return ret; }
UINT32 OAFLACReader::read(UINT8* samples, UINT32 numSamples) { UINT32 overflowSize = (UINT32)mData.overflow.size(); UINT32 overflowNumSamples = 0; UINT32 bytesPerSample = mData.info.bitDepth / 8; if (overflowSize > 0) { UINT32 sampleSize = numSamples * bytesPerSample; if (overflowSize > sampleSize) { std::copy(mData.overflow.begin(), mData.overflow.begin() + sampleSize, samples); mData.overflow.erase(mData.overflow.begin(), mData.overflow.begin() + sampleSize); return numSamples; } else std::copy(mData.overflow.begin(), mData.overflow.end(), samples); overflowNumSamples = overflowSize / bytesPerSample; } mData.output = samples + overflowSize; mData.samplesToRead = numSamples - overflowNumSamples; mData.overflow.clear(); while (mData.samplesToRead > 0) { if (!FLAC__stream_decoder_process_single(mDecoder)) break; if (FLAC__stream_decoder_get_state(mDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM) break; } return numSamples - mData.samplesToRead; }
CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int /*OutputFd*/, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip) { int rval; // FLAC__uint64 jumptime=0; Status = OK; mState = state; mTimePlayed = time_played; mFrameCount = 0; mSamplesProcessed = 0; struct stat s; FLAC__uint64 filesize = 0; mFlacDec = FLAC__stream_decoder_new(); if (!Open(in, mFlacDec)) { Status=DATA_ERR; return Status; } if (fstat(fileno(in), &s)) { perror("CFlacDec::Decoder fstat"); *time_played = 0; } else filesize = (FLAC__uint64)s.st_size; /* up and away ... */ mSlotSize = MAX_OUTPUT_SAMPLES * 2 * FLAC__stream_decoder_get_channels(mFlacDec); // State oldstate=*state; int jumppos=0; int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; int bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; int bytes_to_play = MSECS_TO_PLAY * meta_data->bitrate / 8000; unsigned int oldSecsToSkip = *secondsToSkip; FLAC__uint64 position; do { while(*state==PAUSE) usleep(10000); if(*state==FF || *state==REV) { if (oldSecsToSkip != *secondsToSkip) { actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; oldSecsToSkip = *secondsToSkip; } printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip); if(std::abs(ftell(in)-jumppos) > bytes_to_play) { if(*state==FF) { fseek(in, bytes_to_skip, SEEK_CUR); jumppos=ftell(in); } else { if(ftell(in) < bytes_to_skip) { fseek(in, 0, SEEK_SET); *state=PLAY; } else { fseek(in, -bytes_to_skip, SEEK_CUR); jumppos=ftell(in); } } } // if a custom value was set we only jump once if (*secondsToSkip != 0) { *state=PLAY; } } if (FLAC__stream_decoder_get_state(mFlacDec) == FLAC__STREAM_DECODER_END_OF_STREAM) { rval = false; break; } rval = FLAC__stream_decoder_process_single(mFlacDec); /* update playback position */ if (filesize > 0 && FLAC__stream_decoder_get_decode_position(mFlacDec, &position)) *time_played = position / 1000ULL * mLengthInMsec / filesize; } while (rval && *state != STOP_REQ && Status == OK); // let buffer run dry printf("let buffer run dry\n"); while (rval == true && *state != STOP_REQ && Status == OK /* && mReadSlot != mWriteSlot*/) { printf("...drying - *state=%x, Status=%x\n", *state, Status); usleep(100000); } /* clean up the junk from the party */ if (mMetadata) FLAC__metadata_object_delete(mMetadata); mMetadata = NULL; FLAC__stream_decoder_finish(mFlacDec); FLAC__stream_decoder_delete(mFlacDec); mFlacDec = NULL; audioDecoder->StopClip(); /* and drive home ;) */ return Status; }
CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int OutputFd, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip) { int rval; //FLAC__uint64 jumptime=0; Status = OK; mOutputFd = OutputFd; mState = state; mTimePlayed = time_played; mFrameCount = 0; mSamplesProcessed = 0; mFlacDec = FLAC__stream_decoder_new(); if (!Open(in, mFlacDec)) { Status=DATA_ERR; return Status; } //test //audioDecoder->PrepareClipPlay(frame->header.channels, frame->header.sample_rate, frame->header.bits_per_sample, 1); //audioDecoder->PrepareClipPlay(2, 16, 16, 1); /* up and away ... */ mSlotSize = MAX_OUTPUT_SAMPLES * 2 * FLAC__stream_decoder_get_channels(mFlacDec); //State oldstate=*state; int jumppos=0; int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; int bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); int bytes_to_play = (int) (1.0 * MSECS_TO_PLAY / 1000 * meta_data->bitrate / 8); unsigned int oldSecsToSkip = *secondsToSkip; //FLAC__uint64 position; do { while(*state==PAUSE) usleep(10000); if(*state==FF || *state==REV) { if (oldSecsToSkip != *secondsToSkip) { actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); oldSecsToSkip = *secondsToSkip; } printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip); if(std::abs(ftell(in)-jumppos) > bytes_to_play) { if(*state==FF) { fseek(in, bytes_to_skip, SEEK_CUR); jumppos=ftell(in); } else { if(ftell(in) < bytes_to_skip) { fseek(in, 0, SEEK_SET); *state=PLAY; } else { fseek(in, -bytes_to_skip, SEEK_CUR); jumppos=ftell(in); } } } // if a custom value was set we only jump once if (*secondsToSkip != 0) { *state=PLAY; } } if (FLAC__stream_decoder_get_state(mFlacDec) == FLAC__STREAM_DECODER_END_OF_STREAM) { rval = false; break; } rval = FLAC__stream_decoder_process_single(mFlacDec); // TODO: calculate time_played from the actual file position so that REW/FF actions will be included *time_played = (mSamplesProcessed * (mLengthInMsec/1000)) / mTotalSamples; } while (rval && *state!=STOP_REQ && Status==OK); // let buffer run dry printf("let buffer run dry\n"); while (rval==true && *state!=STOP_REQ && Status==OK /* && mReadSlot != mWriteSlot*/) { printf("...drying - *state=%x, Status=%x\n", *state, Status); usleep(100000); } if(audioDecoder) audioDecoder->StopClip(); /* clean up the junk from the party */ if (mMetadata) FLAC__metadata_object_delete(mMetadata); mMetadata = NULL; FLAC__stream_decoder_finish(mFlacDec); FLAC__stream_decoder_delete(mFlacDec); mFlacDec = NULL; /* and drive home ;) */ return Status; }
ReadableSampleFrames SoundSourceFLAC::readSampleFramesClamped( WritableSampleFrames writableSampleFrames) { const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start(); if (m_curFrameIndex != firstFrameIndex) { // Seek to the new position SINT seekFrameIndex = firstFrameIndex; int retryCount = 0; // NOTE(uklotzde): This loop avoids unnecessary seek operations. // If the file is decoded from the beginning to the end during // continuous playback no seek operations are necessary. This // may hide rare seek errors that we have observed in some "flaky" // FLAC files. The retry strategy implemented by this loop tries // to solve these issues when randomly seeking through such a file. while ((seekFrameIndex != m_curFrameIndex) && (retryCount <= kSeekErrorMaxRetryCount)) { // Discard decoded sample data before seeking m_sampleBuffer.clear(); invalidateCurFrameIndex(); if (FLAC__stream_decoder_seek_absolute(m_decoder, seekFrameIndex)) { // Success: Set the new position m_curFrameIndex = seekFrameIndex; DEBUG_ASSERT(FLAC__STREAM_DECODER_SEEK_ERROR != FLAC__stream_decoder_get_state(m_decoder)); } else { // Failure kLogger.warning() << "Seek error at" << seekFrameIndex << "in file" << m_file.fileName(); if (FLAC__STREAM_DECODER_SEEK_ERROR == FLAC__stream_decoder_get_state(m_decoder)) { // Flush the input stream of the decoder according to the // documentation of FLAC__stream_decoder_seek_absolute() if (!FLAC__stream_decoder_flush(m_decoder)) { kLogger.warning() << "Failed to flush input buffer of the FLAC decoder after seek failure" << "in file" << m_file.fileName(); invalidateCurFrameIndex(); // ...and abort return ReadableSampleFrames( IndexRange::between( m_curFrameIndex, m_curFrameIndex)); } } if (frameIndexMin() < seekFrameIndex) { // The next seek position should start at a preceding sample block. // By subtracting max. blocksize from the current seek position it // is guaranteed that the targeted sample blocks of subsequent seek // operations will differ. DEBUG_ASSERT(0 < m_maxBlocksize); seekFrameIndex -= m_maxBlocksize; if (seekFrameIndex < frameIndexMin()) { seekFrameIndex = frameIndexMin(); } } else { // We have already reached the beginning of the file // and cannot move the seek position backwards any // further! break; // exit loop } } } // Decoding starts before the actual target position DEBUG_ASSERT(m_curFrameIndex <= firstFrameIndex); const auto precedingFrames = IndexRange::between(m_curFrameIndex, firstFrameIndex); if (!precedingFrames.empty() && (precedingFrames != readSampleFramesClamped(WritableSampleFrames(precedingFrames)).frameIndexRange())) { kLogger.warning() << "Failed to skip preceding frames" << precedingFrames; // Abort return ReadableSampleFrames( IndexRange::between( m_curFrameIndex, m_curFrameIndex)); } } DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex); const SINT numberOfSamplesTotal = frames2samples(writableSampleFrames.frameLength()); SINT numberOfSamplesRemaining = numberOfSamplesTotal; SINT outputSampleOffset = 0; while (0 < numberOfSamplesRemaining) { // If our buffer from libflac is empty (either because we explicitly cleared // it or because we've simply used all the samples), ask for a new buffer if (m_sampleBuffer.empty()) { // Save the current frame index const SINT curFrameIndexBeforeProcessing = m_curFrameIndex; // Documentation of FLAC__stream_decoder_process_single(): // "Depending on what was decoded, the metadata or write callback // will be called with the decoded metadata block or audio frame." // See also: https://xiph.org/flac/api/group__flac__stream__decoder.html#ga9d6df4a39892c05955122cf7f987f856 if (!FLAC__stream_decoder_process_single(m_decoder)) { kLogger.warning() << "Failed to decode FLAC file" << m_file.fileName(); break; // abort } // After decoding we might first need to skip some samples if the // decoder complained that it has lost sync for some malformed(?) // files if (m_curFrameIndex != curFrameIndexBeforeProcessing) { if (m_curFrameIndex < curFrameIndexBeforeProcessing) { kLogger.warning() << "Trying to adjust frame index" << m_curFrameIndex << "<" << curFrameIndexBeforeProcessing << "while decoding FLAC file" << m_file.fileName(); const auto skipFrames = IndexRange::between(m_curFrameIndex, curFrameIndexBeforeProcessing); if (skipFrames != readSampleFramesClamped(WritableSampleFrames(skipFrames)).frameIndexRange()) { kLogger.warning() << "Failed to skip sample frames" << skipFrames << "while decoding FLAC file" << m_file.fileName(); break; // abort } } else { kLogger.warning() << "Unexpected frame index" << m_curFrameIndex << ">" << curFrameIndexBeforeProcessing << "while decoding FLAC file" << m_file.fileName(); break; // abort } } DEBUG_ASSERT(curFrameIndexBeforeProcessing == m_curFrameIndex); } if (m_sampleBuffer.empty()) { break; // EOF } const SINT numberOfSamplesRead = std::min(m_sampleBuffer.readableLength(), numberOfSamplesRemaining); const SampleBuffer::ReadableSlice readableSlice( m_sampleBuffer.shrinkForReading(numberOfSamplesRead)); DEBUG_ASSERT(readableSlice.length() == numberOfSamplesRead); if (writableSampleFrames.writableData()) { SampleUtil::copy( writableSampleFrames.writableData(outputSampleOffset), readableSlice.data(), readableSlice.length()); outputSampleOffset += numberOfSamplesRead; } m_curFrameIndex += samples2frames(numberOfSamplesRead); numberOfSamplesRemaining -= numberOfSamplesRead; } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfSamplesTotal >= numberOfSamplesRemaining); const SINT numberOfSamples = numberOfSamplesTotal - numberOfSamplesRemaining; return ReadableSampleFrames( IndexRange::forward(firstFrameIndex, samples2frames(numberOfSamples)), SampleBuffer::ReadableSlice( writableSampleFrames.writableData(), std::min(writableSampleFrames.writableLength(), numberOfSamples))); }
FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) { FLAC__uint64 first_frame_offset, lower_bound, upper_bound; FLAC__int64 pos = -1, last_pos = -1; int i, lower_seek_point = -1, upper_seek_point = -1; unsigned approx_bytes_per_frame; FLAC__uint64 last_frame_sample = FLAC__U64L(0xffffffffffffffff); FLAC__bool needs_seek; const FLAC__uint64 total_samples = decoder->private_->stream_info.total_samples; const unsigned min_blocksize = decoder->private_->stream_info.min_blocksize; const unsigned max_blocksize = decoder->private_->stream_info.max_blocksize; const unsigned max_framesize = decoder->private_->stream_info.max_framesize; const unsigned channels = FLAC__seekable_stream_decoder_get_channels(decoder); const unsigned bps = FLAC__seekable_stream_decoder_get_bits_per_sample(decoder); /* we are just guessing here, but we want to guess high, not low */ if(max_framesize > 0) { approx_bytes_per_frame = max_framesize; } /* * Check if it's a known fixed-blocksize stream. Note that though * the spec doesn't allow zeroes in the STREAMINFO block, we may * never get a STREAMINFO block when decoding so the value of * min_blocksize might be zero. */ else if(min_blocksize == max_blocksize && min_blocksize > 0) { /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */ approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64; } else approx_bytes_per_frame = 4608 * channels * bps/8 + 64; /* * The decode position is currently at the first frame since we * rewound and processed metadata. */ if(!FLAC__seekable_stream_decoder_get_decode_position(decoder, &first_frame_offset)) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } /* * First, we set an upper and lower bound on where in the * stream we will search. For now we assume the worst case * scenario, which is our best guess at the beginning of * the first and last frames. */ lower_bound = first_frame_offset; /* calc the upper_bound, beyond which we never want to seek */ if(max_framesize > 0) upper_bound = stream_length - (max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */ else upper_bound = stream_length - ((channels * bps * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2); /* * Now we refine the bounds if we have a seektable with * suitable points. Note that according to the spec they * must be ordered by ascending sample number. */ if(0 != decoder->private_->seek_table) { /* find the closest seek point <= target_sample, if it exists */ for(i = (int)decoder->private_->seek_table->num_points - 1; i >= 0; i--) { if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number <= target_sample) break; } if(i >= 0) { /* i.e. we found a suitable seek point... */ lower_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset; lower_seek_point = i; } /* find the closest seek point > target_sample, if it exists */ for(i = 0; i < (int)decoder->private_->seek_table->num_points; i++) { if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number > target_sample) break; } if(i < (int)decoder->private_->seek_table->num_points) { /* i.e. we found a suitable seek point... */ upper_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset; upper_seek_point = i; } } /* * Now guess at where within those bounds our target * sample will be. */ if(lower_seek_point >= 0) { /* first see if our sample is within a few frames of the lower seekpoint */ if(decoder->private_->seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < decoder->private_->seek_table->points[lower_seek_point].sample_number + (decoder->private_->seek_table->points[lower_seek_point].frame_samples * 4)) { pos = (FLAC__int64)lower_bound; } else if(upper_seek_point >= 0) { const FLAC__uint64 target_offset = target_sample - decoder->private_->seek_table->points[lower_seek_point].sample_number; const FLAC__uint64 range_samples = decoder->private_->seek_table->points[upper_seek_point].sample_number - decoder->private_->seek_table->points[lower_seek_point].sample_number; const FLAC__uint64 range_bytes = upper_bound - lower_bound; #if defined _MSC_VER || defined __MINGW32__ /* with VC++ you have to spoon feed it the casting */ pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)(FLAC__int64)target_offset / (double)(FLAC__int64)range_samples * (double)(FLAC__int64)(range_bytes-1)) - approx_bytes_per_frame; #else pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)target_offset / (double)range_samples * (double)(range_bytes-1)) - approx_bytes_per_frame; #endif } } /* * If there's no seek table, we need to use the metadata (if we * have it) and the filelength to estimate the position of the * frame with the correct sample. */ if(pos < 0 && total_samples > 0) { #if defined _MSC_VER || defined __MINGW32__ /* with VC++ you have to spoon feed it the casting */ pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((double)(FLAC__int64)target_sample / (double)(FLAC__int64)total_samples * (double)(FLAC__int64)(stream_length-first_frame_offset-1)) - approx_bytes_per_frame; #else pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((double)target_sample / (double)total_samples * (double)(stream_length-first_frame_offset-1)) - approx_bytes_per_frame; #endif } /* * If there's no seek table and total_samples is unknown, we * don't even bother trying to figure out a target, we just use * our current position. */ if(pos < 0) { FLAC__uint64 upos; if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } pos = (FLAC__int64)upos; needs_seek = false; } else needs_seek = true; /* clip the position to the bounds, lower bound takes precedence */ if(pos >= (FLAC__int64)upper_bound) { pos = (FLAC__int64)upper_bound-1; needs_seek = true; } if(pos < (FLAC__int64)lower_bound) { pos = (FLAC__int64)lower_bound; needs_seek = true; } decoder->private_->target_sample = target_sample; while(1) { if(needs_seek) { if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return false; } } /* Now we need to get a frame. It is possible for our seek * to land in the middle of audio data that looks exactly like * a frame header from a future version of an encoder. When * that happens, FLAC__stream_decoder_process_single() will * return false and the state will be * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. But there is a * remote possibility that it is properly synced at such a * "future-codec frame", so to make sure, we wait to see * several "unparseable" errors in a row before bailing out. */ { unsigned unparseable_count; FLAC__bool got_a_frame = false; for (unparseable_count = 0; !got_a_frame && unparseable_count < 10; unparseable_count++) { if(FLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) got_a_frame = true; else if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_UNPARSEABLE_STREAM) /* try again. we don't want to flush the decoder since that clears the bitbuffer */ decoder->private_->stream_decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; else /* it's a real error */ break; } if (!got_a_frame) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } } /* our write callback will change the state when it gets to the target frame */ if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING) { break; } else { /* we need to narrow the search */ const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number; FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); if(this_frame_sample == last_frame_sample && pos < last_pos) { /* our last move backwards wasn't big enough, double it */ pos -= (last_pos - pos); needs_seek = true; } else { if(target_sample < this_frame_sample) { last_pos = pos; approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * channels * bps/8 + 64; pos -= approx_bytes_per_frame; needs_seek = true; } else { /* target_sample >= this_frame_sample + this frame's blocksize */ FLAC__uint64 upos; if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } last_pos = pos; pos = (FLAC__int64)upos; pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder); needs_seek = false; /* * if we haven't hit the target frame yet and our position hasn't changed, * it means we're at the end of the stream and the seek target does not exist. */ if(last_pos == pos) { decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; return false; } } } if(pos < (FLAC__int64)lower_bound) pos = (FLAC__int64)lower_bound; last_frame_sample = this_frame_sample; } } return true; }
/* read mode: * 0 - no read after seek * 1 - read 2 frames * 2 - read until end */ static FLAC__bool seek_barrage(FLAC__bool is_ogg, const char *filename, off_t filesize, unsigned count, FLAC__int64 total_samples, unsigned read_mode) { FLAC__StreamDecoder *decoder; DecoderClientData decoder_client_data; unsigned i; long int n; decoder_client_data.got_data = false; decoder_client_data.total_samples = 0; decoder_client_data.quiet = false; decoder_client_data.ignore_errors = false; decoder_client_data.error_occurred = false; printf("\n+++ seek test: FLAC__StreamDecoder (%s FLAC, read_mode=%u)\n\n", is_ogg? "Ogg":"native", read_mode); decoder = FLAC__stream_decoder_new(); if(0 == decoder) return die_("FLAC__stream_decoder_new() FAILED, returned NULL\n"); if(is_ogg) { if(FLAC__stream_decoder_init_ogg_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) return die_s_("FLAC__stream_decoder_init_file() FAILED", decoder); } else { if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) return die_s_("FLAC__stream_decoder_init_file() FAILED", decoder); } if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) return die_s_("FLAC__stream_decoder_process_until_end_of_metadata() FAILED", decoder); if(!is_ogg) { /* not necessary to do this for Ogg because of its seeking method */ /* process until end of stream to make sure we can still seek in that state */ decoder_client_data.quiet = true; if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) return die_s_("FLAC__stream_decoder_process_until_end_of_stream() FAILED", decoder); decoder_client_data.quiet = false; printf("stream decoder state is %s\n", FLAC__stream_decoder_get_resolved_state_string(decoder)); if(FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_END_OF_STREAM) return die_s_("expected FLAC__STREAM_DECODER_END_OF_STREAM", decoder); } #ifdef _MSC_VER printf("file's total_samples is %I64u\n", decoder_client_data.total_samples); #else printf("file's total_samples is %llu\n", (unsigned long long)decoder_client_data.total_samples); #endif #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__ if (decoder_client_data.total_samples > (FLAC__uint64)RAND_MAX) { printf("ERROR: must be total_samples < %u\n", (unsigned)RAND_MAX); return false; } #endif n = (long int)decoder_client_data.total_samples; if(n == 0 && total_samples >= 0) n = (long int)total_samples; /* if we don't have a total samples count, just guess based on the file size */ /* @@@ for is_ogg we should get it from last page's granulepos */ if(n == 0) { /* 8 would imply no compression, 9 guarantees that we will get some samples off the end of the stream to test that case */ n = 9 * filesize / (decoder_client_data.channels * decoder_client_data.bits_per_sample); #if !defined _MSC_VER && !defined __MINGW32__ if(n > RAND_MAX) n = RAND_MAX; #endif } printf("Begin seek barrage, count=%u\n", count); for (i = 0; !stop_signal_ && (count == 0 || i < count); i++) { FLAC__uint64 pos; /* for the first 10, seek to the first 10 samples */ if (n >= 10 && i < 10) { pos = i; } /* for the second 10, seek to the last 10 samples */ else if (n >= 10 && i < 20) { pos = n - 1 - (i-10); } /* for the third 10, seek past the end and make sure we fail properly as expected */ else if (i < 30) { pos = n + (i-20); } else { #if !defined _MSC_VER && !defined __MINGW32__ pos = (FLAC__uint64)(random() % n); #else /* RAND_MAX is only 32767 in my MSVC */ pos = (FLAC__uint64)((rand()<<15|rand()) % n); #endif } #ifdef _MSC_VER printf("seek(%I64u)... ", pos); #else printf("seek(%llu)... ", (unsigned long long)pos); #endif fflush(stdout); if(!FLAC__stream_decoder_seek_absolute(decoder, pos)) { if(pos >= (FLAC__uint64)n) printf("seek past end failed as expected... "); else if(decoder_client_data.total_samples == 0 && total_samples <= 0) printf("seek failed, assuming it was past EOF... "); else return die_s_("FLAC__stream_decoder_seek_absolute() FAILED", decoder); if(!FLAC__stream_decoder_flush(decoder)) return die_s_("FLAC__stream_decoder_flush() FAILED", decoder); } else if(read_mode == 1) { printf("decode_frame... "); fflush(stdout); if(!FLAC__stream_decoder_process_single(decoder)) return die_s_("FLAC__stream_decoder_process_single() FAILED", decoder); printf("decode_frame... "); fflush(stdout); if(!FLAC__stream_decoder_process_single(decoder)) return die_s_("FLAC__stream_decoder_process_single() FAILED", decoder); } else if(read_mode == 2) { printf("decode_all... "); fflush(stdout); decoder_client_data.quiet = true; if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) return die_s_("FLAC__stream_decoder_process_until_end_of_stream() FAILED", decoder); decoder_client_data.quiet = false; } printf("OK\n"); fflush(stdout); } if(FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) { if(!FLAC__stream_decoder_finish(decoder)) return die_s_("FLAC__stream_decoder_finish() FAILED", decoder); } FLAC__stream_decoder_delete(decoder); printf("\nPASSED!\n"); return true; }
unsigned FLAC_plugin__decode(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data, char *sample_buffer) { /* fill reservoir */ while (wide_samples_in_reservoir_ < SAMPLES_PER_WRITE) { if (FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) { stream_data->eof = true; break; } else if (!FLAC__stream_decoder_process_single(decoder)) { FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder)); stream_data->eof = true; break; } if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position)) decode_position = 0; } /* output samples */ if (wide_samples_in_reservoir_ > 0) { const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE); const unsigned channels = stream_data->channels; unsigned i; int bytes; if (cfg.replaygain.enable && stream_data->has_replaygain) { bytes = FLAC__replaygain_synthesis__apply_gain( sample_buffer, true, /* little_endian_data_out */ stream_data->output_bits_per_sample == 8, /* unsigned_data_out */ reservoir__, n, channels, stream_data->bits_per_sample, stream_data->output_bits_per_sample, stream_data->replay_scale, cfg.replaygain.hard_limit, cfg.resolution.replaygain.dither, &stream_data->dither_context ); } else { bytes = FLAC__plugin_common__pack_pcm_signed_little_endian( sample_buffer, reservoir__, n, channels, stream_data->bits_per_sample, stream_data->output_bits_per_sample ); } wide_samples_in_reservoir_ -= n; for (i = 0; i < channels; i++) memmove(&reservoir_[i][0], &reservoir_[i][n], sizeof(reservoir_[0][0]) * wide_samples_in_reservoir_); return bytes; } else { stream_data->eof = true; return 0; } }