SoundSource::OpenResult SoundSourceWV::tryOpen( OpenMode /*mode*/, const OpenParams& params) { DEBUG_ASSERT(!m_wpc); char msg[80]; // hold possible error message int openFlags = OPEN_WVC | OPEN_NORMALIZE; if ((params.channelCount() == 1) || (params.channelCount() == 2)) { openFlags |= OPEN_2CH_MAX; } // We use WavpackOpenFileInputEx to support Unicode paths on windows // http://www.wavpack.com/lib_use.txt QString wavPackFileName = getLocalFileName(); m_pWVFile = new QFile(wavPackFileName); m_pWVFile->open(QFile::ReadOnly); QString correctionFileName(wavPackFileName + "c"); if (QFile::exists(correctionFileName)) { // If there is a correction file, open it as well m_pWVCFile = new QFile(correctionFileName); m_pWVCFile->open(QFile::ReadOnly); } m_wpc = WavpackOpenFileInputEx(&s_streamReader, m_pWVFile, m_pWVCFile, msg, openFlags, 0); if (!m_wpc) { kLogger.warning() << "failed to open file : " << msg; return OpenResult::Failed; } setChannelCount(WavpackGetReducedChannels(m_wpc)); setSampleRate(WavpackGetSampleRate(m_wpc)); initFrameIndexRangeOnce( mixxx::IndexRange::forward( 0, WavpackGetNumSamples(m_wpc))); if (WavpackGetMode(m_wpc) & MODE_FLOAT) { m_sampleScaleFactor = CSAMPLE_PEAK; } else { const int bitsPerSample = WavpackGetBitsPerSample(m_wpc); if ((bitsPerSample >= 8) && (bitsPerSample <= 32)) { // Range of signed sample values: [-2 ^ (bitsPerSample - 1), 2 ^ (bitsPerSample - 1) - 1] const uint32_t absSamplePeak = 1u << (bitsPerSample - 1); DEBUG_ASSERT(absSamplePeak > 0); // Scaled range of sample values: [-CSAMPLE_PEAK, CSAMPLE_PEAK) m_sampleScaleFactor = CSAMPLE_PEAK / absSamplePeak; } else { kLogger.warning() << "Invalid bits per sample:" << bitsPerSample; return OpenResult::Aborted; } } m_curFrameIndex = frameIndexMin(); return OpenResult::Succeeded; }
void SoundSourceFLAC::flacMetadata(const FLAC__StreamMetadata* metadata) { // https://xiph.org/flac/api/group__flac__stream__decoder.html#ga43e2329c15731c002ac4182a47990f85 // "...one STREAMINFO block, followed by zero or more other metadata blocks." // "...by default the decoder only calls the metadata callback for the STREAMINFO block..." // "...always before the first audio frame (i.e. write callback)." switch (metadata->type) { case FLAC__METADATA_TYPE_STREAMINFO: { setChannelCount(metadata->data.stream_info.channels); setSampleRate(metadata->data.stream_info.sample_rate); initFrameIndexRangeOnce( IndexRange::forward( 0, metadata->data.stream_info.total_samples)); const unsigned bitsPerSample = metadata->data.stream_info.bits_per_sample; DEBUG_ASSERT(kBitsPerSampleDefault != bitsPerSample); if (kBitsPerSampleDefault == m_bitsPerSample) { // not set before if ((bitsPerSample >= 4) && (bitsPerSample <= 32)) { m_bitsPerSample = bitsPerSample; } else { kLogger.warning() << "Invalid bits per sample:" << bitsPerSample; } } else { // already set before -> check for consistency if (bitsPerSample != m_bitsPerSample) { kLogger.warning() << "Unexpected bits per sample:" << bitsPerSample << " <> " << m_bitsPerSample; } } m_maxBlocksize = metadata->data.stream_info.max_blocksize; if (0 >= m_maxBlocksize) { kLogger.warning() << "Invalid max. blocksize" << m_maxBlocksize; } const SINT sampleBufferCapacity = m_maxBlocksize * channelCount(); if (m_sampleBuffer.capacity() < sampleBufferCapacity) { m_sampleBuffer.adjustCapacity(sampleBufferCapacity); } break; } default: // Ignore all other metadata types break; } }
SoundSource::OpenResult SoundSourceOggVorbis::tryOpen( OpenMode /*mode*/, const OpenParams& /*config*/) { m_pFile = std::make_unique<QFile>(getLocalFileName()); if (!m_pFile->open(QFile::ReadOnly)) { kLogger.warning() << "Failed to open file for" << getUrlString(); return OpenResult::Failed; } const int initDecoderResult = ov_open_callbacks(m_pFile.get(), &m_vf, nullptr, 0, s_callbacks); switch (initDecoderResult) { case 0: // success -> continue break; case OV_ENOTVORBIS: case OV_EVERSION: kLogger.warning() << "Unsupported format in" << getUrlString(); return OpenResult::Aborted; default: kLogger.warning() << "Failed to initialize decoder for" << getUrlString(); return OpenResult::Failed; } if (!ov_seekable(&m_vf)) { kLogger.warning() << "Stream in" << getUrlString() << "is not seekable"; return OpenResult::Aborted; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { kLogger.warning() << "Failed to read stream info from" << getUrlString(); return OpenResult::Failed; } setChannelCount(vi->channels); setSampleRate(vi->rate); if (0 < vi->bitrate_nominal) { initBitrateOnce(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { initBitrateOnce(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { initFrameIndexRangeOnce(IndexRange::forward(0, pcmTotal)); } else { kLogger.warning() << "Failed to read read total length of" << getUrlString(); return OpenResult::Failed; } return OpenResult::Succeeded; }