#ifndef OBOE_FILTER_AUDIO_STREAM_H
#define OBOE_FILTER_AUDIO_STREAM_H
#include <memory>
#include <oboe/AudioStream.h>
#include "DataConversionFlowGraph.h"
namespace oboe {
class FilterAudioStream : public AudioStream, AudioStreamCallback {
public:
FilterAudioStream(const AudioStreamBuilder &builder, AudioStream *childStream)
: AudioStream(builder)
, mChildStream(childStream) {
if (builder.isErrorCallbackSpecified()) {
mErrorCallback = mChildStream->swapErrorCallback(this);
}
if (builder.isDataCallbackSpecified()) {
mDataCallback = mChildStream->swapDataCallback(this);
} else {
const int size = childStream->getFramesPerBurst() * childStream->getBytesPerFrame();
mBlockingBuffer = std::make_unique<uint8_t[]>(size);
}
mBufferCapacityInFrames = mChildStream->getBufferCapacityInFrames();
mPerformanceMode = mChildStream->getPerformanceMode();
mSharingMode = mChildStream->getSharingMode();
mInputPreset = mChildStream->getInputPreset();
mFramesPerBurst = mChildStream->getFramesPerBurst();
mDeviceId = mChildStream->getDeviceId();
mHardwareSampleRate = mChildStream->getHardwareSampleRate();
mHardwareChannelCount = mChildStream->getHardwareChannelCount();
mHardwareFormat = mChildStream->getHardwareFormat();
}
virtual ~FilterAudioStream() = default;
AudioStream *getChildStream() const {
return mChildStream.get();
}
Result configureFlowGraph();
Result close() override {
const Result result1 = mChildStream->close();
const Result result2 = AudioStream::close();
return (result1 != Result::OK ? result1 : result2);
}
Result requestStart() override {
return mChildStream->requestStart();
}
Result requestPause() override {
return mChildStream->requestPause();
}
Result requestFlush() override {
return mChildStream->requestFlush();
}
Result requestStop() override {
return mChildStream->requestStop();
}
ResultWithValue<int32_t> read(void *buffer,
int32_t numFrames,
int64_t timeoutNanoseconds) override;
ResultWithValue<int32_t> write(const void *buffer,
int32_t numFrames,
int64_t timeoutNanoseconds) override;
StreamState getState() override {
return mChildStream->getState();
}
Result waitForStateChange(
StreamState inputState,
StreamState *nextState,
int64_t timeoutNanoseconds) override {
return mChildStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
}
bool isXRunCountSupported() const override {
return mChildStream->isXRunCountSupported();
}
AudioApi getAudioApi() const override {
return mChildStream->getAudioApi();
}
void updateFramesWritten() override {
mFramesWritten = static_cast<int64_t>(mChildStream->getFramesWritten() * mRateScaler);
}
void updateFramesRead() override {
mFramesRead = static_cast<int64_t>(mChildStream->getFramesRead() * mRateScaler);
}
void *getUnderlyingStream() const override {
return mChildStream->getUnderlyingStream();
}
ResultWithValue<int32_t> setBufferSizeInFrames(int32_t requestedFrames) override {
return mChildStream->setBufferSizeInFrames(requestedFrames);
}
int32_t getBufferSizeInFrames() override {
mBufferSizeInFrames = mChildStream->getBufferSizeInFrames();
return mBufferSizeInFrames;
}
ResultWithValue<int32_t> getXRunCount() override {
return mChildStream->getXRunCount();
}
ResultWithValue<double> calculateLatencyMillis() override {
return mChildStream->calculateLatencyMillis();
}
Result getTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds) override {
int64_t childPosition = 0;
Result result = mChildStream->getTimestamp(clockId, &childPosition, timeNanoseconds);
if (framePosition) {
*framePosition = childPosition * mRateScaler;
}
return result;
}
DataCallbackResult onAudioReady(AudioStream *oboeStream,
void *audioData,
int32_t numFrames) override;
bool onError(AudioStream * , Result error) override {
if (mErrorCallback != nullptr) {
return mErrorCallback->onError(this, error);
}
return false;
}
void onErrorBeforeClose(AudioStream * , Result error) override {
if (mErrorCallback != nullptr) {
mErrorCallback->onErrorBeforeClose(this, error);
}
}
void onErrorAfterClose(AudioStream * , Result error) override {
AudioStream::close();
if (mErrorCallback != nullptr) {
mErrorCallback->onErrorAfterClose(this, error);
}
}
oboe::Result getLastErrorCallbackResult() const override {
return mChildStream->getLastErrorCallbackResult();
}
private:
std::unique_ptr<AudioStream> mChildStream; std::unique_ptr<DataConversionFlowGraph> mFlowGraph; std::unique_ptr<uint8_t[]> mBlockingBuffer; double mRateScaler = 1.0; };
}
#endif