diff options
author | Uwe Klotz <uwe_klotz@web.de> | 2017-07-30 16:31:57 +0200 |
---|---|---|
committer | Uwe Klotz <uwe_klotz@web.de> | 2017-11-06 22:27:20 +0100 |
commit | 36c51de0a46111c81404bc77a32f1d8abea6f768 (patch) | |
tree | 6f14e1eb49e1e75ad229873e3baed1f63b77e0a7 /plugins | |
parent | a02fa40b6cc7c137089573bb67c87ca1ef7afe75 (diff) |
Introduce next abstraction level of the AudioSource API
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/soundsourcem4a/soundsourcem4a.cpp | 66 | ||||
-rw-r--r-- | plugins/soundsourcem4a/soundsourcem4a.h | 6 | ||||
-rwxr-xr-x | plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp | 50 | ||||
-rwxr-xr-x | plugins/soundsourcemediafoundation/soundsourcemediafoundation.h | 6 | ||||
-rw-r--r-- | plugins/soundsourcewv/soundsourcewv.cpp | 66 | ||||
-rw-r--r-- | plugins/soundsourcewv/soundsourcewv.h | 6 |
6 files changed, 118 insertions, 82 deletions
diff --git a/plugins/soundsourcem4a/soundsourcem4a.cpp b/plugins/soundsourcem4a/soundsourcem4a.cpp index a6b3a00308..2649ee7f07 100644 --- a/plugins/soundsourcem4a/soundsourcem4a.cpp +++ b/plugins/soundsourcem4a/soundsourcem4a.cpp @@ -382,32 +382,33 @@ void SoundSourceM4A::restartDecoding(MP4SampleId sampleBlockId) { m_sampleBuffer.reset(); } -IndexRange SoundSourceM4A::readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) { - auto readableFrames = - adjustReadableFrameIndexRangeAndOutputBuffer( - frameIndexRange, pOutputBuffer); - if (readableFrames.empty()) { - return readableFrames; +ReadableSampleFrames SoundSourceM4A::readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) { + const auto writableSampleFrames = + clampWritableSampleFrames(readMode, sampleFrames); + if (writableSampleFrames.frameIndexRange().empty()) { + return ReadableSampleFrames(writableSampleFrames.frameIndexRange()); } - if (m_curFrameIndex != readableFrames.start()) { + const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start(); + + if (m_curFrameIndex != firstFrameIndex) { // NOTE(uklotzde): Resetting the decoder near to the beginning // of the stream when seeking backwards produces invalid sample // values! As a consequence the seeking test fails. if ((m_curSampleBlockId != MP4_INVALID_SAMPLE_ID) && - (readableFrames.start() < m_curFrameIndex) && - (readableFrames.start() <= (frameIndexMin() + kNumberOfPrefetchFrames))) { + (firstFrameIndex < m_curFrameIndex) && + (firstFrameIndex <= (frameIndexMin() + kNumberOfPrefetchFrames))) { // Workaround: Reset the decoder when seeking near to the beginning // of the stream while decoding. reopenDecoder(); } MP4SampleId sampleBlockId = kSampleBlockIdMin - + (readableFrames.start() / m_framesPerSampleBlock); + + (firstFrameIndex / m_framesPerSampleBlock); DEBUG_ASSERT(isValidSampleBlockId(sampleBlockId)); - if ((readableFrames.start() < m_curFrameIndex) || // seeking backwards? + if ((firstFrameIndex < m_curFrameIndex) || // seeking backwards? !isValidSampleBlockId(m_curSampleBlockId) || // invalid seek position? (sampleBlockId > (m_curSampleBlockId + m_numberOfPrefetchSampleBlocks))) { // jumping forward? @@ -426,20 +427,25 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( } // Decoding starts before the actual target position - DEBUG_ASSERT(m_curFrameIndex <= readableFrames.start()); + DEBUG_ASSERT(m_curFrameIndex <= firstFrameIndex); const auto precedingFrames = - IndexRange::between(m_curFrameIndex, readableFrames.start()); + IndexRange::between(m_curFrameIndex, firstFrameIndex); if (!precedingFrames.empty() && (precedingFrames != skipSampleFrames(precedingFrames))) { kLogger.warning() << "Failed to skip preceding frames" << precedingFrames; - return IndexRange(); + // Abort + return ReadableSampleFrames( + IndexRange::between( + m_curFrameIndex, + m_curFrameIndex)); } } - DEBUG_ASSERT(m_curFrameIndex == readableFrames.start()); + DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex); + + const SINT numberOfSamplesTotal = frames2samples(writableSampleFrames.frameIndexRange().length()); - const SINT numberOfSamplesTotal = frames2samples(readableFrames.length()); SINT numberOfSamplesRemaining = numberOfSamplesTotal; SINT outputSampleOffset = 0; while (0 < numberOfSamplesRemaining) { @@ -448,9 +454,9 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( // Consume previously decoded sample data const SampleBuffer::ReadableSlice readableSlice( m_sampleBuffer.readFromHead(numberOfSamplesRemaining)); - if (pOutputBuffer) { + if (readMode == ReadMode::Store) { SampleUtil::copy( - pOutputBuffer->data(outputSampleOffset), + writableSampleFrames.sampleBuffer().data(outputSampleOffset), readableSlice.data(), readableSlice.size()); outputSampleOffset += readableSlice.size(); @@ -499,9 +505,10 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( CSAMPLE* pDecodeBuffer; // in/out parameter SINT decodeBufferCapacity; const SINT decodeBufferCapacityMin = frames2samples(m_framesPerSampleBlock); - if (pOutputBuffer && (decodeBufferCapacityMin <= numberOfSamplesRemaining)) { + if ((readMode == ReadMode::Store) && + (decodeBufferCapacityMin <= numberOfSamplesRemaining)) { // Decode samples directly into the output buffer - pDecodeBuffer = pOutputBuffer->data(outputSampleOffset); + pDecodeBuffer = writableSampleFrames.sampleBuffer().data(outputSampleOffset); decodeBufferCapacity = numberOfSamplesRemaining; } else { // Decode next sample block into temporary buffer @@ -555,7 +562,8 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( const SINT numberOfSamplesDecoded = decFrameInfo.samples; DEBUG_ASSERT(numberOfSamplesDecoded <= decodeBufferCapacity); SINT numberOfSamplesRead; - if (pOutputBuffer && (pDecodeBuffer == pOutputBuffer->data(outputSampleOffset))) { + if ((readMode == ReadMode::Store) && + (pDecodeBuffer == writableSampleFrames.sampleBuffer().data(outputSampleOffset))) { // Decoded in-place DEBUG_ASSERT(numberOfSamplesDecoded <= numberOfSamplesRemaining); numberOfSamplesRead = numberOfSamplesDecoded; @@ -572,9 +580,9 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( const SampleBuffer::ReadableSlice readableSlice( m_sampleBuffer.readFromHead(numberOfSamplesRead)); DEBUG_ASSERT(readableSlice.size() == numberOfSamplesRead); - if (pOutputBuffer) { + if (readMode == ReadMode::Store) { SampleUtil::copy( - pOutputBuffer->data(outputSampleOffset), + writableSampleFrames.sampleBuffer().data(outputSampleOffset), readableSlice.data(), readableSlice.size()); outputSampleOffset += numberOfSamplesRead; @@ -590,8 +598,12 @@ IndexRange SoundSourceM4A::readOrSkipSampleFrames( DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfSamplesTotal >= numberOfSamplesRemaining); - return readableFrames.cutFrontRange( - samples2frames(numberOfSamplesTotal - numberOfSamplesRemaining)); + const SINT numberOfSamples = numberOfSamplesTotal - numberOfSamplesRemaining; + return ReadableSampleFrames( + IndexRange::forward(firstFrameIndex, samples2frames(numberOfSamples)), + SampleBuffer::ReadableSlice( + writableSampleFrames.sampleBuffer().data(), + std::min(writableSampleFrames.sampleBuffer().size(), numberOfSamples))); } QString SoundSourceProviderM4A::getName() const { diff --git a/plugins/soundsourcem4a/soundsourcem4a.h b/plugins/soundsourcem4a/soundsourcem4a.h index e8f1950967..94088b8363 100644 --- a/plugins/soundsourcem4a/soundsourcem4a.h +++ b/plugins/soundsourcem4a/soundsourcem4a.h @@ -24,9 +24,9 @@ public: void close() override; - IndexRange readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) override; + ReadableSampleFrames readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) override; private: OpenResult tryOpen(const AudioSourceConfig& audioSrcCfg) override; diff --git a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp index d69b7d3e1a..a078b8f1dd 100755 --- a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp +++ b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp @@ -238,26 +238,35 @@ void SoundSourceMediaFoundation::seekSampleFrame(SINT frameIndex) { } } -IndexRange SoundSourceMediaFoundation::readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) { - auto readableFrames = - adjustReadableFrameIndexRangeAndOutputBuffer( - frameIndexRange, pOutputBuffer); - if (readableFrames.empty()) { - return readableFrames; - } - - seekSampleFrame(readableFrames.start()); - if (m_currentFrameIndex != readableFrames.start()) { +ReadableSampleFrames SoundSourceMediaFoundation::readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) { + const auto writableSampleFrames = + clampWritableSampleFrames(readMode, sampleFrames); + if (writableSampleFrames.frameIndexRange().empty()) { + return ReadableSampleFrames(writableSampleFrames.frameIndexRange()); + } + + const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start(); + + seekSampleFrame(firstFrameIndex); + if (m_currentFrameIndex != firstFrameIndex) { kLogger.warning() << "Failed to position reader at beginning of decoding range" - << readableFrames; - return mixxx::IndexRange(); // abort + << writableSampleFrames.frameIndexRange(); + // Abort + return ReadableSampleFrames( + mixxx::IndexRange::between( + m_currentFrameIndex, + m_currentFrameIndex)); } + DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex); + + const SINT numberOfFramesTotal = writableSampleFrames.frameIndexRange().length(); - SINT numberOfFramesRemaining = readableFrames.length(); - CSAMPLE* pSampleBuffer = pOutputBuffer ? pOutputBuffer->data() : nullptr; + CSAMPLE* pSampleBuffer = (readMode == ReadMode::Store) ? + writableSampleFrames.sampleBuffer().data() : nullptr; + SINT numberOfFramesRemaining = numberOfFramesTotal; while (numberOfFramesRemaining > 0) { SampleBuffer::ReadableSlice readableSlice( m_sampleBuffer.readFromHead( @@ -452,7 +461,14 @@ IndexRange SoundSourceMediaFoundation::readOrSkipSampleFrames( } } - return readableFrames.cutFrontRange(readableFrames.length() - numberOfFramesRemaining); + DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); + DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining); + const SINT numberOfFrames = numberOfFramesTotal - numberOfFramesRemaining; + return ReadableSampleFrames( + IndexRange::forward(firstFrameIndex, numberOfFrames), + SampleBuffer::ReadableSlice( + writableSampleFrames.sampleBuffer().data(), + std::min(writableSampleFrames.sampleBuffer().size(), frames2samples(numberOfFrames)))); } //------------------------------------------------------------------- diff --git a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h index 7e738a9d08..58d19934bf 100755 --- a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h +++ b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h @@ -57,9 +57,9 @@ public: void close() override; - IndexRange readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) override; + ReadableSampleFrames readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) override; private: OpenResult tryOpen(const mixxx::AudioSourceConfig& audioSrcCfg) override; diff --git a/plugins/soundsourcewv/soundsourcewv.cpp b/plugins/soundsourcewv/soundsourcewv.cpp index c5c385773d..18e0f686e5 100644 --- a/plugins/soundsourcewv/soundsourcewv.cpp +++ b/plugins/soundsourcewv/soundsourcewv.cpp @@ -102,26 +102,27 @@ void SoundSourceWV::close() { } } -IndexRange SoundSourceWV::readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) { - auto readableFrames = - adjustReadableFrameIndexRangeAndOutputBuffer( - frameIndexRange, pOutputBuffer); - if (readableFrames.empty()) { - return readableFrames; +ReadableSampleFrames SoundSourceWV::readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) { + const auto writableSampleFrames = + clampWritableSampleFrames(readMode, sampleFrames); + if (writableSampleFrames.frameIndexRange().empty()) { + return ReadableSampleFrames(writableSampleFrames.frameIndexRange()); } - if (pOutputBuffer) { - if (m_curFrameIndex != readableFrames.start()) { - if (WavpackSeekSample(m_wpc, readableFrames.start())) { - m_curFrameIndex = readableFrames.start(); + const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start(); + + if (readMode == ReadMode::Store) { + if (m_curFrameIndex != firstFrameIndex) { + if (WavpackSeekSample(m_wpc, firstFrameIndex)) { + m_curFrameIndex = firstFrameIndex; } else { kLogger.warning() - << "Could not seek to frame index range" - << readableFrames; + << "Could not seek to first frame index" + << firstFrameIndex; m_curFrameIndex = WavpackGetSampleIndex(m_wpc); - return IndexRange(); + return ReadableSampleFrames(IndexRange::between(m_curFrameIndex, m_curFrameIndex)); } } } else { @@ -131,40 +132,47 @@ IndexRange SoundSourceWV::readOrSkipSampleFrames( // we don't want to read samples into a temporary buffer that // has to be allocated we are seeking to the position after // the skipped samples. - if (m_curFrameIndex != readableFrames.end()) { - if (WavpackSeekSample(m_wpc, readableFrames.end())) { - m_curFrameIndex = readableFrames.end(); - return readableFrames; + if (m_curFrameIndex != writableSampleFrames.frameIndexRange().end()) { + if (WavpackSeekSample(m_wpc, writableSampleFrames.frameIndexRange().end())) { + m_curFrameIndex = writableSampleFrames.frameIndexRange().end(); + return ReadableSampleFrames(writableSampleFrames.frameIndexRange()); } else { kLogger.warning() << "Could not skip frame index range" - << readableFrames; + << writableSampleFrames.frameIndexRange(); m_curFrameIndex = WavpackGetSampleIndex(m_wpc); - return IndexRange::between(m_curFrameIndex, m_curFrameIndex); + return ReadableSampleFrames(IndexRange::between(m_curFrameIndex, m_curFrameIndex)); } } } + DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex); + DEBUG_ASSERT(readMode == ReadMode::Store); + + const SINT numberOfFramesTotal = writableSampleFrames.frameIndexRange().length(); - DEBUG_ASSERT(m_curFrameIndex == readableFrames.start()); - DEBUG_ASSERT(pOutputBuffer); static_assert(sizeof(CSAMPLE) == sizeof(int32_t), "CSAMPLE and int32_t must have the same size"); + CSAMPLE* pOutputBuffer = writableSampleFrames.sampleBuffer().data(); SINT unpackCount = WavpackUnpackSamples(m_wpc, - reinterpret_cast<int32_t*>(pOutputBuffer->data()), readableFrames.length()); + reinterpret_cast<int32_t*>(pOutputBuffer), numberOfFramesTotal); DEBUG_ASSERT(unpackCount >= 0); - DEBUG_ASSERT(unpackCount <= readableFrames.length()); + DEBUG_ASSERT(unpackCount <= numberOfFramesTotal); if (!(WavpackGetMode(m_wpc) & MODE_FLOAT)) { // signed integer -> float const SINT sampleCount = frames2samples(unpackCount); for (SINT i = 0; i < sampleCount; ++i) { const int32_t sampleValue = - *reinterpret_cast<int32_t*>(pOutputBuffer->data(i)); - *pOutputBuffer->data(i) = CSAMPLE(sampleValue) * m_sampleScaleFactor; + *reinterpret_cast<int32_t*>(pOutputBuffer); + *pOutputBuffer++ = CSAMPLE(sampleValue) * m_sampleScaleFactor; } } - const auto result = IndexRange::forward(m_curFrameIndex, unpackCount); + const auto resultRange = IndexRange::forward(m_curFrameIndex, unpackCount); m_curFrameIndex += unpackCount; - return result; + return ReadableSampleFrames( + resultRange, + SampleBuffer::ReadableSlice( + writableSampleFrames.sampleBuffer().data(), + frames2samples(unpackCount))); } QString SoundSourceProviderWV::getName() const { diff --git a/plugins/soundsourcewv/soundsourcewv.h b/plugins/soundsourcewv/soundsourcewv.h index 295a5dc9c3..5e4640a66e 100644 --- a/plugins/soundsourcewv/soundsourcewv.h +++ b/plugins/soundsourcewv/soundsourcewv.h @@ -16,9 +16,9 @@ class SoundSourceWV: public SoundSourcePlugin { void close() override; - IndexRange readOrSkipSampleFrames( - IndexRange frameIndexRange, - SampleBuffer::WritableSlice* pOutputBuffer) override; + ReadableSampleFrames readSampleFrames( + ReadMode readMode, + WritableSampleFrames sampleFrames) override; private: OpenResult tryOpen(const AudioSourceConfig& audioSrcCfg) override; |