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