Skip to content

Commit

Permalink
Fix capture and record audioeffect bugs for surround systems.
Browse files Browse the repository at this point in the history
  • Loading branch information
BuzzLord committed May 31, 2024
1 parent 2551986 commit c3f8750
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 9 deletions.
3 changes: 3 additions & 0 deletions doc/classes/AudioEffectCapture.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
</method>
</methods>
<members>
<member name="active_channel" type="int" setter="set_active_channel" getter="get_active_channel" default="0">
The audio bus channel that is captured by the effect.
</member>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="0.1">
Length of the internal ring buffer, in seconds. Setting the buffer length will have no effect if already initialized.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/AudioEffectRecord.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
</method>
</methods>
<members>
<member name="active_channel" type="int" setter="set_active_channel" getter="get_active_channel" default="0">
The audio bus channel that is used for recording by the effect. Note that changing to a different channel will remove the previously recorded sample.
</member>
<member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="1">
Specifies the format in which the sample will be recorded. See [enum AudioStreamWAV.Format] for available formats.
</member>
Expand Down
1 change: 1 addition & 0 deletions servers/audio/audio_effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class AudioEffectInstance : public RefCounted {
public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
virtual bool process_silence() const;
virtual void set_current_channel(int p_channel) {}
};

class AudioEffect : public Resource {
Expand Down
15 changes: 15 additions & 0 deletions servers/audio/effects/audio_effect_capture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ void AudioEffectCapture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_discarded_frames"), &AudioEffectCapture::get_discarded_frames);
ClassDB::bind_method(D_METHOD("get_buffer_length_frames"), &AudioEffectCapture::get_buffer_length_frames);
ClassDB::bind_method(D_METHOD("get_pushed_frames"), &AudioEffectCapture::get_pushed_frames);
ClassDB::bind_method(D_METHOD("set_active_channel", "channel"), &AudioEffectCapture::set_active_channel);
ClassDB::bind_method(D_METHOD("get_active_channel"), &AudioEffectCapture::get_active_channel);

ADD_PROPERTY(PropertyInfo(Variant::INT, "active_channel", PROPERTY_HINT_ENUM, "Stereo,3.1,5.1,7.1"), "set_active_channel", "get_active_channel");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}

Expand Down Expand Up @@ -116,13 +119,25 @@ int64_t AudioEffectCapture::get_pushed_frames() const {
return pushed_frames.get();
}

void AudioEffectCapture::set_active_channel(int p_channel) {
active_channel = p_channel;
}

int AudioEffectCapture::get_active_channel() const {
return active_channel;
}

void AudioEffectCaptureInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
RingBuffer<AudioFrame> &buffer = base->buffer;

for (int i = 0; i < p_frame_count; i++) {
p_dst_frames[i] = p_src_frames[i];
}

if (base->get_active_channel() != current_channel) {
return;
}

if (buffer.space_left() >= p_frame_count) {
// Add incoming audio frames to the IO ring buffer
int32_t ret = buffer.write(p_src_frames, p_frame_count);
Expand Down
6 changes: 6 additions & 0 deletions servers/audio/effects/audio_effect_capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ class AudioEffectCaptureInstance : public AudioEffectInstance {
GDCLASS(AudioEffectCaptureInstance, AudioEffectInstance);
friend class AudioEffectCapture;
Ref<AudioEffectCapture> base;
int current_channel;

public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) override;
virtual bool process_silence() const override;
virtual void set_current_channel(int p_channel) override { current_channel = p_channel; }
};

class AudioEffectCapture : public AudioEffect {
Expand All @@ -60,6 +62,7 @@ class AudioEffectCapture : public AudioEffect {
SafeNumeric<uint64_t> pushed_frames;
float buffer_length_seconds = 0.1f;
bool buffer_initialized = false;
int active_channel = 0;

protected:
static void _bind_methods();
Expand All @@ -78,6 +81,9 @@ class AudioEffectCapture : public AudioEffect {
int64_t get_discarded_frames() const;
int get_buffer_length_frames() const;
int64_t get_pushed_frames() const;

void set_active_channel(int p_channel);
int get_active_channel() const;
};

#endif // AUDIO_EFFECT_CAPTURE_H
2 changes: 1 addition & 1 deletion servers/audio/effects/audio_effect_compressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AudioEffectCompressorInstance : public AudioEffectInstance {
int current_channel;

public:
void set_current_channel(int p_channel) { current_channel = p_channel; }
virtual void set_current_channel(int p_channel) override { current_channel = p_channel; }
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) override;
};

Expand Down
45 changes: 40 additions & 5 deletions servers/audio/effects/audio_effect_record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ bool AudioEffectRecordInstance::process_silence() const {
return true;
}

void AudioEffectRecordInstance::set_current_channel(int p_channel) {
base->register_channel_instance(p_channel, Ref<AudioEffectRecordInstance>(this));
}

void AudioEffectRecordInstance::_io_thread_process() {
while (is_recording) {
_update_buffer();
Expand Down Expand Up @@ -123,6 +127,7 @@ void AudioEffectRecordInstance::finish() {
Ref<AudioEffectInstance> AudioEffectRecord::instantiate() {
Ref<AudioEffectRecordInstance> ins;
ins.instantiate();
ins->base = Ref<AudioEffectRecord>(this);
ins->is_recording = false;

//Re-using the buffer size calculations from audio_effect_delay.cpp
Expand All @@ -147,17 +152,26 @@ Ref<AudioEffectInstance> AudioEffectRecord::instantiate() {

ins->ring_buffer_read_pos = 0;

ensure_thread_stopped();
return ins;
}

void AudioEffectRecord::set_current_instance(Ref<AudioEffectRecordInstance> p_instance) {
bool is_currently_recording = false;
if (current_instance != nullptr) {
is_currently_recording = current_instance->is_recording;
}
if (is_currently_recording) {
ins->init();
ensure_thread_stopped();
if (is_currently_recording && p_instance != nullptr) {
p_instance->init();
}
current_instance = ins;
current_instance = p_instance;
}

return ins;
void AudioEffectRecord::register_channel_instance(int p_channel, Ref<AudioEffectRecordInstance> p_instance) {
if (active_channel == p_channel) {
set_current_instance(p_instance);
}
channel_instances.insert(p_channel, p_instance);
}

void AudioEffectRecord::ensure_thread_stopped() {
Expand Down Expand Up @@ -197,6 +211,24 @@ AudioStreamWAV::Format AudioEffectRecord::get_format() const {
return format;
}

void AudioEffectRecord::set_active_channel(int p_channel) {
if (active_channel == p_channel) {
return;
}
active_channel = p_channel;
HashMap<int, Ref<AudioEffectRecordInstance>>::Iterator it = channel_instances.find(p_channel);
if (it) {
set_current_instance(it->value);
} else {
WARN_PRINT("Active channel set to uninitialized channel idx " + itos(p_channel) + ".");
set_current_instance(Ref<AudioEffectRecordInstance>());
}
}

int AudioEffectRecord::get_active_channel() const {
return active_channel;
}

Ref<AudioStreamWAV> AudioEffectRecord::get_recording() const {
AudioStreamWAV::Format dst_format = format;
bool stereo = true; //forcing mono is not implemented
Expand Down Expand Up @@ -282,7 +314,10 @@ void AudioEffectRecord::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioEffectRecord::set_format);
ClassDB::bind_method(D_METHOD("get_format"), &AudioEffectRecord::get_format);
ClassDB::bind_method(D_METHOD("get_recording"), &AudioEffectRecord::get_recording);
ClassDB::bind_method(D_METHOD("set_active_channel", "channel"), &AudioEffectRecord::set_active_channel);
ClassDB::bind_method(D_METHOD("get_active_channel"), &AudioEffectRecord::get_active_channel);

ADD_PROPERTY(PropertyInfo(Variant::INT, "active_channel", PROPERTY_HINT_ENUM, "Stereo,3.1,5.1,7.1"), "set_active_channel", "get_active_channel");
ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
}

Expand Down
8 changes: 8 additions & 0 deletions servers/audio/effects/audio_effect_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class AudioEffectRecord;
class AudioEffectRecordInstance : public AudioEffectInstance {
GDCLASS(AudioEffectRecordInstance, AudioEffectInstance);
friend class AudioEffectRecord;
Ref<AudioEffectRecord> base;

bool is_recording;
Thread io_thread;
Expand All @@ -67,6 +68,7 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
void finish();
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) override;
virtual bool process_silence() const override;
virtual void set_current_channel(int p_channel) override;
};

class AudioEffectRecord : public AudioEffect {
Expand All @@ -78,10 +80,14 @@ class AudioEffectRecord : public AudioEffect {
IO_BUFFER_SIZE_MS = 1500
};

HashMap<int, Ref<AudioEffectRecordInstance>> channel_instances;
Ref<AudioEffectRecordInstance> current_instance;
int active_channel = 0;

AudioStreamWAV::Format format;

void set_current_instance(Ref<AudioEffectRecordInstance> p_instance);
void register_channel_instance(int p_channel, Ref<AudioEffectRecordInstance> p_instance);
void ensure_thread_stopped();

protected:
Expand All @@ -93,6 +99,8 @@ class AudioEffectRecord : public AudioEffect {
bool is_recording_active() const;
void set_format(AudioStreamWAV::Format p_format);
AudioStreamWAV::Format get_format() const;
void set_active_channel(int p_channel);
int get_active_channel() const;
Ref<AudioStreamWAV> get_recording() const;
AudioEffectRecord();
~AudioEffectRecord();
Expand Down
4 changes: 1 addition & 3 deletions servers/audio_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,9 +1006,7 @@ void AudioServer::_update_bus_effects(int p_bus) {
buses.write[p_bus]->channels.write[i].effect_instances.resize(buses[p_bus]->effects.size());
for (int j = 0; j < buses[p_bus]->effects.size(); j++) {
Ref<AudioEffectInstance> fx = buses.write[p_bus]->effects.write[j].effect->instantiate();
if (Object::cast_to<AudioEffectCompressorInstance>(*fx)) {
Object::cast_to<AudioEffectCompressorInstance>(*fx)->set_current_channel(i);
}
fx->set_current_channel(i);
buses.write[p_bus]->channels.write[i].effect_instances.write[j] = fx;
}
}
Expand Down

0 comments on commit c3f8750

Please sign in to comment.