8000 oboe: fix sample rate converter for input streams · google/oboe@7c3bff2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7c3bff2

Browse files
oboe: fix sample rate converter for input streams
The callbackCount was not handled correctly. This could cause a stream to stall and stop calling callbacks. Fixes #987
1 parent 3b22c66 commit 7c3bff2

File tree

5 files changed

+20
-16
lines changed

5 files changed

+20
-16
lines changed

src/common/DataConversionFlowGraph.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ Result DataConversionFlowGraph::configure(AudioStream *sourceStream, AudioStream
9898
? sourceStream->getFramesPerBurst()
9999
: sourceStream->getFramesPerCallback();
100100
// Source
101-
// If OUTPUT and using a callback then call back to the app using a SourceCaller.
102-
// If INPUT and NOT using a callback then read from the child stream using a SourceCaller.
101+
// IF OUTPUT and using a callback then call back to the app using a SourceCaller.
102+
// OR IF INPUT and NOT using a callback then read from the child stream using a SourceCaller.
103103
if ((sourceStream->getCallback() != nullptr && isOutput)
104104
|| (sourceStream->getCallback() == nullptr && isInput)) {
105105
switch (sourceFormat) {
@@ -118,8 +118,8 @@ Result DataConversionFlowGraph::configure(AudioStream *sourceStream, AudioStream
118118
mSourceCaller->setStream(sourceStream);
119119
lastOutput = &mSourceCaller->output;
120120
} else {
121-
// If OUTPUT and NOT using a callback then write to the child stream using a BlockWriter.
122-
// If INPUT and using a callback then write to the app using a BlockWriter.
121+
// IF OUTPUT and NOT using a callback then write to the child stream using a BlockWriter.
122+
// OR IF INPUT and using a callback then write to the app using a BlockWriter.
123123
switch (sourceFormat) {
124124
case AudioFormat::Float:
125125
mSource = std::make_unique<SourceFloat>(sourceChannelCount);
@@ -200,8 +200,6 @@ Result DataConversionFlowGraph::configure(AudioStream *sourceStream, AudioStream
200200
}
201201
lastOutput->connect(&mSink->input);
202202

203-
mFramePosition = 0;
204-
205203
return Result::OK;
206204
}
207205

@@ -210,7 +208,6 @@ int32_t DataConversionFlowGraph::read(void *buffer, int32_t numFrames, int64_t t
210208
mSourceCaller->setTimeoutNanos(timeoutNanos);
211209
}
212210
int32_t numRead = mSink->read(buffer, numFrames);
213-
mFramePosition += numRead;
214211
return numRead;
215212
}
216213

@@ -221,7 +218,6 @@ int32_t DataConversionFlowGraph::write(void *inputBuffer, int32_t numFrames) {
221218
while (true) {
222219
// Pull and read some data in app format into a small buffer.
223220
int32_t framesRead = mSink->read(mAppBuffer.get(), flowgraph::kDefaultBufferSize);
224-
mFramePosition += framesRead;
225221
if (framesRead <= 0) break;
226222
// Write to a block adapter, which will call the destination whenever it has enough data.
227223
int32_t bytesRead = mBlockWriter.write(mAppBuffer.get(),

src/common/DataConversionFlowGraph.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ class DataConversionFlowGraph : public FixedBlockProcessor {
8080
DataCallbackResult mCallbackResult = DataCallbackResult::Continue;
8181
AudioStream *mFilterStream = nullptr;
8282
std::unique_ptr<uint8_t[]> mAppBuffer;
83-
84-
int64_t mFramePosition = 0;
8583
};
8684

8785
}

src/flowgraph/FlowGraphNode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,4 @@ float *FlowGraphPortFloatInput::getBuffer() {
111111

112112
int32_t FlowGraphSink::pullData(int32_t numFrames) {
113113
return FlowGraphNode::pullData(numFrames, getLastCallCount() + 1);
114-
}
114+
}

src/flowgraph/SampleRateConverter.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,17 @@ SampleRateConverter::SampleRateConverter(int32_t channelCount, MultiChannelResam
2525
setDataPulledAutomatically(false);
2626
}
2727

28+
void SampleRateConverter::reset() {
29+
FlowGraphNode::reset();
30+
mInputCursor = kInitialCallCount;
31+
}
32+
2833
// Return true if there is a sample available.
2934
bool SampleRateConverter::isInputAvailable() {
35+
// If we have consumed all of the input data then go out and get some more.
3036
if (mInputCursor >= mNumValidInputFrames) {
31-
mNumValidInputFrames = input.pullData(mInputFramePosition, input.getFramesPerBuffer());
32-
mInputFramePosition += mNumValidInputFrames;
37+
mInputCallCount++;
38+
mNumValidInputFrames = input.pullData(mInputCallCount, input.getFramesPerBuffer());
3339
mInputCursor = 0;
3440
}
3541
return (mInputCursor < mNumValidInputFrames);

src/flowgraph/SampleRateConverter.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class SampleRateConverter : public FlowGraphFilter {
3838
return "SampleRateConverter";
3939
}
4040

41+
void reset() override;
42+
4143
private:
4244

4345
// Return true if there is a sample available.
@@ -48,9 +50,11 @@ class SampleRateConverter : public FlowGraphFilter {
4850

4951
resampler::MultiChannelResampler &mResampler;
5052

51-
int32_t mInputCursor = 0;
52-
int32_t mNumValidInputFrames = 0;
53-
int64_t mInputFramePosition = 0; // monotonic counter of input frames used for pullData
53+
int32_t mInputCursor = 0; // offset into the input port buffer
54+
int32_t mNumValidInputFrames = 0; // number of valid frames currently in the input port buffer
55+
// We need our own callCount for upstream calls because calls occur at a different rate.
56+
// This means we cannot have cyclic graphs or merges that contain an SRC.
57+
int64_t mInputCallCount = 0;
5458

5559
};
5660

0 commit comments

Comments
 (0)
0