1 #include "sources/soundsourceflac.h"
2 
3 #include "util/logger.h"
4 #include "util/math.h"
5 #include "util/sample.h"
6 
7 namespace mixxx {
8 
9 namespace {
10 
11 const Logger kLogger("SoundSourceFLAC");
12 
13 // The maximum number of retries to fix seek errors. On a seek error
14 // the next seek will start one (or more) sample blocks before the
15 // position of the preceding seek operation that has failed.
16 constexpr int kSeekErrorMaxRetryCount = 3;
17 
18 // begin callbacks (have to be regular functions because normal libFLAC isn't C++-aware)
19 
FLAC_read_cb(const FLAC__StreamDecoder *,FLAC__byte buffer[],size_t * bytes,void * client_data)20 FLAC__StreamDecoderReadStatus FLAC_read_cb(const FLAC__StreamDecoder*,
21         FLAC__byte buffer[],
22         size_t* bytes,
23         void* client_data) {
24     return static_cast<SoundSourceFLAC*>(client_data)->flacRead(buffer, bytes);
25 }
26 
FLAC_seek_cb(const FLAC__StreamDecoder *,FLAC__uint64 absolute_byte_offset,void * client_data)27 FLAC__StreamDecoderSeekStatus FLAC_seek_cb(const FLAC__StreamDecoder*,
28         FLAC__uint64 absolute_byte_offset,
29         void* client_data) {
30     return static_cast<SoundSourceFLAC*>(client_data)->flacSeek(absolute_byte_offset);
31 }
32 
FLAC_tell_cb(const FLAC__StreamDecoder *,FLAC__uint64 * absolute_byte_offset,void * client_data)33 FLAC__StreamDecoderTellStatus FLAC_tell_cb(const FLAC__StreamDecoder*,
34         FLAC__uint64* absolute_byte_offset,
35         void* client_data) {
36     return static_cast<SoundSourceFLAC*>(client_data)->flacTell(absolute_byte_offset);
37 }
38 
FLAC_length_cb(const FLAC__StreamDecoder *,FLAC__uint64 * stream_length,void * client_data)39 FLAC__StreamDecoderLengthStatus FLAC_length_cb(const FLAC__StreamDecoder*,
40         FLAC__uint64* stream_length,
41         void* client_data) {
42     return static_cast<SoundSourceFLAC*>(client_data)->flacLength(stream_length);
43 }
44 
FLAC_eof_cb(const FLAC__StreamDecoder *,void * client_data)45 FLAC__bool FLAC_eof_cb(const FLAC__StreamDecoder*, void* client_data) {
46     return static_cast<SoundSourceFLAC*>(client_data)->flacEOF();
47 }
48 
FLAC_write_cb(const FLAC__StreamDecoder *,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)49 FLAC__StreamDecoderWriteStatus FLAC_write_cb(const FLAC__StreamDecoder*,
50         const FLAC__Frame* frame,
51         const FLAC__int32* const buffer[],
52         void* client_data) {
53     return static_cast<SoundSourceFLAC*>(client_data)->flacWrite(frame, buffer);
54 }
55 
FLAC_metadata_cb(const FLAC__StreamDecoder *,const FLAC__StreamMetadata * metadata,void * client_data)56 void FLAC_metadata_cb(const FLAC__StreamDecoder*,
57         const FLAC__StreamMetadata* metadata,
58         void* client_data) {
59     static_cast<SoundSourceFLAC*>(client_data)->flacMetadata(metadata);
60 }
61 
FLAC_error_cb(const FLAC__StreamDecoder *,FLAC__StreamDecoderErrorStatus status,void * client_data)62 void FLAC_error_cb(const FLAC__StreamDecoder*,
63         FLAC__StreamDecoderErrorStatus status,
64         void* client_data) {
65     static_cast<SoundSourceFLAC*>(client_data)->flacError(status);
66 }
67 
68 // end callbacks
69 
70 const SINT kBitsPerSampleDefault = 0;
71 
72 } // namespace
73 
74 //static
75 const QString SoundSourceProviderFLAC::kDisplayName = QStringLiteral("Xiph.org libFLAC");
76 
77 //static
78 const QStringList SoundSourceProviderFLAC::kSupportedFileExtensions = {
79         QStringLiteral("flac"),
80 };
81 
getPriorityHint(const QString & supportedFileExtension) const82 SoundSourceProviderPriority SoundSourceProviderFLAC::getPriorityHint(
83         const QString& supportedFileExtension) const {
84     Q_UNUSED(supportedFileExtension)
85     // This reference decoder is supposed to produce more accurate
86     // and reliable results than any other DEFAULT provider.
87     return SoundSourceProviderPriority::Higher;
88 }
89 
SoundSourceFLAC(const QUrl & url)90 SoundSourceFLAC::SoundSourceFLAC(const QUrl& url)
91         : SoundSource(url),
92           m_file(getLocalFileName()),
93           m_decoder(nullptr),
94           m_maxBlocksize(0),
95           m_bitsPerSample(kBitsPerSampleDefault),
96           m_curFrameIndex(0) {
97 }
98 
~SoundSourceFLAC()99 SoundSourceFLAC::~SoundSourceFLAC() {
100     close();
101 }
102 
tryOpen(OpenMode,const OpenParams &)103 SoundSource::OpenResult SoundSourceFLAC::tryOpen(
104         OpenMode /*mode*/,
105         const OpenParams& /*config*/) {
106     DEBUG_ASSERT(!m_file.isOpen());
107     if (!m_file.open(QIODevice::ReadOnly)) {
108         kLogger.warning()
109                 << "Failed to open FLAC file:"
110                 << m_file.fileName();
111         return OpenResult::Failed;
112     }
113 
114     m_decoder = FLAC__stream_decoder_new();
115     if (m_decoder == nullptr) {
116         kLogger.warning()
117                 << "Failed to create FLAC decoder!";
118         return OpenResult::Failed;
119     }
120     FLAC__stream_decoder_set_md5_checking(m_decoder, false);
121     const FLAC__StreamDecoderInitStatus initStatus(
122             FLAC__stream_decoder_init_stream(
123                     m_decoder,
124                     FLAC_read_cb,
125                     FLAC_seek_cb,
126                     FLAC_tell_cb,
127                     FLAC_length_cb,
128                     FLAC_eof_cb,
129                     FLAC_write_cb,
130                     FLAC_metadata_cb,
131                     FLAC_error_cb,
132                     this));
133     if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
134         kLogger.warning()
135                 << "Failed to initialize FLAC decoder:"
136                 << initStatus;
137         return OpenResult::Failed;
138     }
139     if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder)) {
140         kLogger.warning()
141                 << "Failed to process FLAC metadata:"
142                 << FLAC__stream_decoder_get_state(m_decoder);
143         return OpenResult::Failed;
144     }
145 
146     m_curFrameIndex = frameIndexMin();
147 
148     return OpenResult::Succeeded;
149 }
150 
close()151 void SoundSourceFLAC::close() {
152     if (m_decoder) {
153         FLAC__stream_decoder_finish(m_decoder);
154         FLAC__stream_decoder_delete(m_decoder); // frees memory
155         m_decoder = nullptr;
156     }
157 
158     m_file.close();
159 }
160 
readSampleFramesClamped(const WritableSampleFrames & writableSampleFrames)161 ReadableSampleFrames SoundSourceFLAC::readSampleFramesClamped(
162         const WritableSampleFrames& writableSampleFrames) {
163     const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start();
164 
165     if (m_curFrameIndex != firstFrameIndex) {
166         // Seek to the new position
167         SINT seekFrameIndex = firstFrameIndex;
168         int retryCount = 0;
169         // NOTE(uklotzde): This loop avoids unnecessary seek operations.
170         // If the file is decoded from the beginning to the end during
171         // continuous playback no seek operations are necessary. This
172         // may hide rare seek errors that we have observed in some "flaky"
173         // FLAC files. The retry strategy implemented by this loop tries
174         // to solve these issues when randomly seeking through such a file.
175         while ((seekFrameIndex != m_curFrameIndex) &&
176                 (retryCount <= kSeekErrorMaxRetryCount)) {
177             // Discard decoded sample data before seeking
178             m_sampleBuffer.clear();
179             invalidateCurFrameIndex();
180             if (FLAC__stream_decoder_seek_absolute(m_decoder, seekFrameIndex)) {
181                 DEBUG_ASSERT(FLAC__STREAM_DECODER_SEEK_ERROR != FLAC__stream_decoder_get_state(m_decoder));
182                 // Success: Set the new position
183                 m_curFrameIndex = seekFrameIndex;
184             } else {
185                 // Failure
186                 kLogger.warning()
187                         << "Seek error at" << seekFrameIndex
188                         << "in file" << m_file.fileName();
189                 if (FLAC__STREAM_DECODER_SEEK_ERROR == FLAC__stream_decoder_get_state(m_decoder)) {
190                     // Flush the input stream of the decoder according to the
191                     // documentation of FLAC__stream_decoder_seek_absolute()
192                     if (!FLAC__stream_decoder_flush(m_decoder)) {
193                         kLogger.warning()
194                                 << "Failed to flush input buffer of the FLAC decoder after seek failure"
195                                 << "in file" << m_file.fileName();
196                         invalidateCurFrameIndex();
197                         // ...and abort
198                         return ReadableSampleFrames(
199                                 IndexRange::between(
200                                         m_curFrameIndex,
201                                         m_curFrameIndex));
202                     }
203                 }
204                 if (frameIndexMin() < seekFrameIndex) {
205                     // The next seek position should start at a preceding sample block.
206                     // By subtracting max. blocksize from the current seek position it
207                     // is guaranteed that the targeted sample blocks of subsequent seek
208                     // operations will differ.
209                     DEBUG_ASSERT(0 < m_maxBlocksize);
210                     seekFrameIndex -= m_maxBlocksize;
211                     if (seekFrameIndex < frameIndexMin()) {
212                         seekFrameIndex = frameIndexMin();
213                     }
214                 } else {
215                     // We have already reached the beginning of the file
216                     // and cannot move the seek position backwards any
217                     // further! As a last resort try to reset the decoder.
218                     kLogger.warning()
219                             << "Resetting decoder after seek errors";
220                     if (!FLAC__stream_decoder_reset(m_decoder)) {
221                         kLogger.critical()
222                                 << "Failed to reset decoder after seek errors";
223                         break; // exit loop
224                     }
225                 }
226             }
227         }
228 
229         // Decoding starts before the actual target position
230         DEBUG_ASSERT(m_curFrameIndex <= firstFrameIndex);
231         const auto precedingFrames =
232                 IndexRange::between(m_curFrameIndex, firstFrameIndex);
233         if (!precedingFrames.empty() &&
234                 (precedingFrames != readSampleFramesClamped(WritableSampleFrames(precedingFrames)).frameIndexRange())) {
235             kLogger.warning()
236                     << "Resetting decoder after failure to skip preceding frames"
237                     << precedingFrames;
238             if (!FLAC__stream_decoder_reset(m_decoder)) {
239                 kLogger.critical()
240                         << "Failed to reset decoder after skip errors";
241             }
242             // Abort
243             return ReadableSampleFrames(
244                     IndexRange::between(
245                             m_curFrameIndex,
246                             m_curFrameIndex));
247         }
248     }
249     DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex);
250 
251     const SINT numberOfSamplesTotal =
252             getSignalInfo().frames2samples(
253                     writableSampleFrames.frameLength());
254 
255     SINT numberOfSamplesRemaining = numberOfSamplesTotal;
256     SINT outputSampleOffset = 0;
257     while (0 < numberOfSamplesRemaining) {
258         // If our buffer from libflac is empty (either because we explicitly cleared
259         // it or because we've simply used all the samples), ask for a new buffer
260         if (m_sampleBuffer.empty()) {
261             // Save the current frame index
262             const SINT curFrameIndexBeforeProcessing = m_curFrameIndex;
263             // Documentation of FLAC__stream_decoder_process_single():
264             // "Depending on what was decoded, the metadata or write callback
265             // will be called with the decoded metadata block or audio frame."
266             // See also: https://xiph.org/flac/api/group__flac__stream__decoder.html#ga9d6df4a39892c05955122cf7f987f856
267             if (!FLAC__stream_decoder_process_single(m_decoder)) {
268                 kLogger.warning()
269                         << "Failed to decode FLAC file"
270                         << m_file.fileName();
271                 break; // abort
272             }
273             // After decoding we might first need to skip some samples if the
274             // decoder complained that it has lost sync for some malformed(?)
275             // files
276             if (m_curFrameIndex != curFrameIndexBeforeProcessing) {
277                 if (m_curFrameIndex < curFrameIndexBeforeProcessing) {
278                     kLogger.warning()
279                             << "Trying to adjust frame index"
280                             << m_curFrameIndex << "<" << curFrameIndexBeforeProcessing
281                             << "while decoding FLAC file"
282                             << m_file.fileName();
283                     const auto skipFrames =
284                             IndexRange::between(m_curFrameIndex, curFrameIndexBeforeProcessing);
285                     if (skipFrames != readSampleFramesClamped(WritableSampleFrames(skipFrames)).frameIndexRange()) {
286                         kLogger.warning()
287                                 << "Failed to skip sample frames"
288                                 << skipFrames
289                                 << "while decoding FLAC file"
290                                 << m_file.fileName();
291                         break; // abort
292                     }
293                 } else {
294                     kLogger.warning()
295                             << "Unexpected frame index"
296                             << m_curFrameIndex << ">" << curFrameIndexBeforeProcessing
297                             << "while decoding FLAC file"
298                             << m_file.fileName();
299                     break; // abort
300                 }
301             }
302             DEBUG_ASSERT(curFrameIndexBeforeProcessing == m_curFrameIndex);
303         }
304         if (m_sampleBuffer.empty()) {
305             break; // EOF
306         }
307 
308         const SINT numberOfSamplesRead =
309                 std::min(m_sampleBuffer.readableLength(), numberOfSamplesRemaining);
310         const SampleBuffer::ReadableSlice readableSlice(
311                 m_sampleBuffer.shrinkForReading(numberOfSamplesRead));
312         DEBUG_ASSERT(readableSlice.length() == numberOfSamplesRead);
313         if (writableSampleFrames.writableData()) {
314             SampleUtil::copy(
315                     writableSampleFrames.writableData(outputSampleOffset),
316                     readableSlice.data(),
317                     readableSlice.length());
318             outputSampleOffset += numberOfSamplesRead;
319         }
320         m_curFrameIndex += getSignalInfo().samples2frames(numberOfSamplesRead);
321         numberOfSamplesRemaining -= numberOfSamplesRead;
322     }
323 
324     DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
325     DEBUG_ASSERT(numberOfSamplesTotal >= numberOfSamplesRemaining);
326     const SINT numberOfSamples = numberOfSamplesTotal - numberOfSamplesRemaining;
327     return ReadableSampleFrames(
328             IndexRange::forward(firstFrameIndex, getSignalInfo().samples2frames(numberOfSamples)),
329             SampleBuffer::ReadableSlice(
330                     writableSampleFrames.writableData(),
331                     std::min(writableSampleFrames.writableLength(), numberOfSamples)));
332 }
333 
334 // flac callback methods
flacRead(FLAC__byte buffer[],size_t * bytes)335 FLAC__StreamDecoderReadStatus SoundSourceFLAC::flacRead(FLAC__byte buffer[],
336         size_t* bytes) {
337     const qint64 maxlen = *bytes;
338     if (0 >= maxlen) {
339         *bytes = 0;
340         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
341     }
342 
343     const qint64 readlen = m_file.read((char*)buffer, maxlen);
344 
345     if (0 < readlen) {
346         *bytes = readlen;
347         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
348     } else {
349         *bytes = 0;
350         if (0 == readlen) {
351             return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
352         } else {
353             return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
354         }
355     }
356 }
357 
flacSeek(FLAC__uint64 absolute_byte_offset)358 FLAC__StreamDecoderSeekStatus SoundSourceFLAC::flacSeek(FLAC__uint64 absolute_byte_offset) {
359     if (m_file.seek(absolute_byte_offset)) {
360         return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
361     } else {
362         kLogger.warning()
363                 << "SoundSourceFLAC: An unrecoverable error occurred ("
364                 << m_file.fileName() << ")";
365         return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
366     }
367 }
368 
flacTell(FLAC__uint64 * offset)369 FLAC__StreamDecoderTellStatus SoundSourceFLAC::flacTell(FLAC__uint64* offset) {
370     if (m_file.isSequential()) {
371         return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
372     }
373     *offset = m_file.pos();
374     return FLAC__STREAM_DECODER_TELL_STATUS_OK;
375 }
376 
flacLength(FLAC__uint64 * length)377 FLAC__StreamDecoderLengthStatus SoundSourceFLAC::flacLength(
378         FLAC__uint64* length) {
379     if (m_file.isSequential()) {
380         return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
381     }
382     *length = m_file.size();
383     return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
384 }
385 
flacEOF()386 FLAC__bool SoundSourceFLAC::flacEOF() {
387     if (m_file.isSequential()) {
388         return false;
389     }
390     return m_file.atEnd();
391 }
392 
393 namespace {
394 
395 // Workaround for improperly encoded FLAC files that may contain
396 // garbage in the most significant, unused bits of decoded samples.
397 // Required at least for libFLAC 1.3.2. This workaround might become
398 // obsolete once libFLAC is taking care of these issues internally.
399 // https://bugs.launchpad.net/mixxx/+bug/1769717
400 // https://hydrogenaud.io/index.php/topic,61792.msg559045.html#msg559045
401 
402 // We multiply the decoded samples by 2 ^ (32 - m_bitsPerSample) to
403 // get rid of the garbage in the most significant bits which get shifted
404 // out to the left. The resulting, upscaled integer value is then scaled
405 // down to the floating point range [-CSAMPLE_PEAK, CSAMPLE_PEAK - epsilon]
406 // with epsilon = 1 / 2 ^ bitsPerSample.
407 //
408 // We have to negate the nominator to compensate for the negative denominator!
409 // Otherwise the phase would be inverted: https://bugs.launchpad.net/mixxx/+bug/1933001
410 constexpr CSAMPLE kSampleScaleFactor = -CSAMPLE_PEAK /
411         (static_cast<FLAC__int32>(1) << std::numeric_limits<FLAC__int32>::digits);
412 
convertDecodedSample(FLAC__int32 decodedSample,int bitsPerSample)413 inline CSAMPLE convertDecodedSample(FLAC__int32 decodedSample, int bitsPerSample) {
414     static_assert(std::numeric_limits<FLAC__int32>::is_signed);
415     static_assert(kSampleScaleFactor > CSAMPLE_ZERO, "preserve phase of decoded signal");
416     // Multiples by 2 ^ (32 - bitsPerSample)
417     const auto upscaleShift = (std::numeric_limits<FLAC__int32>::digits + 1) - bitsPerSample;
418     const auto upscaledSample = decodedSample << upscaleShift;
419     // upscaledSample is now a 32-bit signed integer that needs to scaled
420     // to the range [-CSAMPLE_PEAK, CSAMPLE_PEAK - epsilon]
421     return upscaledSample * kSampleScaleFactor;
422 }
423 
424 } // anonymous namespace
425 
flacWrite(const FLAC__Frame * frame,const FLAC__int32 * const buffer[])426 FLAC__StreamDecoderWriteStatus SoundSourceFLAC::flacWrite(
427         const FLAC__Frame* frame, const FLAC__int32* const buffer[]) {
428     VERIFY_OR_DEBUG_ASSERT(frame->header.channels > 0) {
429         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
430     }
431     const auto channelCount = mixxx::audio::ChannelCount::fromInt(frame->header.channels);
432     if (getSignalInfo().getChannelCount() > channelCount) {
433         kLogger.warning()
434                 << "Corrupt or unsupported FLAC file:"
435                 << "Invalid number of channels in FLAC frame header"
436                 << channelCount << "<>" << getSignalInfo().getChannelCount();
437         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
438     }
439     VERIFY_OR_DEBUG_ASSERT(frame->header.sample_rate > 0) {
440         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
441     }
442     const auto sampleRate = mixxx::audio::SampleRate(frame->header.sample_rate);
443     if (getSignalInfo().getSampleRate() != sampleRate) {
444         kLogger.warning()
445                 << "Corrupt or unsupported FLAC file:"
446                 << "Invalid sample rate in FLAC frame header"
447                 << sampleRate << "<>" << getSignalInfo().getSampleRate();
448         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
449     }
450     const SINT numReadableFrames = frame->header.blocksize;
451     if (numReadableFrames > m_maxBlocksize) {
452         kLogger.warning()
453                 << "Corrupt or unsupported FLAC file:"
454                 << "Block size in FLAC frame header exceeds the maximum block size"
455                 << frame->header.blocksize << ">" << m_maxBlocksize;
456         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
457     }
458 
459     // According to the API docs the decoder will always report the current
460     // position in "FLAC samples" (= "Mixxx frames") for convenience
461     DEBUG_ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
462     m_curFrameIndex = frame->header.number.sample_number;
463 
464     // Decode buffer should be empty before decoding the next frame
465     DEBUG_ASSERT(m_sampleBuffer.empty());
466     const SampleBuffer::WritableSlice writableSlice(
467             m_sampleBuffer.growForWriting(
468                     getSignalInfo().frames2samples(numReadableFrames)));
469 
470     const SINT numWritableFrames =
471             getSignalInfo().samples2frames(writableSlice.length());
472     DEBUG_ASSERT(numWritableFrames <= numReadableFrames);
473     if (numWritableFrames < numReadableFrames) {
474         kLogger.warning()
475                 << "Sample buffer has not enough free space for all decoded FLAC samples:"
476                 << numWritableFrames << "<" << numReadableFrames;
477     }
478 
479     CSAMPLE* pSampleBuffer = writableSlice.data();
480     DEBUG_ASSERT(getSignalInfo().getChannelCount() <= channelCount);
481     switch (getSignalInfo().getChannelCount()) {
482     case 1: {
483         // optimized code for 1 channel (mono)
484         for (SINT i = 0; i < numWritableFrames; ++i) {
485             *pSampleBuffer++ = convertDecodedSample(buffer[0][i], m_bitsPerSample);
486         }
487         break;
488     }
489     case 2: {
490         // optimized code for 2 channels (stereo)
491         for (SINT i = 0; i < numWritableFrames; ++i) {
492             *pSampleBuffer++ = convertDecodedSample(buffer[0][i], m_bitsPerSample);
493             *pSampleBuffer++ = convertDecodedSample(buffer[1][i], m_bitsPerSample);
494         }
495         break;
496     }
497     default: {
498         // generic code for multiple channels
499         for (SINT i = 0; i < numWritableFrames; ++i) {
500             for (SINT j = 0; j < getSignalInfo().getChannelCount(); ++j) {
501                 *pSampleBuffer++ = convertDecodedSample(buffer[j][i], m_bitsPerSample);
502             }
503         }
504     }
505     }
506 
507     return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
508 }
509 
flacMetadata(const FLAC__StreamMetadata * metadata)510 void SoundSourceFLAC::flacMetadata(const FLAC__StreamMetadata* metadata) {
511     // https://xiph.org/flac/api/group__flac__stream__decoder.html#ga43e2329c15731c002ac4182a47990f85
512     // "...one STREAMINFO block, followed by zero or more other metadata blocks."
513     // "...by default the decoder only calls the metadata callback for the STREAMINFO block..."
514     // "...always before the first audio frame (i.e. write callback)."
515     switch (metadata->type) {
516     case FLAC__METADATA_TYPE_STREAMINFO: {
517         initChannelCountOnce(metadata->data.stream_info.channels);
518         initSampleRateOnce(metadata->data.stream_info.sample_rate);
519         initFrameIndexRangeOnce(
520                 IndexRange::forward(
521                         0,
522                         metadata->data.stream_info.total_samples));
523 
524         const SINT bitsPerSample = metadata->data.stream_info.bits_per_sample;
525         DEBUG_ASSERT(bitsPerSample > 0);
526         DEBUG_ASSERT(kBitsPerSampleDefault != bitsPerSample);
527         if (kBitsPerSampleDefault == m_bitsPerSample) {
528             // not set before
529             if ((bitsPerSample >= 4) && (bitsPerSample <= 32)) {
530                 m_bitsPerSample = bitsPerSample;
531             } else {
532                 kLogger.warning()
533                         << "Invalid bits per sample:"
534                         << bitsPerSample;
535             }
536         } else {
537             // already set before -> check for consistency
538             if (bitsPerSample != m_bitsPerSample) {
539                 kLogger.warning()
540                         << "Unexpected bits per sample:"
541                         << bitsPerSample << " <> " << m_bitsPerSample;
542             }
543         }
544         DEBUG_ASSERT(m_maxBlocksize >= 0);
545         m_maxBlocksize = math_max(
546                 m_maxBlocksize,
547                 static_cast<SINT>(metadata->data.stream_info.max_blocksize));
548         if (m_maxBlocksize > 0) {
549             const SINT sampleBufferCapacity =
550                     m_maxBlocksize * getSignalInfo().getChannelCount();
551             if (m_sampleBuffer.capacity() < sampleBufferCapacity) {
552                 m_sampleBuffer.adjustCapacity(sampleBufferCapacity);
553             }
554         } else {
555             kLogger.warning()
556                     << "Invalid max. blocksize" << m_maxBlocksize;
557         }
558         break;
559     }
560     default:
561         // Ignore all other metadata types
562         break;
563     }
564 }
565 
flacError(FLAC__StreamDecoderErrorStatus status)566 void SoundSourceFLAC::flacError(FLAC__StreamDecoderErrorStatus status) {
567     QString error;
568     // not much can be done at this point -- luckly the decoder seems to be
569     // pretty forgiving -- bkgood
570     switch (status) {
571     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
572         error = "STREAM_DECODER_ERROR_STATUS_LOST_SYNC";
573         break;
574     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
575         error = "STREAM_DECODER_ERROR_STATUS_BAD_HEADER";
576         break;
577     case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
578         error = "STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH";
579         break;
580     case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
581         error = "STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM";
582         break;
583     }
584     kLogger.warning()
585             << "FLAC decoding error" << error
586             << "in file" << m_file.fileName();
587     // not much else to do here... whatever function that initiated whatever
588     // decoder method resulted in this error will return an error, and the caller
589     // will bail. libFLAC docs say to not close the decoder here -- bkgood
590 }
591 
592 } // namespace mixxx
593