Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,49 +33,24 @@ AndroidAudioRecorder::AndroidAudioRecorder(
streamMaxBufferSizeInFrames_(0) {}

/// @brief Destructor ensures that the audio stream and each output type are closed and flushed up remaining data.
/// TODO: Possibly locks here are not necessary, but we might have an issue with oboe having raw pointer to the
/// recorder (and player) instances, thus creating race conditions during destruction.
/// callable from the JS thread only (i hope).
/// callable from the JS thread or hadnled by audio thread (if js dropped recorder first).
AndroidAudioRecorder::~AndroidAudioRecorder() {
std::shared_ptr<AudioFileWriter> fileWriter;
std::shared_ptr<AudioRecorderCallback> dataCallback;
std::shared_ptr<RecorderAdapterNode> adapterNode;
{
std::scoped_lock dtorLock(callbackMutex_, fileWriterMutex_, adapterNodeMutex_);

if (usesFileOutput()) {
fileOutputConfigured_.store(false, std::memory_order_release);
fileWriter = std::move(fileWriter_);
}

if (usesCallback()) {
callbackOutputConfigured_.store(false, std::memory_order_release);
dataCallback = std::move(dataCallback_);
}

if (isConnected()) {
connectedConfigured_.store(false, std::memory_order_release);
adapterNode = std::move(adapterNode_);
deinterleavingBuffer_ = nullptr;
}

fileOutputEnabled_.store(false, std::memory_order_release);
callbackOutputEnabled_.store(false, std::memory_order_release);
isConnected_.store(false, std::memory_order_release);
}

if (fileWriter != nullptr) {
fileWriter->closeFile();
}

if (dataCallback != nullptr) {
dataCallback->cleanup();
}

if (adapterNode != nullptr) {
adapterNode->adapterCleanup();
}

// there is no need to lock here, as there could be two threads that can destruct js gc and audio thread one (or one created by it)
// if we are on js:
// audio thread dropped recorder so onAudioReady callback would not be called anymore
//
// if we are on audio thread:
// js dropped recorder and oboe states that "callback object cannot be deleted before the stream is deleted"
if (fileWriter_ != nullptr) {
fileWriter_->closeFile();
}
if (dataCallback_ != nullptr) {
dataCallback_->cleanup();
}
if (adapterNode_ != nullptr) {
adapterNode_->adapterCleanup();
}
// oboe could be handling stopping and closing the stream, sanity check just in case
if (mStream_ != nullptr) {
mStream_->requestStop();
mStream_->close();
Expand All @@ -100,8 +75,8 @@ Result<NoneType, std::string> AndroidAudioRecorder::openAudioStream() {
->setFormatConversionAllowed(true)
->setPerformanceMode(oboe::PerformanceMode::None)
->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium)
->setDataCallback(this)
->setErrorCallback(this);
->setDataCallback(shared_from_this())
->setErrorCallback(shared_from_this());

auto result = builder.openStream(mStream_);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class AndroidRecorderCallback;
class AndroidFileWriterBackend;
class AudioEventHandlerRegistry;

class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecorder {
class AndroidAudioRecorder : public oboe::AudioStreamCallback,
public AudioRecorder,
public std::enable_shared_from_this<AndroidAudioRecorder> {
public:
explicit AndroidAudioRecorder(
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ AudioPlayer::AudioPlayer(
: renderAudio_(renderAudio),
sampleRate_(sampleRate),
channelCount_(channelCount),
isRunning_(false) {
isInitialized_ = openAudioStream();
}
isRunning_(false) {}

bool AudioPlayer::openAudioStream() {
AudioStreamBuilder builder;
Expand All @@ -32,9 +30,9 @@ bool AudioPlayer::openAudioStream() {
->setChannelCount(channelCount_)
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
->setFramesPerDataCallback(RENDER_QUANTUM_SIZE)
->setDataCallback(this)
->setSampleRate(static_cast<int>(sampleRate_))
->setErrorCallback(this);
->setDataCallback(shared_from_this())
->setErrorCallback(shared_from_this())
->setSampleRate(static_cast<int>(sampleRate_));

auto result = builder.openStream(mStream_);
if (result != oboe::Result::OK || mStream_ == nullptr) {
Expand All @@ -44,6 +42,7 @@ bool AudioPlayer::openAudioStream() {
}

buffer_ = std::make_shared<DSPAudioBuffer>(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_);
isInitialized_ = true;
return true;
}

Expand Down Expand Up @@ -105,7 +104,7 @@ AudioPlayer::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numF
return DataCallbackResult::Continue;
}

auto buffer = static_cast<float *>(audioData);
auto *buffer = static_cast<float *>(audioData);
int processedFrames = 0;

while (processedFrames < numFrames) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ using namespace oboe;

class AudioContext;

class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback {
class AudioPlayer : public AudioStreamDataCallback,
public AudioStreamErrorCallback,
public std::enable_shared_from_this<AudioPlayer> {
public:
friend class AudioContext;
AudioPlayer(
const std::function<void(std::shared_ptr<DSPAudioBuffer>, int)> &renderAudio,
float sampleRate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void AudioContext::initialize() {
#ifdef ANDROID
audioPlayer_ = std::make_shared<AudioPlayer>(
this->renderAudio(), getSampleRate(), destination_->getChannelCount());
audioPlayer_->openAudioStream();
#else
audioPlayer_ = std::make_shared<IOSAudioPlayer>(
this->renderAudio(), getSampleRate(), destination_->getChannelCount());
Expand Down
Loading