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; }
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; }
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); } }
SoundSource::OpenResult SoundSourceFLAC::tryOpen( OpenMode /*mode*/, const OpenParams& /*config*/) { DEBUG_ASSERT(!m_file.isOpen()); if (!m_file.open(QIODevice::ReadOnly)) { kLogger.warning() << "Failed to open FLAC file:" << m_file.fileName(); return OpenResult::Failed; } m_decoder = FLAC__stream_decoder_new(); if (m_decoder == nullptr) { kLogger.warning() << "Failed to create FLAC decoder!"; return OpenResult::Failed; } FLAC__stream_decoder_set_md5_checking(m_decoder, false); const FLAC__StreamDecoderInitStatus initStatus( FLAC__stream_decoder_init_stream(m_decoder, FLAC_read_cb, FLAC_seek_cb, FLAC_tell_cb, FLAC_length_cb, FLAC_eof_cb, FLAC_write_cb, FLAC_metadata_cb, FLAC_error_cb, this)); if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { kLogger.warning() << "Failed to initialize FLAC decoder:" << initStatus; return OpenResult::Failed; } if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder)) { kLogger.warning() << "Failed to process FLAC metadata:" << FLAC__stream_decoder_get_state(m_decoder); return OpenResult::Failed; } m_curFrameIndex = frameIndexMin(); return OpenResult::Succeeded; }
FLAC__StreamDecoderState EasyFLAC__get_state(const EasyFLAC__StreamDecoder *decoder) { if (decoder->is_oggflac) return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->oggflac); else return FLAC__stream_decoder_get_state(decoder->flac); }
Result SoundSourceFLAC::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { DEBUG_ASSERT(!m_file.isOpen()); if (!m_file.open(QIODevice::ReadOnly)) { qWarning() << "Failed to open FLAC file:" << m_file.fileName(); return ERR; } m_decoder = FLAC__stream_decoder_new(); if (m_decoder == NULL) { qWarning() << "Failed to create FLAC decoder!"; return ERR; } FLAC__stream_decoder_set_md5_checking(m_decoder, FALSE); const FLAC__StreamDecoderInitStatus initStatus( FLAC__stream_decoder_init_stream(m_decoder, FLAC_read_cb, FLAC_seek_cb, FLAC_tell_cb, FLAC_length_cb, FLAC_eof_cb, FLAC_write_cb, FLAC_metadata_cb, FLAC_error_cb, this)); if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { qWarning() << "Failed to initialize FLAC decoder:" << initStatus; return ERR; } if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder)) { qWarning() << "Failed to process FLAC metadata:" << FLAC__stream_decoder_get_state(m_decoder); return ERR; } m_curFrameIndex = getMinFrameIndex(); return OK; }
bool_t read_metadata(FLAC__StreamDecoder *decoder, callback_info *info) { FLAC__StreamDecoderState ret; reset_info(info); /* Reset the decoder */ if (FLAC__stream_decoder_reset(decoder) == false) { FLACNG_ERROR("Could not reset the decoder!\n"); return FALSE; } /* Try to decode the metadata */ if (FLAC__stream_decoder_process_until_end_of_metadata(decoder) == false) { ret = FLAC__stream_decoder_get_state(decoder); AUDDBG("Could not read the metadata: %s(%d)!\n", FLAC__StreamDecoderStateString[ret], ret); reset_info(info); return FALSE; } return TRUE; }
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; }
int FLAC_plugin__seek(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data) { int pos; FLAC__uint64 target_sample = stream_data->total_samples * stream_data->seek_to / stream_data->length_in_msec; if (stream_data->total_samples > 0 && target_sample >= stream_data->total_samples && target_sample > 0) target_sample = stream_data->total_samples - 1; /* even if the seek fails we have to reset these so that we don't repeat the seek */ stream_data->seek_to = -1; stream_data->eof = false; wide_samples_in_reservoir_ = 0; pos = (int)(target_sample*1000 / stream_data->sample_rate); if (!FLAC__stream_decoder_seek_absolute(decoder, target_sample)) { if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) FLAC__stream_decoder_flush(decoder); pos = -1; } bh_index_last_o = bh_index_last_w = (pos/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE; if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position)) decode_position = 0; return pos; }
void safe_decoder_finish_(FLAC__StreamDecoder *decoder) { if(decoder && FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) (void)FLAC__stream_decoder_finish(decoder); if(stream_data_.is_http_source) flac_http_close(); }
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; }
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; }
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; }
static gboolean gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps) { const GValue *headers; GstFlacDec *flacdec; GstStructure *s; guint i, num; flacdec = GST_FLAC_DEC (dec); GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps); s = gst_caps_get_structure (caps, 0); headers = gst_structure_get_value (s, "streamheader"); if (headers == NULL || !GST_VALUE_HOLDS_ARRAY (headers)) { GST_WARNING_OBJECT (dec, "no 'streamheader' field in input caps, try " "adding a flacparse element upstream"); return FALSE; } if (gst_adapter_available (flacdec->adapter) > 0) { GST_WARNING_OBJECT (dec, "unexpected data left in adapter"); gst_adapter_clear (flacdec->adapter); } num = gst_value_array_get_size (headers); for (i = 0; i < num; ++i) { const GValue *header_val; GstBuffer *header_buf; header_val = gst_value_array_get_value (headers, i); if (header_val == NULL || !GST_VALUE_HOLDS_BUFFER (header_val)) return FALSE; header_buf = g_value_dup_boxed (header_val); GST_INFO_OBJECT (dec, "pushing header buffer of %" G_GSIZE_FORMAT " bytes " "into adapter", gst_buffer_get_size (header_buf)); gst_adapter_push (flacdec->adapter, header_buf); } GST_DEBUG_OBJECT (dec, "Processing headers and metadata"); if (!FLAC__stream_decoder_process_until_end_of_metadata (flacdec->decoder)) { GST_WARNING_OBJECT (dec, "process_until_end_of_metadata failed"); if (FLAC__stream_decoder_get_state (flacdec->decoder) == FLAC__STREAM_DECODER_ABORTED) { GST_WARNING_OBJECT (flacdec, "Read callback caused internal abort"); /* allow recovery */ gst_adapter_clear (flacdec->adapter); FLAC__stream_decoder_flush (flacdec->decoder); gst_flac_dec_handle_decoder_error (flacdec, TRUE); } } GST_INFO_OBJECT (dec, "headers and metadata are now processed"); return TRUE; }
/** * Main. */ int main(int argc, char *argv[]) { FLAC__bool ok = true; FLAC__StreamDecoder* decoder = 0; FLAC__StreamDecoderInitStatus init_status; // init system SystemInit(); RCC_configure(); GPIO_configure(); //TODO // setup UART, LEDs, SDIO, I2S, etc // setup decoder if((decoder = FLAC__stream_decoder_new()) == NULL) { fprintf(stderr, "ERROR: allocating decoder\n"); return 1; } // optional MD5 check. How much cycles does this cost? //FLAC__stream_decoder_set_md5_checking(decoder, true); // init decoder void* client_data = 0; //TODO init_status = FLAC__stream_decoder_init_stream(decoder, read_callback, seek_callback, tell_callback, length_callback, eof_callback, write_callback, metadata_callback, error_callback, client_data); if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { fprintf(stderr, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]); ok = false; } if (ok) { ok = FLAC__stream_decoder_process_until_end_of_stream(decoder); fprintf(stderr, "decoding: %s\n", ok? "succeeded" : "FAILED"); fprintf(stderr, " state: %s\n", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(decoder)]); } // loop forever, just handle IRQs while(1); // never called but usefull to know //FLAC__stream_decoder_delete(decoder); return 0; }
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 FLAC__bool die_s_(const char *msg, const FLAC__StreamDecoder *decoder) { FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(decoder); if(msg) printf("FAILED, %s", msg); else printf("FAILED"); printf(", state = %u (%s)\n", (unsigned)state, FLAC__StreamDecoderStateString[state]); return false; }
FlacReader::FlacReader( MemoryIo* source ) : m_bitdepth( 0 ) , m_channels( 0 ) , m_samplerate( 0 ) , m_decoder( 0 ) , m_source( source ) , m_sourcepos( 0 ) , m_totalsamples( 0 ) { m_decoder = FLAC__stream_decoder_new(); if( !m_decoder ) { throw std::runtime_error( "failed to create the flac decoder" ); } FLAC__StreamDecoderInitStatus status = FLAC__stream_decoder_init_stream( m_decoder, &FlacReader::read_callback, &FlacReader::seek_callback, &FlacReader::tell_callback, &FlacReader::length_callback, &FlacReader::eof_callback, &FlacReader::write_callback, 0, &FlacReader::error_callback, this ); if( status != FLAC__STREAM_DECODER_INIT_STATUS_OK ) { FLAC__stream_decoder_delete( m_decoder ); throw std::runtime_error( FLAC__StreamDecoderInitStatusString[ status ] ); } if( !FLAC__stream_decoder_process_until_end_of_stream( m_decoder ) ) { FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state( m_decoder ); FLAC__stream_decoder_delete( m_decoder ); if( m_error ) { throw StrException( m_error ); } else { throw std::runtime_error( FLAC__StreamDecoderStateString[ state ] ); } } }
double FlacDecoder::SetPosition(double seconds) { FLAC__uint64 seekToSample = (FLAC__uint64)((double) this->sampleRate * seconds); if (FLAC__stream_decoder_seek_absolute(this->decoder, seekToSample)) { return seconds; } if (FLAC__stream_decoder_get_state(this->decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) { if (FLAC__stream_decoder_flush(this->decoder)) { if (FLAC__stream_decoder_seek_absolute(this->decoder, seekToSample)) { return seconds; } } } return -1; }
// soundsource overrides Result SoundSourceFLAC::open() { if (!m_file.open(QIODevice::ReadOnly)) { qWarning() << "SSFLAC: Could not read file!"; return ERR; } m_decoder = FLAC__stream_decoder_new(); if (m_decoder == NULL) { qWarning() << "SSFLAC: decoder allocation failed!"; return ERR; } FLAC__StreamDecoderInitStatus initStatus( FLAC__stream_decoder_init_stream( m_decoder, FLAC_read_cb, FLAC_seek_cb, FLAC_tell_cb, FLAC_length_cb, FLAC_eof_cb, FLAC_write_cb, FLAC_metadata_cb, FLAC_error_cb, (void*) this) ); if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { qWarning() << "SSFLAC: decoder init failed!"; goto decoderError; } if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder)) { qWarning() << "SSFLAC: process to end of meta failed!"; qWarning() << "SSFLAC: decoder state: " << FLAC__stream_decoder_get_state(m_decoder); goto decoderError; } // now number of samples etc. should be populated if (m_flacBuffer == NULL) { // we want 2 samples per frame, see ::flacWrite code -- bkgood m_flacBuffer = new FLAC__int16[m_maxBlocksize * 2 /*m_iChannels*/]; } if (m_leftoverBuffer == NULL) { m_leftoverBuffer = new FLAC__int16[m_maxBlocksize * 2 /*m_iChannels*/]; } // qDebug() << "SSFLAC: Total samples: " << m_samples; // qDebug() << "SSFLAC: Sampling rate: " << m_iSampleRate << " Hz"; // qDebug() << "SSFLAC: Channels: " << m_iChannels; // qDebug() << "SSFLAC: BPS: " << m_bps; return OK; decoderError: FLAC__stream_decoder_finish(m_decoder); FLAC__stream_decoder_delete(m_decoder); m_decoder = NULL; qWarning() << "SSFLAC: Decoder error at file" << m_qFilename; return ERR; }
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; }
int main(int argc, char *argv[]) { FLAC__bool ok = true; FLAC__StreamDecoder *decoder = 0; FLAC__StreamDecoderInitStatus init_status; FILE *fout; if(argc != 3) { fprintf(stderr, "usage: %s infile.flac outfile.wav\n", argv[0]); return 1; } if((fout = fopen(argv[2], "wb")) == NULL) { fprintf(stderr, "ERROR: opening %s for output\n", argv[2]); return 1; } if((decoder = FLAC__stream_decoder_new()) == NULL) { fprintf(stderr, "ERROR: allocating decoder\n"); fclose(fout); return 1; } (void)FLAC__stream_decoder_set_md5_checking(decoder, true); init_status = FLAC__stream_decoder_init_file(decoder, argv[1], write_callback, metadata_callback, error_callback, /*client_data=*/fout); if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { fprintf(stderr, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]); ok = false; } if(ok) { ok = FLAC__stream_decoder_process_until_end_of_stream(decoder); fprintf(stderr, "decoding: %s\n", ok? "succeeded" : "FAILED"); fprintf(stderr, " state: %s\n", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(decoder)]); } FLAC__stream_decoder_delete(decoder); fclose(fout); return 0; }
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; }
static int start_read(sox_format_t * const ft) { priv_t * p = (priv_t *)ft->priv; lsx_debug("API version %u", FLAC_API_VERSION_CURRENT); p->decoder = FLAC__stream_decoder_new(); if (p->decoder == NULL) { lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the decoder instance"); return SOX_EOF; } FLAC__stream_decoder_set_md5_checking(p->decoder, sox_true); FLAC__stream_decoder_set_metadata_respond_all(p->decoder); if (FLAC__stream_decoder_init_FILE(p->decoder, ft->fp, /* Not using SoX IO */ FLAC__frame_decode_callback, FLAC__decoder_metadata_callback, FLAC__decoder_error_callback, ft) != FLAC__STREAM_DECODER_INIT_STATUS_OK){ lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR initialising decoder"); return SOX_EOF; } ft->fp = NULL; /* Transfer ownership of fp to FLAC */ if (!FLAC__stream_decoder_process_until_end_of_metadata(p->decoder)) { lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR whilst decoding metadata"); return SOX_EOF; } if (FLAC__stream_decoder_get_state(p->decoder) > FLAC__STREAM_DECODER_END_OF_STREAM) { lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR during metadata decoding"); return SOX_EOF; } ft->encoding.encoding = SOX_ENCODING_FLAC; ft->signal.rate = p->sample_rate; ft->encoding.bits_per_sample = p->bits_per_sample; ft->signal.channels = p->channels; ft->signal.length = p->total_samples * p->channels; return SOX_SUCCESS; }
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_API FLAC__StreamDecoderState FLAC__seekable_stream_decoder_get_stream_decoder_state(const FLAC__SeekableStreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); return FLAC__stream_decoder_get_state(decoder->private_->stream_decoder); }
bool flac_reader_c::parse_file() { FLAC__StreamDecoderState state; flac_block_t block; uint64_t u, old_pos; int result, progress, old_progress; bool ok; m_in->setFilePointer(0); metadata_parsed = false; mxinfo(Y("+-> Parsing the FLAC file. This can take a LONG time.\n")); init_flac_decoder(); result = FLAC__stream_decoder_process_until_end_of_metadata(m_flac_decoder.get()); mxverb(2, boost::format("flac_reader: extract->metadata, result: %1%, mdp: %2%, num blocks: %3%\n") % result % metadata_parsed % blocks.size()); if (!metadata_parsed) mxerror_fn(m_ti.m_fname, Y("No metadata block found. This file is broken.\n")); FLAC__stream_decoder_get_decode_position(m_flac_decoder.get(), &u); block.type = FLAC_BLOCK_TYPE_HEADERS; block.filepos = 0; block.len = u; old_pos = u; blocks.push_back(block); mxverb(2, boost::format("flac_reader: headers: block at %1% with size %2%\n") % block.filepos % block.len); old_progress = -5; ok = FLAC__stream_decoder_skip_single_frame(m_flac_decoder.get()); while (ok) { state = FLAC__stream_decoder_get_state(m_flac_decoder.get()); progress = m_in->getFilePointer() * 100 / m_size; if ((progress - old_progress) >= 5) { mxinfo(boost::format(Y("+-> Pre-parsing FLAC file: %1%%%%2%")) % progress % "\r"); old_progress = progress; } if (FLAC__stream_decoder_get_decode_position(m_flac_decoder.get(), &u) && (u != old_pos)) { block.type = FLAC_BLOCK_TYPE_DATA; block.filepos = old_pos; block.len = u - old_pos; old_pos = u; blocks.push_back(block); mxverb(2, boost::format("flac_reader: skip/decode frame, block at %1% with size %2%\n") % block.filepos % block.len); } if (state > FLAC__STREAM_DECODER_READ_FRAME) break; ok = FLAC__stream_decoder_skip_single_frame(m_flac_decoder.get()); } if (100 != old_progress) mxinfo(Y("+-> Pre-parsing FLAC file: 100%\n")); else mxinfo("\n"); if ((blocks.size() == 0) || (blocks[0].type != FLAC_BLOCK_TYPE_HEADERS)) mxerror(Y("flac_reader: Could not read all header packets.\n")); m_in->setFilePointer(0); blocks[0].len -= 4; blocks[0].filepos = 4; return metadata_parsed; }