mirror of https://github.com/auygun/kaliber.git
Make member variables in MixerInput private
This commit is contained in:
parent
19910be27e
commit
e65d37e846
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "base/log.h"
|
||||
#include "base/task_runner.h"
|
||||
#include "base/thread_pool.h"
|
||||
#include "engine/audio/audio_bus.h"
|
||||
#include "engine/audio/mixer_input.h"
|
||||
|
||||
|
@ -33,11 +32,11 @@ AudioMixer::~AudioMixer() {
|
|||
audio_sink_.reset();
|
||||
}
|
||||
|
||||
void AudioMixer::AddInput(std::shared_ptr<MixerInput> input) {
|
||||
void AudioMixer::AddInput(std::shared_ptr<MixerInput> mixer_input) {
|
||||
DCHECK(audio_enabled_);
|
||||
|
||||
std::lock_guard<std::mutex> scoped_lock(lock_);
|
||||
inputs_[0].push_back(input);
|
||||
inputs_[0].push_back(mixer_input);
|
||||
}
|
||||
|
||||
void AudioMixer::Suspend() {
|
||||
|
@ -62,8 +61,8 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
memset(output_buffer, 0, sizeof(float) * num_frames * kChannelCount);
|
||||
|
||||
for (auto it = inputs_[1].begin(); it != inputs_[1].end();) {
|
||||
auto audio_bus = (*it)->audio_bus.get();
|
||||
unsigned flags = (*it)->flags.load(std::memory_order_relaxed);
|
||||
auto* audio_bus = (*it)->GetAudioBus().get();
|
||||
unsigned flags = (*it)->GetFlags();
|
||||
bool marked_for_removal = false;
|
||||
|
||||
if (flags & MixerInput::kStopped) {
|
||||
|
@ -75,14 +74,12 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
src[1] = src[0]; // mono.
|
||||
|
||||
size_t num_samples = audio_bus->samples_per_channel();
|
||||
size_t src_index = (*it)->src_index;
|
||||
size_t step = (*it)->step.load(std::memory_order_relaxed);
|
||||
size_t accumulator = (*it)->accumulator;
|
||||
float amplitude = (*it)->amplitude;
|
||||
float amplitude_inc =
|
||||
(*it)->amplitude_inc.load(std::memory_order_relaxed);
|
||||
float max_amplitude =
|
||||
(*it)->max_amplitude.load(std::memory_order_relaxed);
|
||||
size_t src_index = (*it)->GetSrcIndex();
|
||||
size_t step = (*it)->GetStep();
|
||||
size_t accumulator = (*it)->GetAccumulator();
|
||||
float amplitude = (*it)->GetAmplitude();
|
||||
float amplitude_inc = (*it)->GetAmplitudeInc();
|
||||
float max_amplitude = (*it)->GetMaxAmplitude();
|
||||
size_t channel_offset = (flags & MixerInput::kSimulateStereo)
|
||||
? audio_bus->sample_rate() / 10
|
||||
: 0;
|
||||
|
@ -118,37 +115,29 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
accumulator %= 100;
|
||||
} else {
|
||||
if (audio_bus->EndOfStream()) {
|
||||
src_index %= num_samples;
|
||||
marked_for_removal = !(flags & MixerInput::kLoop);
|
||||
if (!(flags & MixerInput::kLoop))
|
||||
marked_for_removal = true;
|
||||
else
|
||||
src_index %= num_samples;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(*it)->streaming_in_progress.load(std::memory_order_acquire)) {
|
||||
if ((*it)->OnMoreData(!!(flags & MixerInput::kLoop))) {
|
||||
src_index %= num_samples;
|
||||
(*it)->streaming_in_progress.store(true, std::memory_order_relaxed);
|
||||
|
||||
// Swap buffers and start streaming in background.
|
||||
audio_bus->SwapBuffers();
|
||||
src[0] = audio_bus->GetChannelData(0);
|
||||
src[1] = audio_bus->GetChannelData(1);
|
||||
if (!src[1])
|
||||
src[1] = src[0]; // mono.
|
||||
num_samples = audio_bus->samples_per_channel();
|
||||
|
||||
ThreadPool::Get().PostTask(
|
||||
HERE,
|
||||
std::bind(&AudioMixer::DoStream, this, *it,
|
||||
flags & MixerInput::kLoop),
|
||||
true);
|
||||
} else {
|
||||
DLOG(0) << "Mixer buffer underrun!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*it)->src_index = src_index;
|
||||
(*it)->accumulator = accumulator;
|
||||
(*it)->amplitude = amplitude;
|
||||
// Remember last sample position and volume.
|
||||
(*it)->SetPosition(src_index, accumulator);
|
||||
(*it)->SetAmplitude(amplitude);
|
||||
}
|
||||
|
||||
if (marked_for_removal) {
|
||||
|
@ -160,9 +149,9 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
}
|
||||
|
||||
for (auto it = removed_inputs_.begin(); it != removed_inputs_.end();) {
|
||||
if (!(*it)->streaming_in_progress.load(std::memory_order_relaxed)) {
|
||||
if (!(*it)->IsStreamingInProgress()) {
|
||||
main_thread_task_runner_->PostTask(
|
||||
HERE, std::bind(&AudioMixer::EndCallback, this, *it));
|
||||
HERE, std::bind(&MixerInput::OnRemovedFromMixer, *it));
|
||||
it = removed_inputs_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
|
@ -170,25 +159,4 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioMixer::DoStream(std::shared_ptr<MixerInput> input, bool loop) {
|
||||
input->audio_bus->Stream(loop);
|
||||
input->streaming_in_progress.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void AudioMixer::EndCallback(std::shared_ptr<MixerInput> input) {
|
||||
input->streaming = false;
|
||||
|
||||
if (input->pending_audio_bus) {
|
||||
input->audio_bus = input->pending_audio_bus;
|
||||
input->pending_audio_bus.reset();
|
||||
}
|
||||
|
||||
if (input->end_cb)
|
||||
input->end_cb();
|
||||
if (input->restart_cb) {
|
||||
input->restart_cb();
|
||||
input->restart_cb = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace eng
|
||||
|
|
|
@ -14,8 +14,7 @@ class TaskRunner;
|
|||
|
||||
namespace eng {
|
||||
|
||||
class AudioBus;
|
||||
struct MixerInput;
|
||||
class MixerInput;
|
||||
|
||||
// Mix and render audio with low overhead. The mixer has zero or more inputs
|
||||
// which can be added at any time. The mixer will pull from each input source
|
||||
|
@ -29,7 +28,7 @@ class AudioMixer : public AudioSink::Delegate {
|
|||
AudioMixer();
|
||||
~AudioMixer();
|
||||
|
||||
void AddInput(std::shared_ptr<MixerInput> input);
|
||||
void AddInput(std::shared_ptr<MixerInput> mixer_input);
|
||||
|
||||
void SetEnableAudio(bool enable) { audio_enabled_ = enable; }
|
||||
bool IsAudioEnabled() const { return audio_enabled_; }
|
||||
|
@ -57,10 +56,6 @@ class AudioMixer : public AudioSink::Delegate {
|
|||
int GetChannelCount() final { return kChannelCount; }
|
||||
void RenderAudio(float* output_buffer, size_t num_frames) final;
|
||||
|
||||
void DoStream(std::shared_ptr<MixerInput> sample, bool loop);
|
||||
|
||||
void EndCallback(std::shared_ptr<MixerInput> sample);
|
||||
|
||||
AudioMixer(const AudioMixer&) = delete;
|
||||
AudioMixer& operator=(const AudioMixer&) = delete;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "engine/audio/mixer_input.h"
|
||||
|
||||
#include "base/log.h"
|
||||
#include "base/thread_pool.h"
|
||||
#include "engine/audio/audio_bus.h"
|
||||
#include "engine/audio/audio_mixer.h"
|
||||
|
||||
|
@ -21,78 +22,124 @@ std::shared_ptr<MixerInput> MixerInput::Create() {
|
|||
return std::shared_ptr<MixerInput>(new MixerInput());
|
||||
}
|
||||
|
||||
void MixerInput::SetAudioBus(std::shared_ptr<AudioBus> bus) {
|
||||
if (streaming)
|
||||
pending_audio_bus = bus;
|
||||
void MixerInput::SetAudioBus(std::shared_ptr<AudioBus> audio_bus) {
|
||||
if (playing_)
|
||||
pending_audio_bus_ = audio_bus;
|
||||
else
|
||||
audio_bus = bus;
|
||||
audio_bus_ = audio_bus;
|
||||
}
|
||||
|
||||
void MixerInput::Play(AudioMixer* mixer, bool restart) {
|
||||
if (!mixer->IsAudioEnabled())
|
||||
if (!mixer->IsAudioEnabled()) {
|
||||
if (!playing_ && end_cb_)
|
||||
end_cb_();
|
||||
return;
|
||||
}
|
||||
|
||||
// If already streaming check if stream position needs to be reset.
|
||||
if (streaming) {
|
||||
// If already playing check if stream position needs to be reset.
|
||||
if (playing_) {
|
||||
if (restart)
|
||||
flags.fetch_or(kStopped, std::memory_order_relaxed);
|
||||
flags_.fetch_or(kStopped, std::memory_order_relaxed);
|
||||
|
||||
if (flags.load(std::memory_order_relaxed) & kStopped)
|
||||
restart_cb = [&, mixer, restart]() -> void { Play(mixer, restart); };
|
||||
if (flags_.load(std::memory_order_relaxed) & kStopped)
|
||||
restart_cb_ = [&, mixer, restart]() -> void { Play(mixer, restart); };
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (restart || audio_bus->EndOfStream()) {
|
||||
src_index = 0;
|
||||
accumulator = 0;
|
||||
audio_bus->ResetStream();
|
||||
if (restart || audio_bus_->EndOfStream()) {
|
||||
src_index_ = 0;
|
||||
accumulator_ = 0;
|
||||
audio_bus_->ResetStream();
|
||||
}
|
||||
|
||||
streaming = true;
|
||||
flags.fetch_and(~kStopped, std::memory_order_relaxed);
|
||||
playing_ = true;
|
||||
flags_.fetch_and(~kStopped, std::memory_order_relaxed);
|
||||
mixer->AddInput(shared_from_this());
|
||||
}
|
||||
|
||||
void MixerInput::Stop() {
|
||||
if (streaming) {
|
||||
restart_cb = nullptr;
|
||||
flags.fetch_or(kStopped, std::memory_order_relaxed);
|
||||
if (playing_) {
|
||||
restart_cb_ = nullptr;
|
||||
flags_.fetch_or(kStopped, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void MixerInput::SetLoop(bool loop) {
|
||||
if (loop)
|
||||
flags.fetch_or(kLoop, std::memory_order_relaxed);
|
||||
flags_.fetch_or(kLoop, std::memory_order_relaxed);
|
||||
else
|
||||
flags.fetch_and(~kLoop, std::memory_order_relaxed);
|
||||
flags_.fetch_and(~kLoop, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetSimulateStereo(bool simulate) {
|
||||
if (simulate)
|
||||
flags.fetch_or(kSimulateStereo, std::memory_order_relaxed);
|
||||
flags_.fetch_or(kSimulateStereo, std::memory_order_relaxed);
|
||||
else
|
||||
flags.fetch_and(~kSimulateStereo, std::memory_order_relaxed);
|
||||
flags_.fetch_and(~kSimulateStereo, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetResampleStep(size_t value) {
|
||||
step.store(value + 100, std::memory_order_relaxed);
|
||||
step_.store(value + 100, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetAmplitude(float value) {
|
||||
amplitude.store(value, std::memory_order_relaxed);
|
||||
amplitude_.store(value, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetMaxAmplitude(float value) {
|
||||
max_amplitude.store(value, std::memory_order_relaxed);
|
||||
max_amplitude_.store(value, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetAmplitudeInc(float value) {
|
||||
amplitude_inc.store(value, std::memory_order_relaxed);
|
||||
amplitude_inc_.store(value, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetEndCallback(base::Closure cb) {
|
||||
end_cb = std::move(cb);
|
||||
end_cb_ = std::move(cb);
|
||||
}
|
||||
|
||||
bool MixerInput::IsStreamingInProgress() const {
|
||||
return streaming_in_progress_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MixerInput::SetPosition(size_t index, int accumulator) {
|
||||
src_index_ = index;
|
||||
accumulator_ = accumulator;
|
||||
}
|
||||
|
||||
bool MixerInput::OnMoreData(bool loop) {
|
||||
if (streaming_in_progress_.load(std::memory_order_acquire))
|
||||
return false;
|
||||
|
||||
streaming_in_progress_.store(true, std::memory_order_relaxed);
|
||||
audio_bus_->SwapBuffers();
|
||||
ThreadPool::Get().PostTask(
|
||||
HERE,
|
||||
[&, loop]() {
|
||||
audio_bus_->Stream(loop);
|
||||
streaming_in_progress_.store(false, std::memory_order_release);
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MixerInput::OnRemovedFromMixer() {
|
||||
DCHECK(!streaming_in_progress_.load(std::memory_order_relaxed));
|
||||
DCHECK(playing_);
|
||||
playing_ = false;
|
||||
|
||||
if (pending_audio_bus_) {
|
||||
audio_bus_ = pending_audio_bus_;
|
||||
pending_audio_bus_.reset();
|
||||
}
|
||||
|
||||
if (end_cb_)
|
||||
end_cb_();
|
||||
if (restart_cb_) {
|
||||
restart_cb_();
|
||||
restart_cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace eng
|
||||
|
|
|
@ -13,16 +13,19 @@ class AudioMixer;
|
|||
|
||||
// An audio input stream that gets mixed and rendered to the audio sink. Handles
|
||||
// playback and volume control.
|
||||
struct MixerInput : public std::enable_shared_from_this<MixerInput> {
|
||||
class MixerInput : public std::enable_shared_from_this<MixerInput> {
|
||||
public:
|
||||
enum Flags { kLoop = 1, kStopped = 2, kSimulateStereo = 4 };
|
||||
|
||||
~MixerInput();
|
||||
|
||||
static std::shared_ptr<MixerInput> Create();
|
||||
|
||||
// Set AudioBus for playback. If this MixerInput is already streaming, keeps
|
||||
// it as pending and sets once playback ends.
|
||||
void SetAudioBus(std::shared_ptr<AudioBus> bus);
|
||||
bool IsValid() const { return !!audio_bus_; }
|
||||
|
||||
// Set AudioBus for playback. If this MixerInput is already playing, keeps it
|
||||
// as pending and sets once playback ends.
|
||||
void SetAudioBus(std::shared_ptr<AudioBus> audio_bus);
|
||||
|
||||
// Starts playback. Remembers last stream position. Resets the stream position
|
||||
// if restart is true.
|
||||
|
@ -31,6 +34,7 @@ struct MixerInput : public std::enable_shared_from_this<MixerInput> {
|
|||
// Stops playback. Does not reset stream position.
|
||||
void Stop();
|
||||
|
||||
// Set whether the playback should loop or not.
|
||||
void SetLoop(bool loop);
|
||||
|
||||
// Simulate stereo effect slightly delays one channel.
|
||||
|
@ -47,30 +51,57 @@ struct MixerInput : public std::enable_shared_from_this<MixerInput> {
|
|||
// Set a callback to be called once playback ends.
|
||||
void SetEndCallback(base::Closure cb);
|
||||
|
||||
// Active AudioBus.
|
||||
std::shared_ptr<AudioBus> audio_bus;
|
||||
// AudioBus to be set as active once playback ends.
|
||||
std::shared_ptr<AudioBus> pending_audio_bus;
|
||||
// Stream position.
|
||||
size_t src_index = 0;
|
||||
size_t accumulator = 0;
|
||||
// Getters
|
||||
std::shared_ptr<AudioBus> GetAudioBus() const { return audio_bus_; }
|
||||
unsigned GetFlags() const { return flags_.load(std::memory_order_relaxed); }
|
||||
size_t GetStep() const { return step_.load(std::memory_order_relaxed); }
|
||||
float GetAmplitude() const {
|
||||
return amplitude_.load(std::memory_order_relaxed);
|
||||
}
|
||||
float GetAmplitudeInc() const {
|
||||
return amplitude_inc_.load(std::memory_order_relaxed);
|
||||
}
|
||||
float GetMaxAmplitude() const {
|
||||
return max_amplitude_.load(std::memory_order_relaxed);
|
||||
}
|
||||
size_t GetSrcIndex() const { return src_index_; }
|
||||
size_t GetAccumulator() const { return accumulator_; }
|
||||
|
||||
// Accessed by main thread only.
|
||||
bool streaming = false;
|
||||
base::Closure end_cb;
|
||||
base::Closure restart_cb;
|
||||
bool IsStreamingInProgress() const;
|
||||
|
||||
// Accessed by main thread and audio thread.
|
||||
std::atomic<unsigned> flags{0};
|
||||
std::atomic<size_t> step{100};
|
||||
std::atomic<float> amplitude{1.0f};
|
||||
std::atomic<float> amplitude_inc{0};
|
||||
std::atomic<float> max_amplitude{1.0f};
|
||||
// Called by the mixer to save the last sample position.
|
||||
void SetPosition(size_t index, int accumulator);
|
||||
|
||||
// Accessed by audio thread and decoding worker thread.
|
||||
std::atomic<bool> streaming_in_progress{false};
|
||||
// Called by the mixer when more data is needed.
|
||||
bool OnMoreData(bool loop);
|
||||
|
||||
// Called by the mixer when playback ends.
|
||||
void OnRemovedFromMixer();
|
||||
|
||||
private:
|
||||
// Active AudioBus.
|
||||
std::shared_ptr<AudioBus> audio_bus_;
|
||||
// AudioBus to be set as active once playback ends.
|
||||
std::shared_ptr<AudioBus> pending_audio_bus_;
|
||||
// Stream position.
|
||||
size_t src_index_ = 0;
|
||||
size_t accumulator_ = 0;
|
||||
|
||||
// Accessed by main thread only.
|
||||
bool playing_ = false;
|
||||
base::Closure end_cb_;
|
||||
base::Closure restart_cb_;
|
||||
|
||||
// Accessed by main thread and audio thread.
|
||||
std::atomic<unsigned> flags_{0};
|
||||
std::atomic<size_t> step_{100};
|
||||
std::atomic<float> amplitude_{1.0f};
|
||||
std::atomic<float> amplitude_inc_{0};
|
||||
std::atomic<float> max_amplitude_{1.0f};
|
||||
|
||||
// Accessed by audio thread and decoding worker thread.
|
||||
std::atomic<bool> streaming_in_progress_{false};
|
||||
|
||||
MixerInput();
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ void SoundPlayer::SetSound(std::shared_ptr<AudioBus> sound) {
|
|||
}
|
||||
|
||||
void SoundPlayer::Play(bool loop, float fade_in_duration) {
|
||||
if (!input_->audio_bus)
|
||||
if (!input_->IsValid())
|
||||
return;
|
||||
|
||||
int step = variate_ ? Engine::Get().GetRandomGenerator().Roll(3) - 2 : 0;
|
||||
|
@ -35,7 +35,7 @@ void SoundPlayer::Play(bool loop, float fade_in_duration) {
|
|||
if (fade_in_duration > 0) {
|
||||
input_->SetAmplitude(0);
|
||||
input_->SetAmplitudeInc(
|
||||
1.0f / (input_->audio_bus->sample_rate() * fade_in_duration));
|
||||
1.0f / (input_->GetAudioBus()->sample_rate() * fade_in_duration));
|
||||
} else {
|
||||
input_->SetAmplitude(max_amplitude_);
|
||||
input_->SetAmplitudeInc(0);
|
||||
|
@ -44,24 +44,24 @@ void SoundPlayer::Play(bool loop, float fade_in_duration) {
|
|||
}
|
||||
|
||||
void SoundPlayer::Resume(float fade_in_duration) {
|
||||
if (!input_->audio_bus)
|
||||
if (!input_->IsValid())
|
||||
return;
|
||||
|
||||
if (fade_in_duration > 0) {
|
||||
input_->SetAmplitude(0);
|
||||
input_->SetAmplitudeInc(
|
||||
1.0f / (input_->audio_bus->sample_rate() * fade_in_duration));
|
||||
1.0f / (input_->GetAudioBus()->sample_rate() * fade_in_duration));
|
||||
}
|
||||
input_->Play(Engine::Get().GetAudioMixer(), false);
|
||||
}
|
||||
|
||||
void SoundPlayer::Stop(float fade_out_duration) {
|
||||
if (!input_->audio_bus)
|
||||
if (!input_->IsValid())
|
||||
return;
|
||||
|
||||
if (fade_out_duration > 0)
|
||||
input_->SetAmplitudeInc(
|
||||
-1.0f / (input_->audio_bus->sample_rate() * fade_out_duration));
|
||||
-1.0f / (input_->GetAudioBus()->sample_rate() * fade_out_duration));
|
||||
else
|
||||
input_->Stop();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace eng {
|
||||
|
||||
class AudioBus;
|
||||
struct MixerInput;
|
||||
class MixerInput;
|
||||
|
||||
class SoundPlayer {
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue