Made audio stream handling safe for long streams

This commit is contained in:
Daniel Wolf 2016-06-14 17:41:58 +02:00
parent d1bbe8538e
commit 522f6c2019
11 changed files with 48 additions and 48 deletions

View File

@ -9,10 +9,10 @@ public:
virtual ~AudioStream() {} virtual ~AudioStream() {}
virtual std::unique_ptr<AudioStream> clone(bool reset) const = 0; virtual std::unique_ptr<AudioStream> clone(bool reset) const = 0;
virtual int getSampleRate() const = 0; virtual int getSampleRate() const = 0;
virtual int getSampleCount() const = 0; virtual int64_t getSampleCount() const = 0;
TimeRange getTruncatedRange() const; TimeRange getTruncatedRange() const;
virtual int getSampleIndex() const = 0; virtual int64_t getSampleIndex() const = 0;
virtual void seek(int sampleIndex) = 0; virtual void seek(int64_t sampleIndex) = 0;
bool endOfStream() const; bool endOfStream() const;
virtual float readSample() = 0; virtual float readSample() = 0;
}; };

View File

@ -29,15 +29,15 @@ int AudioStreamSegment::getSampleRate() const {
return audioStream->getSampleRate(); return audioStream->getSampleRate();
} }
int AudioStreamSegment::getSampleCount() const { int64_t AudioStreamSegment::getSampleCount() const {
return sampleCount; return sampleCount;
} }
int AudioStreamSegment::getSampleIndex() const { int64_t AudioStreamSegment::getSampleIndex() const {
return audioStream->getSampleIndex() - sampleOffset; return audioStream->getSampleIndex() - sampleOffset;
} }
void AudioStreamSegment::seek(int sampleIndex) { void AudioStreamSegment::seek(int64_t sampleIndex) {
audioStream->seek(sampleIndex + sampleOffset); audioStream->seek(sampleIndex + sampleOffset);
} }

View File

@ -8,14 +8,14 @@ public:
AudioStreamSegment(const AudioStreamSegment& rhs, bool reset); AudioStreamSegment(const AudioStreamSegment& rhs, bool reset);
std::unique_ptr<AudioStream> clone(bool reset) const override; std::unique_ptr<AudioStream> clone(bool reset) const override;
int getSampleRate() const override; int getSampleRate() const override;
int getSampleCount() const override; int64_t getSampleCount() const override;
int getSampleIndex() const override; int64_t getSampleIndex() const override;
void seek(int sampleIndex) override; void seek(int64_t sampleIndex) override;
float readSample() override; float readSample() override;
private: private:
std::unique_ptr<AudioStream> audioStream; std::unique_ptr<AudioStream> audioStream;
int sampleOffset, sampleCount; int64_t sampleOffset, sampleCount;
}; };
std::unique_ptr<AudioStream> createSegment(std::unique_ptr<AudioStream> audioStream, const TimeRange& range); std::unique_ptr<AudioStream> createSegment(std::unique_ptr<AudioStream> audioStream, const TimeRange& range);

View File

@ -22,15 +22,15 @@ int DCOffset::getSampleRate() const {
return inputStream->getSampleRate(); return inputStream->getSampleRate();
} }
int DCOffset::getSampleCount() const { int64_t DCOffset::getSampleCount() const {
return inputStream->getSampleCount(); return inputStream->getSampleCount();
} }
int DCOffset::getSampleIndex() const { int64_t DCOffset::getSampleIndex() const {
return inputStream->getSampleIndex(); return inputStream->getSampleIndex();
} }
void DCOffset::seek(int sampleIndex) { void DCOffset::seek(int64_t sampleIndex) {
inputStream->seek(sampleIndex); inputStream->seek(sampleIndex);
} }
@ -53,11 +53,11 @@ float getDCOffset(AudioStream& audioStream) {
fadingMeanSampleCount = 1 * sampleRate; fadingMeanSampleCount = 1 * sampleRate;
} else { } else {
// Short audio file. Average over the entire length. // Short audio file. Average over the entire length.
flatMeanSampleCount = audioStream.getSampleCount(); flatMeanSampleCount = static_cast<int>(audioStream.getSampleCount());
fadingMeanSampleCount = 0; fadingMeanSampleCount = 0;
} }
int originalSampleIndex = audioStream.getSampleIndex(); int64_t originalSampleIndex = audioStream.getSampleIndex();
audioStream.seek(0); audioStream.seek(0);
auto restorePosition = gsl::finally([&]() { audioStream.seek(originalSampleIndex); }); auto restorePosition = gsl::finally([&]() { audioStream.seek(originalSampleIndex); });

View File

@ -10,9 +10,9 @@ public:
DCOffset(const DCOffset& rhs, bool reset); DCOffset(const DCOffset& rhs, bool reset);
std::unique_ptr<AudioStream> clone(bool reset) const override; std::unique_ptr<AudioStream> clone(bool reset) const override;
int getSampleRate() const override; int getSampleRate() const override;
int getSampleCount() const override; int64_t getSampleCount() const override;
int getSampleIndex() const override; int64_t getSampleIndex() const override;
void seek(int sampleIndex) override; void seek(int64_t sampleIndex) override;
float readSample() override; float readSample() override;
private: private:

View File

@ -37,15 +37,15 @@ int SampleRateConverter::getSampleRate() const {
return outputSampleRate; return outputSampleRate;
} }
int SampleRateConverter::getSampleCount() const { int64_t SampleRateConverter::getSampleCount() const {
return outputSampleCount; return outputSampleCount;
} }
int SampleRateConverter::getSampleIndex() const { int64_t SampleRateConverter::getSampleIndex() const {
return nextOutputSampleIndex; return nextOutputSampleIndex;
} }
void SampleRateConverter::seek(int sampleIndex) { void SampleRateConverter::seek(int64_t sampleIndex) {
if (sampleIndex < 0 || sampleIndex >= outputSampleCount) throw std::invalid_argument("sampleIndex out of range."); if (sampleIndex < 0 || sampleIndex >= outputSampleCount) throw std::invalid_argument("sampleIndex out of range.");
nextOutputSampleIndex = sampleIndex; nextOutputSampleIndex = sampleIndex;
@ -66,12 +66,12 @@ float SampleRateConverter::mean(double inputStart, double inputEnd) {
double sum = 0; double sum = 0;
// ... first sample (weight <= 1) // ... first sample (weight <= 1)
int startIndex = static_cast<int>(inputStart); int64_t startIndex = static_cast<int64_t>(inputStart);
sum += getInputSample(startIndex) * ((startIndex + 1) - inputStart); sum += getInputSample(startIndex) * ((startIndex + 1) - inputStart);
// ... middle samples (weight 1 each) // ... middle samples (weight 1 each)
int endIndex = static_cast<int>(inputEnd); int64_t endIndex = static_cast<int64_t>(inputEnd);
for (int index = startIndex + 1; index < endIndex; index++) { for (int64_t index = startIndex + 1; index < endIndex; ++index) {
sum += getInputSample(index); sum += getInputSample(index);
} }
@ -81,7 +81,7 @@ float SampleRateConverter::mean(double inputStart, double inputEnd) {
return static_cast<float>(sum / (inputEnd - inputStart)); return static_cast<float>(sum / (inputEnd - inputStart));
} }
float SampleRateConverter::getInputSample(int sampleIndex) { float SampleRateConverter::getInputSample(int64_t sampleIndex) {
sampleIndex = std::min(sampleIndex, inputStream->getSampleCount() - 1); sampleIndex = std::min(sampleIndex, inputStream->getSampleCount() - 1);
if (sampleIndex < 0) return 0.0f; if (sampleIndex < 0) return 0.0f;

View File

@ -9,24 +9,24 @@ public:
SampleRateConverter(const SampleRateConverter& rhs, bool reset); SampleRateConverter(const SampleRateConverter& rhs, bool reset);
std::unique_ptr<AudioStream> clone(bool reset) const override; std::unique_ptr<AudioStream> clone(bool reset) const override;
int getSampleRate() const override; int getSampleRate() const override;
int getSampleCount() const override; int64_t getSampleCount() const override;
int getSampleIndex() const override; int64_t getSampleIndex() const override;
void seek(int sampleIndex) override; void seek(int64_t sampleIndex) override;
float readSample() override; float readSample() override;
private: private:
std::unique_ptr<AudioStream> inputStream; std::unique_ptr<AudioStream> inputStream;
double downscalingFactor; // input sample rate / output sample rate double downscalingFactor; // input sample rate / output sample rate
int outputSampleRate; int outputSampleRate;
int outputSampleCount; int64_t outputSampleCount;
float lastInputSample; float lastInputSample;
int lastInputSampleIndex; int64_t lastInputSampleIndex;
int nextOutputSampleIndex; int64_t nextOutputSampleIndex;
float mean(double start, double end); float mean(double start, double end);
float getInputSample(int sampleIndex); float getInputSample(int64_t sampleIndex);
}; };
std::unique_ptr<AudioStream> convertSampleRate(std::unique_ptr<AudioStream> audioStream, int sampleRate); std::unique_ptr<AudioStream> convertSampleRate(std::unique_ptr<AudioStream> audioStream, int sampleRate);

View File

@ -24,15 +24,15 @@ int UnboundedStream::getSampleRate() const {
return innerStream->getSampleRate(); return innerStream->getSampleRate();
} }
int UnboundedStream::getSampleCount() const { int64_t UnboundedStream::getSampleCount() const {
return innerStream->getSampleCount(); return innerStream->getSampleCount();
} }
int UnboundedStream::getSampleIndex() const { int64_t UnboundedStream::getSampleIndex() const {
return sampleIndex; return sampleIndex;
} }
void UnboundedStream::seek(int sampleIndex) { void UnboundedStream::seek(int64_t sampleIndex) {
this->sampleIndex = sampleIndex; this->sampleIndex = sampleIndex;
} }

View File

@ -10,13 +10,13 @@ public:
UnboundedStream(const UnboundedStream& rhs, bool reset); UnboundedStream(const UnboundedStream& rhs, bool reset);
std::unique_ptr<AudioStream> clone(bool reset) const override; std::unique_ptr<AudioStream> clone(bool reset) const override;
int getSampleRate() const override; int getSampleRate() const override;
int getSampleCount() const override; int64_t getSampleCount() const override;
int getSampleIndex() const override; int64_t getSampleIndex() const override;
void seek(int sampleIndex) override; void seek(int64_t sampleIndex) override;
float readSample() override; float readSample() override;
private: private:
std::unique_ptr<AudioStream> innerStream; std::unique_ptr<AudioStream> innerStream;
int sampleIndex; int64_t sampleIndex;
boost::optional<float> firstSample, lastSample; boost::optional<float> firstSample, lastSample;
}; };

View File

@ -173,15 +173,15 @@ int WaveFileReader::getSampleRate() const {
return frameRate; return frameRate;
} }
int WaveFileReader::getSampleCount() const { int64_t WaveFileReader::getSampleCount() const {
return frameCount; return frameCount;
} }
int WaveFileReader::getSampleIndex() const { int64_t WaveFileReader::getSampleIndex() const {
return sampleIndex; return sampleIndex;
} }
void WaveFileReader::seek(int sampleIndex) { void WaveFileReader::seek(int64_t sampleIndex) {
if (sampleIndex < 0 || sampleIndex > sampleCount) throw std::invalid_argument("sampleIndex out of range."); if (sampleIndex < 0 || sampleIndex > sampleCount) throw std::invalid_argument("sampleIndex out of range.");
file.seekg(dataOffset + static_cast<std::streamoff>(sampleIndex * channelCount * bytesPerSample)); file.seekg(dataOffset + static_cast<std::streamoff>(sampleIndex * channelCount * bytesPerSample));

View File

@ -17,9 +17,9 @@ public:
WaveFileReader(const WaveFileReader& rhs, bool reset); WaveFileReader(const WaveFileReader& rhs, bool reset);
std::unique_ptr<AudioStream> clone(bool reset) const override; std::unique_ptr<AudioStream> clone(bool reset) const override;
int getSampleRate() const override ; int getSampleRate() const override ;
int getSampleCount() const override; int64_t getSampleCount() const override;
int getSampleIndex() const override; int64_t getSampleIndex() const override;
void seek(int sampleIndex) override; void seek(int64_t sampleIndex) override;
float readSample() override; float readSample() override;
private: private:
@ -31,9 +31,9 @@ private:
int bytesPerSample; int bytesPerSample;
SampleFormat sampleFormat; SampleFormat sampleFormat;
int frameRate; int frameRate;
int frameCount; int64_t frameCount;
int channelCount; int channelCount;
int sampleCount; int64_t sampleCount;
std::streampos dataOffset; std::streampos dataOffset;
int sampleIndex; int64_t sampleIndex;
}; };