bool FLACStream::seek(const Timestamp &where) { _sampleCache.bufFill = 0; _sampleCache.bufReadPos = NULL; // FLAC uses the sample pair number, thus we always use "false" for the isStereo parameter // of the convertTimeToStreamPos helper. return seekAbsolute((FLAC__uint64)convertTimeToStreamPos(where, getRate(), false).totalNumberOfFrames()); }
int FlacInputStream::readBuffer(int16 *buffer, const int numSamples) { const uint numChannels = getChannels(); if (numChannels == 0) { warning("FlacInputStream: Stream not sucessfully initialised, cant playback"); return -1; // streaminfo wasnt read! } assert(numSamples % numChannels == 0); // must be multiple of channels! assert(buffer != NULL); assert(_outBuffer == NULL); assert(_requestedSamples == 0); _outBuffer = buffer; _requestedSamples = numSamples; // If there is still data in our buffer from the last time around, // copy that first. if (_sampleCache.bufFill > 0) { assert(_sampleCache.bufReadPos >= _sampleCache.bufData); assert(_sampleCache.bufFill % numChannels == 0); const uint copySamples = MIN((uint)numSamples, _sampleCache.bufFill); memcpy(buffer, _sampleCache.bufReadPos, copySamples*sizeof(buffer[0])); _outBuffer = buffer + copySamples; _requestedSamples = numSamples - copySamples; _sampleCache.bufReadPos += copySamples; _sampleCache.bufFill -= copySamples; } bool decoderOk = true; FLAC__StreamDecoderState state = getStreamDecoderState(); // Keep poking FLAC to process more samples until we completely satisfied the request // respectively until we run out of data. while (!_lastSampleWritten && _requestedSamples > 0 && state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) { assert(_sampleCache.bufFill == 0); assert(_requestedSamples % numChannels == 0); processSingleBlock(); state = getStreamDecoderState(); if (state == FLAC__STREAM_DECODER_END_OF_STREAM) { _lastSampleWritten = true; } // If we reached the end of the stream, and looping is enabled: Try to rewind if (_lastSampleWritten && _numLoops != 1) { if (_numLoops != 0) _numLoops--; seekAbsolute(_firstSample); state = getStreamDecoderState(); } } // Error handling switch (state) { case FLAC__STREAM_DECODER_END_OF_STREAM: _lastSampleWritten = true; break; case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: break; default: decoderOk = false; warning("FlacInputStream: An error occured while decoding. DecoderState is: %s", FLAC__StreamDecoderStateString[getStreamDecoderState()]); } // Compute how many samples we actually produced const int samples = (int)(_outBuffer - buffer); assert(samples % numChannels == 0); _outBuffer = NULL; // basically unnecessary, only for the purpose of the asserts _requestedSamples = 0; // basically unnecessary, only for the purpose of the asserts return decoderOk ? samples : -1; }