Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
    }
}
Exemplo n.º 3
0
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;
}