Fix AudioEffectRecord not working without thread support

This commit is contained in:
Marcelo Fernandez 2018-10-10 10:58:29 -03:00
parent 4c1a5d9cfe
commit 7da55fb739
4 changed files with 78 additions and 17 deletions

View File

@ -44,20 +44,25 @@ void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFra
} }
} }
void AudioEffectRecordInstance::_update_buffer() {
//Case: Frames are remaining in the buffer
while (ring_buffer_read_pos < ring_buffer_pos) {
//Read from the buffer into recording_data
_io_store_buffer();
}
}
void AudioEffectRecordInstance::_update(void *userdata) {
AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata;
ins->_update_buffer();
}
bool AudioEffectRecordInstance::process_silence() const { bool AudioEffectRecordInstance::process_silence() const {
return true; return true;
} }
void AudioEffectRecordInstance::_io_thread_process() { void AudioEffectRecordInstance::_io_thread_process() {
//Reset recorder status
thread_active = true; thread_active = true;
ring_buffer_pos = 0;
ring_buffer_read_pos = 0;
//We start a new recording
recording_data.resize(0); //Clear data completely and reset length
is_recording = true;
while (is_recording) { while (is_recording) {
//Check: The current recording has been requested to stop //Check: The current recording has been requested to stop
@ -65,13 +70,9 @@ void AudioEffectRecordInstance::_io_thread_process() {
is_recording = false; is_recording = false;
} }
//Case: Frames are remaining in the buffer _update_buffer();
if (ring_buffer_read_pos < ring_buffer_pos) {
//Read from the buffer into recording_data if (is_recording) {
_io_store_buffer();
}
//Case: The buffer is empty
else if (is_recording) {
//Wait to avoid too much busy-wait //Wait to avoid too much busy-wait
OS::get_singleton()->delay_usec(500); OS::get_singleton()->delay_usec(500);
} }
@ -103,7 +104,35 @@ void AudioEffectRecordInstance::_thread_callback(void *_instance) {
} }
void AudioEffectRecordInstance::init() { void AudioEffectRecordInstance::init() {
//Reset recorder status
ring_buffer_pos = 0;
ring_buffer_read_pos = 0;
//We start a new recording
recording_data.resize(0); //Clear data completely and reset length
is_recording = true;
#ifdef NO_THREADS
AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
#else
io_thread = Thread::create(_thread_callback, this); io_thread = Thread::create(_thread_callback, this);
#endif
}
void AudioEffectRecordInstance::finish() {
#ifdef NO_THREADS
AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
#else
if (thread_active) {
Thread::wait_to_finish(io_thread);
}
#endif
}
AudioEffectRecordInstance::~AudioEffectRecordInstance() {
finish();
} }
Ref<AudioEffectInstance> AudioEffectRecord::instance() { Ref<AudioEffectInstance> AudioEffectRecord::instance() {
@ -145,8 +174,8 @@ Ref<AudioEffectInstance> AudioEffectRecord::instance() {
void AudioEffectRecord::ensure_thread_stopped() { void AudioEffectRecord::ensure_thread_stopped() {
recording_active = false; recording_active = false;
if (current_instance != 0 && current_instance->thread_active) { if (current_instance != 0) {
Thread::wait_to_finish(current_instance->io_thread); current_instance->finish();
} }
} }

View File

@ -62,14 +62,18 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
void _io_store_buffer(); void _io_store_buffer();
static void _thread_callback(void *_instance); static void _thread_callback(void *_instance);
void _init_recording(); void _init_recording();
void _update_buffer();
static void _update(void *userdata);
public: public:
void init(); void init();
void finish();
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count); virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
virtual bool process_silence() const; virtual bool process_silence() const;
AudioEffectRecordInstance() : AudioEffectRecordInstance() :
thread_active(false) {} thread_active(false) {}
~AudioEffectRecordInstance();
}; };
class AudioEffectRecord : public AudioEffect { class AudioEffectRecord : public AudioEffect {

View File

@ -1004,6 +1004,11 @@ void AudioServer::update() {
AudioDriver::get_singleton()->reset_profiling_time(); AudioDriver::get_singleton()->reset_profiling_time();
prof_time = 0; prof_time = 0;
#endif #endif
for (Set<CallbackItem>::Element *E = update_callbacks.front(); E; E = E->next()) {
E->get().callback(E->get().userdata);
}
} }
void AudioServer::load_default_bus_layout() { void AudioServer::load_default_bus_layout() {
@ -1129,6 +1134,25 @@ void AudioServer::remove_callback(AudioCallback p_callback, void *p_userdata) {
unlock(); unlock();
} }
void AudioServer::add_update_callback(AudioCallback p_callback, void *p_userdata) {
lock();
CallbackItem ci;
ci.callback = p_callback;
ci.userdata = p_userdata;
update_callbacks.insert(ci);
unlock();
}
void AudioServer::remove_update_callback(AudioCallback p_callback, void *p_userdata) {
lock();
CallbackItem ci;
ci.callback = p_callback;
ci.userdata = p_userdata;
update_callbacks.erase(ci);
unlock();
}
void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) { void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
ERR_FAIL_COND(p_bus_layout.is_null() || p_bus_layout->buses.size() == 0); ERR_FAIL_COND(p_bus_layout.is_null() || p_bus_layout->buses.size() == 0);

View File

@ -262,6 +262,7 @@ private:
}; };
Set<CallbackItem> callbacks; Set<CallbackItem> callbacks;
Set<CallbackItem> update_callbacks;
friend class AudioDriver; friend class AudioDriver;
void _driver_process(int p_frames, int32_t *p_buffer); void _driver_process(int p_frames, int32_t *p_buffer);
@ -357,6 +358,9 @@ public:
void add_callback(AudioCallback p_callback, void *p_userdata); void add_callback(AudioCallback p_callback, void *p_userdata);
void remove_callback(AudioCallback p_callback, void *p_userdata); void remove_callback(AudioCallback p_callback, void *p_userdata);
void add_update_callback(AudioCallback p_callback, void *p_userdata);
void remove_update_callback(AudioCallback p_callback, void *p_userdata);
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout); void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const; Ref<AudioBusLayout> generate_bus_layout() const;