X Tutup
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
6 changes: 6 additions & 0 deletions doc/classes/AudioEffect.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
<link title="Audio Microphone Record Demo">https://godotengine.org/asset-library/asset/2760</link>
</tutorials>
<methods>
<method name="_finalize" qualifiers="virtual">
<return type="void" />
<description>
Override this method to do any finalization in the [AudioEffect] after all [AudioEffectInstance]s have been created.
</description>
</method>
<method name="_instantiate" qualifiers="virtual required">
<return type="AudioEffectInstance" />
<description>
Expand Down
30 changes: 19 additions & 11 deletions doc/classes/AudioEffectCapture.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
Captures audio from an audio bus in real-time.
</brief_description>
<description>
AudioEffectCapture is an AudioEffect which copies all audio frames from the attached audio effect bus into its internal ring buffer.
Application code should consume these audio frames from this ring buffer using [method get_buffer] and process it as needed, for example to capture data from an [AudioStreamMicrophone], implement application-defined effects, or to transmit audio over the network. When capturing audio data from a microphone, the format of the samples will be stereo 32-bit floating-point PCM.
Unlike [AudioEffectRecord], this effect only returns the raw audio samples instead of encoding them into an [AudioStream].
AudioEffectCapture is an AudioEffect which copies all audio frames from the attached audio effect bus into its internal ring buffer(s). Processing is done per channel by [AudioEffectCaptureInstance]. The parent AudioEffectCapture allows accessing data per-channel via the channel parameter on the get methods, or it can be accessed directly from [AudioEffectCaptureInstance] using [method AudioServer.get_bus_effect_instance].
Application code should consume audio frames from the ring buffer using [method get_buffer] and process it as needed, for example to capture data from an [AudioStreamMicrophone], implement application-defined effects, or to transmit audio over the network. When capturing audio data from a microphone, the format of the samples will be stereo 32-bit floating-point PCM.
Unlike [AudioEffectRecord] or [AudioEffectRecordInstance], this effect only returns the raw audio samples instead of encoding them into an [AudioStream].
[b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings.
</description>
<tutorials>
<link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link>
Expand All @@ -15,54 +16,61 @@
<method name="can_get_buffer" qualifiers="const">
<return type="bool" />
<param index="0" name="frames" type="int" />
<param index="1" name="channel" type="int" default="0" />
<description>
Returns [code]true[/code] if at least [param frames] audio frames are available to read in the internal ring buffer.
Returns [code]true[/code] if at least [param frames] audio frames are available to read in the internal ring buffer of the given [param channel]'s [AudioEffectCaptureInstance].
</description>
</method>
<method name="clear_buffer">
<return type="void" />
<param index="0" name="channel" type="int" default="0" />
<description>
Clears the internal ring buffer.
Clears the internal ring buffer for the given [param channel]'s [AudioEffectCaptureInstance].
[b]Note:[/b] Calling this during a capture can cause the loss of samples which causes popping in the playback.
</description>
</method>
<method name="get_buffer">
<return type="PackedVector2Array" />
<param index="0" name="frames" type="int" />
<param index="1" name="channel" type="int" default="0" />
<description>
Gets the next [param frames] audio samples from the internal ring buffer.
Gets the next [param frames] audio samples from the internal ring buffer on the given [param channel]'s [AudioEffectCaptureInstance].
Returns a [PackedVector2Array] containing exactly [param frames] audio samples if available, or an empty [PackedVector2Array] if insufficient data was available.
The samples are signed floating-point PCM between [code]-1[/code] and [code]1[/code]. You will have to scale them if you want to use them as 8 or 16-bit integer samples. ([code]v = 0x7fff * samples[0].x[/code])
</description>
</method>
<method name="get_buffer_length_frames" qualifiers="const">
<return type="int" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns the total size of the internal ring buffer in frames.
Returns the total size of the internal ring buffer in frames on the given [param channel]'s [AudioEffectCaptureInstance].
</description>
</method>
<method name="get_discarded_frames" qualifiers="const">
<return type="int" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns the number of audio frames discarded from the audio bus due to full buffer.
Returns the number of audio frames discarded from the audio bus due to full buffer on the given [param channel]'s [AudioEffectCaptureInstance].
</description>
</method>
<method name="get_frames_available" qualifiers="const">
<return type="int" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns the number of frames available to read using [method get_buffer].
Returns the number of frames available to read using [method get_buffer], for the given [param channel]'s [AudioEffectCaptureInstance].
</description>
</method>
<method name="get_pushed_frames" qualifiers="const">
<return type="int" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns the number of audio frames inserted from the audio bus.
Returns the number of audio frames inserted from the audio bus, for the given [param channel]'s [AudioEffectCaptureInstance].
</description>
</method>
</methods>
<members>
<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.
Length of the internal ring buffer(s), in seconds. Setting the buffer length will have no effect if already initialized.
</member>
</members>
</class>
70 changes: 70 additions & 0 deletions doc/classes/AudioEffectCaptureInstance.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectCaptureInstance" inherits="AudioEffectInstance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Captures audio from an audio bus, on a specific channel, in real-time.
</brief_description>
<description>
AudioEffectCaptureInstance is an instance of AudioEffectCapture which copies all audio frames from a specific channel of the attached audio effect bus into its internal ring buffer.
Access to instances of this class can be obtained with [method AudioServer.get_bus_effect_instance]. The parent AudioEffectCapture object mirrors the AudioEffectCaptureInstance created for channel 0, so method calls on the parent are passed straight through to the channel 0 instance.
Application code may consume these audio frames from this ring buffer using [method get_buffer] and process it as needed, for example to capture data from an [AudioStreamMicrophone], implement application-defined effects, or to transmit audio over the network. When capturing audio data from a microphone, the format of the samples will be stereo 32-bit floating-point PCM.
Unlike [AudioEffectRecord] or [AudioEffectRecordInstance], this effect only returns the raw audio samples instead of encoding them into an [AudioStream].
[b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings.
</description>
<tutorials>
<link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link>
</tutorials>
<methods>
<method name="can_get_buffer" qualifiers="const">
<return type="bool" />
<param index="0" name="frames" type="int" />
<description>
Returns [code]true[/code] if at least [param frames] audio frames are available to read in the internal ring buffer.
</description>
</method>
<method name="clear_buffer">
<return type="void" />
<description>
Clears the internal ring buffer.
[b]Note:[/b] Calling this during a capture can cause the loss of samples which causes popping in the playback.
</description>
</method>
<method name="get_buffer">
<return type="PackedVector2Array" />
<param index="0" name="frames" type="int" />
<description>
Gets the next [param frames] audio samples from the internal ring buffer.
Returns a [PackedVector2Array] containing exactly [param frames] audio samples if available, or an empty [PackedVector2Array] if insufficient data was available.
The samples are signed floating-point PCM between [code]-1[/code] and [code]1[/code]. You will have to scale them if you want to use them as 8 or 16-bit integer samples. ([code]v = 0x7fff * samples[0].x[/code])
</description>
</method>
<method name="get_buffer_length_frames" qualifiers="const">
<return type="int" />
<description>
Returns the total size of the internal ring buffer in frames.
</description>
</method>
<method name="get_discarded_frames" qualifiers="const">
<return type="int" />
<description>
Returns the number of audio frames discarded from the audio bus due to full buffer.
</description>
</method>
<method name="get_frames_available" qualifiers="const">
<return type="int" />
<description>
Returns the number of frames available to read using [method get_buffer].
</description>
</method>
<method name="get_pushed_frames" qualifiers="const">
<return type="int" />
<description>
Returns the number of audio frames inserted from the audio bus.
</description>
</method>
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length">
Length of the internal ring buffer, in seconds. Initialized to buffer length of parent [AudioEffectCapture]. Setting the buffer length will have no effect if already initialized.
</member>
</members>
</class>
2 changes: 1 addition & 1 deletion doc/classes/AudioEffectInstance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Manipulates the audio it receives for a given effect.
</brief_description>
<description>
An audio effect instance manipulates the audio it receives for a given effect. This instance is automatically created by an [AudioEffect] when it is added to a bus, and should usually not be created directly. If necessary, it can be fetched at run-time with [method AudioServer.get_bus_effect_instance].
An audio effect instance manipulates the audio it receives for a given effect. This instance is automatically created by an [AudioEffect] when it is added to a bus, once for each channel on the bus, and should usually not be created directly. If necessary, it can be fetched at run-time with [method AudioServer.get_bus_effect_instance].
</description>
<tutorials>
<link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link>
Expand Down
13 changes: 8 additions & 5 deletions doc/classes/AudioEffectRecord.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
Audio effect used for recording the sound from an audio bus.
</brief_description>
<description>
Allows the user to record the sound from an audio bus into an [AudioStreamWAV]. When used on the "Master" audio bus, this includes all audio output by Godot.
Unlike [AudioEffectCapture], this effect encodes the recording with the given format (8-bit, 16-bit, or compressed) instead of giving access to the raw audio samples.
Allows the user to record the sound from an audio bus into an [AudioStreamWAV]. When used on the "Master" audio bus, this includes all audio output by Godot. Recording is done per channel by [AudioEffectRecordInstance]. The parent AudioEffectRecord allows accessing data per-channel via the channel parameter on the get methods, or it can be accessed directly from [AudioEffectRecordInstance] using [method AudioServer.get_bus_effect_instance].
Unlike [AudioEffectCapture] or [AudioEffectCaptureInstance], this effect encodes the recording with the given format (8-bit, 16-bit, or compressed) instead of giving access to the raw audio samples.
Can be used (with an [AudioStreamMicrophone]) to record from a microphone.
[b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings.
</description>
Expand All @@ -16,21 +16,24 @@
<methods>
<method name="get_recording" qualifiers="const">
<return type="AudioStreamWAV" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns the recorded sample.
Returns the recorded sample for the given [param channel]'s [AudioEffectRecordInstance].
</description>
</method>
<method name="is_recording_active" qualifiers="const">
<return type="bool" />
<param index="0" name="channel" type="int" default="0" />
<description>
Returns whether the recording is active or not.
Returns whether the recording is active or not on the given [param channel]'s [AudioEffectRecordInstance].
</description>
</method>
<method name="set_recording_active">
<return type="void" />
<param index="0" name="record" type="bool" />
<param index="1" name="channel" type="int" default="0" />
<description>
If [code]true[/code], the sound will be recorded. Note that restarting the recording will remove the previously recorded sample.
If [code]true[/code], the sound will be recorded on the given [param channel]'s [AudioEffectRecordInstance]. Note that restarting the recording will remove the previously recorded sample.
</description>
</method>
</methods>
Expand Down
43 changes: 43 additions & 0 deletions doc/classes/AudioEffectRecordInstance.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectRecordInstance" inherits="AudioEffectInstance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Audio effect instance used for recording the sound from an audio bus from a particular audio channel.
</brief_description>
<description>
Allows the user to record the sound from an individual channel of an audio bus into an [AudioStreamWAV]. When used on the "Master" audio bus, this includes all audio output for that channel by Godot.
Unlike [AudioEffectCapture] or [AudioEffectCaptureInstance], this effect encodes the recording with the given format (8-bit, 16-bit, or compressed) instead of giving access to the raw audio samples.
Can be used (with an [AudioStreamMicrophone]) to record from a microphone.
An instance of this class can be obtained with [method AudioServer.get_bus_effect_instance].
[b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings.
</description>
<tutorials>
<link title="Recording with microphone">$DOCS_URL/tutorials/audio/recording_with_microphone.html</link>
<link title="Audio Microphone Record Demo">https://godotengine.org/asset-library/asset/2760</link>
</tutorials>
<methods>
<method name="get_recording" qualifiers="const">
<return type="AudioStreamWAV" />
<description>
Returns the recorded sample.
</description>
</method>
<method name="is_recording_active" qualifiers="const">
<return type="bool" />
<description>
Returns whether the recording is active or not.
</description>
</method>
<method name="set_recording_active">
<return type="void" />
<param index="0" name="record" type="bool" />
<description>
If [code]true[/code], the sound will be recorded. Note that restarting the recording will remove the previously recorded sample.
</description>
</method>
</methods>
<members>
<member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format">
Specifies the format in which the sample will be recorded. Initialized to format of parent [AudioEffectRecord]. See [enum AudioStreamWAV.Format] for available formats.
</member>
</members>
</class>
14 changes: 14 additions & 0 deletions misc/extension_api_validation/4.5-stable/GH-92532.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
GH-92532
--------
Validate extension JSON: Error: Field 'classes/AudioEffectCapture/methods/can_get_buffer/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/AudioEffectCapture/methods/get_buffer/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/AudioEffectRecord/methods/set_recording_active/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectCapture/methods/clear_buffer': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectCapture/methods/get_buffer_length_frames': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectCapture/methods/get_discarded_frames': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectCapture/methods/get_frames_available': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectCapture/methods/get_pushed_frames': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectRecord/methods/get_recording': arguments
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/AudioEffectRecord/methods/is_recording_active': arguments

Optional argument added. Compatibility methods registered.
7 changes: 6 additions & 1 deletion servers/audio/audio_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ bool AudioEffectInstance::process_silence() const {
GDVIRTUAL_CALL(_process_silence, ret);
return ret;
}

void AudioEffectInstance::_bind_methods() {
GDVIRTUAL_BIND(_process, "src_buffer", "dst_buffer", "frame_count");
GDVIRTUAL_BIND(_process_silence);
Expand All @@ -51,8 +50,14 @@ Ref<AudioEffectInstance> AudioEffect::instantiate() {
GDVIRTUAL_CALL(_instantiate, ret);
return ret;
}

void AudioEffect::finalize() {
GDVIRTUAL_CALL(_finalize);
}

void AudioEffect::_bind_methods() {
GDVIRTUAL_BIND(_instantiate);
GDVIRTUAL_BIND(_finalize);
}

AudioEffect::AudioEffect() {
Expand Down
8 changes: 8 additions & 0 deletions servers/audio/audio_effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,27 @@ class AudioEffectInstance : public RefCounted {
GDVIRTUAL0RC(bool, _process_silence)
static void _bind_methods();

int current_channel;

public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
virtual bool process_silence() const;

void set_current_channel(int p_channel) { current_channel = p_channel; }
int get_current_channel() { return current_channel; }
};

class AudioEffect : public Resource {
GDCLASS(AudioEffect, Resource);

protected:
GDVIRTUAL0R_REQUIRED(Ref<AudioEffectInstance>, _instantiate)
GDVIRTUAL0(_finalize)
static void _bind_methods();

public:
virtual Ref<AudioEffectInstance> instantiate();
virtual void finalize();

AudioEffect();
};
7 changes: 4 additions & 3 deletions servers/audio/audio_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,12 +1097,13 @@ 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;
}
}
for (int j = 0; j < buses[p_bus]->effects.size(); j++) {
buses.write[p_bus]->effects.write[j].effect->finalize();
}
}

void AudioServer::add_bus_effect(int p_bus, const Ref<AudioEffect> &p_effect, int p_at_pos) {
Expand Down
Loading
X Tutup