Made audio stream handling safe for long streams
This commit is contained in:
parent
d1bbe8538e
commit
522f6c2019
|
@ -9,10 +9,10 @@ public:
|
|||
virtual ~AudioStream() {}
|
||||
virtual std::unique_ptr<AudioStream> clone(bool reset) const = 0;
|
||||
virtual int getSampleRate() const = 0;
|
||||
virtual int getSampleCount() const = 0;
|
||||
virtual int64_t getSampleCount() const = 0;
|
||||
TimeRange getTruncatedRange() const;
|
||||
virtual int getSampleIndex() const = 0;
|
||||
virtual void seek(int sampleIndex) = 0;
|
||||
virtual int64_t getSampleIndex() const = 0;
|
||||
virtual void seek(int64_t sampleIndex) = 0;
|
||||
bool endOfStream() const;
|
||||
virtual float readSample() = 0;
|
||||
};
|
||||
|
|
|
@ -29,15 +29,15 @@ int AudioStreamSegment::getSampleRate() const {
|
|||
return audioStream->getSampleRate();
|
||||
}
|
||||
|
||||
int AudioStreamSegment::getSampleCount() const {
|
||||
int64_t AudioStreamSegment::getSampleCount() const {
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
int AudioStreamSegment::getSampleIndex() const {
|
||||
int64_t AudioStreamSegment::getSampleIndex() const {
|
||||
return audioStream->getSampleIndex() - sampleOffset;
|
||||
}
|
||||
|
||||
void AudioStreamSegment::seek(int sampleIndex) {
|
||||
void AudioStreamSegment::seek(int64_t sampleIndex) {
|
||||
audioStream->seek(sampleIndex + sampleOffset);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@ public:
|
|||
AudioStreamSegment(const AudioStreamSegment& rhs, bool reset);
|
||||
std::unique_ptr<AudioStream> clone(bool reset) const override;
|
||||
int getSampleRate() const override;
|
||||
int getSampleCount() const override;
|
||||
int getSampleIndex() const override;
|
||||
void seek(int sampleIndex) override;
|
||||
int64_t getSampleCount() const override;
|
||||
int64_t getSampleIndex() const override;
|
||||
void seek(int64_t sampleIndex) override;
|
||||
float readSample() override;
|
||||
|
||||
private:
|
||||
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);
|
||||
|
|
|
@ -22,15 +22,15 @@ int DCOffset::getSampleRate() const {
|
|||
return inputStream->getSampleRate();
|
||||
}
|
||||
|
||||
int DCOffset::getSampleCount() const {
|
||||
int64_t DCOffset::getSampleCount() const {
|
||||
return inputStream->getSampleCount();
|
||||
}
|
||||
|
||||
int DCOffset::getSampleIndex() const {
|
||||
int64_t DCOffset::getSampleIndex() const {
|
||||
return inputStream->getSampleIndex();
|
||||
}
|
||||
|
||||
void DCOffset::seek(int sampleIndex) {
|
||||
void DCOffset::seek(int64_t sampleIndex) {
|
||||
inputStream->seek(sampleIndex);
|
||||
}
|
||||
|
||||
|
@ -53,11 +53,11 @@ float getDCOffset(AudioStream& audioStream) {
|
|||
fadingMeanSampleCount = 1 * sampleRate;
|
||||
} else {
|
||||
// Short audio file. Average over the entire length.
|
||||
flatMeanSampleCount = audioStream.getSampleCount();
|
||||
flatMeanSampleCount = static_cast<int>(audioStream.getSampleCount());
|
||||
fadingMeanSampleCount = 0;
|
||||
}
|
||||
|
||||
int originalSampleIndex = audioStream.getSampleIndex();
|
||||
int64_t originalSampleIndex = audioStream.getSampleIndex();
|
||||
audioStream.seek(0);
|
||||
auto restorePosition = gsl::finally([&]() { audioStream.seek(originalSampleIndex); });
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ public:
|
|||
DCOffset(const DCOffset& rhs, bool reset);
|
||||
std::unique_ptr<AudioStream> clone(bool reset) const override;
|
||||
int getSampleRate() const override;
|
||||
int getSampleCount() const override;
|
||||
int getSampleIndex() const override;
|
||||
void seek(int sampleIndex) override;
|
||||
int64_t getSampleCount() const override;
|
||||
int64_t getSampleIndex() const override;
|
||||
void seek(int64_t sampleIndex) override;
|
||||
float readSample() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -37,15 +37,15 @@ int SampleRateConverter::getSampleRate() const {
|
|||
return outputSampleRate;
|
||||
}
|
||||
|
||||
int SampleRateConverter::getSampleCount() const {
|
||||
int64_t SampleRateConverter::getSampleCount() const {
|
||||
return outputSampleCount;
|
||||
}
|
||||
|
||||
int SampleRateConverter::getSampleIndex() const {
|
||||
int64_t SampleRateConverter::getSampleIndex() const {
|
||||
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.");
|
||||
|
||||
nextOutputSampleIndex = sampleIndex;
|
||||
|
@ -66,12 +66,12 @@ float SampleRateConverter::mean(double inputStart, double inputEnd) {
|
|||
double sum = 0;
|
||||
|
||||
// ... first sample (weight <= 1)
|
||||
int startIndex = static_cast<int>(inputStart);
|
||||
int64_t startIndex = static_cast<int64_t>(inputStart);
|
||||
sum += getInputSample(startIndex) * ((startIndex + 1) - inputStart);
|
||||
|
||||
// ... middle samples (weight 1 each)
|
||||
int endIndex = static_cast<int>(inputEnd);
|
||||
for (int index = startIndex + 1; index < endIndex; index++) {
|
||||
int64_t endIndex = static_cast<int64_t>(inputEnd);
|
||||
for (int64_t index = startIndex + 1; index < endIndex; ++index) {
|
||||
sum += getInputSample(index);
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ float SampleRateConverter::mean(double inputStart, double inputEnd) {
|
|||
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);
|
||||
if (sampleIndex < 0) return 0.0f;
|
||||
|
||||
|
|
|
@ -9,24 +9,24 @@ public:
|
|||
SampleRateConverter(const SampleRateConverter& rhs, bool reset);
|
||||
std::unique_ptr<AudioStream> clone(bool reset) const override;
|
||||
int getSampleRate() const override;
|
||||
int getSampleCount() const override;
|
||||
int getSampleIndex() const override;
|
||||
void seek(int sampleIndex) override;
|
||||
int64_t getSampleCount() const override;
|
||||
int64_t getSampleIndex() const override;
|
||||
void seek(int64_t sampleIndex) override;
|
||||
float readSample() override;
|
||||
private:
|
||||
std::unique_ptr<AudioStream> inputStream;
|
||||
double downscalingFactor; // input sample rate / output sample rate
|
||||
|
||||
int outputSampleRate;
|
||||
int outputSampleCount;
|
||||
int64_t outputSampleCount;
|
||||
|
||||
float lastInputSample;
|
||||
int lastInputSampleIndex;
|
||||
int64_t lastInputSampleIndex;
|
||||
|
||||
int nextOutputSampleIndex;
|
||||
int64_t nextOutputSampleIndex;
|
||||
|
||||
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);
|
|
@ -24,15 +24,15 @@ int UnboundedStream::getSampleRate() const {
|
|||
return innerStream->getSampleRate();
|
||||
}
|
||||
|
||||
int UnboundedStream::getSampleCount() const {
|
||||
int64_t UnboundedStream::getSampleCount() const {
|
||||
return innerStream->getSampleCount();
|
||||
}
|
||||
|
||||
int UnboundedStream::getSampleIndex() const {
|
||||
int64_t UnboundedStream::getSampleIndex() const {
|
||||
return sampleIndex;
|
||||
}
|
||||
|
||||
void UnboundedStream::seek(int sampleIndex) {
|
||||
void UnboundedStream::seek(int64_t sampleIndex) {
|
||||
this->sampleIndex = sampleIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@ public:
|
|||
UnboundedStream(const UnboundedStream& rhs, bool reset);
|
||||
std::unique_ptr<AudioStream> clone(bool reset) const override;
|
||||
int getSampleRate() const override;
|
||||
int getSampleCount() const override;
|
||||
int getSampleIndex() const override;
|
||||
void seek(int sampleIndex) override;
|
||||
int64_t getSampleCount() const override;
|
||||
int64_t getSampleIndex() const override;
|
||||
void seek(int64_t sampleIndex) override;
|
||||
float readSample() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<AudioStream> innerStream;
|
||||
int sampleIndex;
|
||||
int64_t sampleIndex;
|
||||
boost::optional<float> firstSample, lastSample;
|
||||
};
|
||||
|
|
|
@ -173,15 +173,15 @@ int WaveFileReader::getSampleRate() const {
|
|||
return frameRate;
|
||||
}
|
||||
|
||||
int WaveFileReader::getSampleCount() const {
|
||||
int64_t WaveFileReader::getSampleCount() const {
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
int WaveFileReader::getSampleIndex() const {
|
||||
int64_t WaveFileReader::getSampleIndex() const {
|
||||
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.");
|
||||
|
||||
file.seekg(dataOffset + static_cast<std::streamoff>(sampleIndex * channelCount * bytesPerSample));
|
||||
|
|
|
@ -17,9 +17,9 @@ public:
|
|||
WaveFileReader(const WaveFileReader& rhs, bool reset);
|
||||
std::unique_ptr<AudioStream> clone(bool reset) const override;
|
||||
int getSampleRate() const override ;
|
||||
int getSampleCount() const override;
|
||||
int getSampleIndex() const override;
|
||||
void seek(int sampleIndex) override;
|
||||
int64_t getSampleCount() const override;
|
||||
int64_t getSampleIndex() const override;
|
||||
void seek(int64_t sampleIndex) override;
|
||||
float readSample() override;
|
||||
|
||||
private:
|
||||
|
@ -31,9 +31,9 @@ private:
|
|||
int bytesPerSample;
|
||||
SampleFormat sampleFormat;
|
||||
int frameRate;
|
||||
int frameCount;
|
||||
int64_t frameCount;
|
||||
int channelCount;
|
||||
int sampleCount;
|
||||
int64_t sampleCount;
|
||||
std::streampos dataOffset;
|
||||
int sampleIndex;
|
||||
int64_t sampleIndex;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue