Skip to content
Closed
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
Binary file added audio/mic_input/Intro.ogg
Binary file not shown.
19 changes: 19 additions & 0 deletions audio/mic_input/Intro.ogg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[remap]

importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://c2re52petqrvx"
path="res://.godot/imported/Intro.ogg-dfe75727d0e47692e220adf97ddb7ad9.oggvorbisstr"

[deps]

source_file="res://Intro.ogg"
dest_files=["res://.godot/imported/Intro.ogg-dfe75727d0e47692e220adf97ddb7ad9.oggvorbisstr"]

[params]

loop=true
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
136 changes: 136 additions & 0 deletions audio/mic_input/MicRecord.gd
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All files need to use snake_case file names.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
extends Control

var wav_recording: AudioStreamWAV
var input_mix_rate : int = 44100
var audio_chunk_size_ms : int = 20
var audio_sample_size : int = 882

var total_samples : int = 0
var sample_duration : float = 0.0
var recording_buffer : Variant = null

var audio_sample_image : Image
var audio_sample_texture : ImageTexture
var generator_timestamp : float = 0.0
var generator_freq : float = 0.0
Comment on lines +3 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the GDScript style guide.

Suggested change
var wav_recording: AudioStreamWAV
var input_mix_rate : int = 44100
var audio_chunk_size_ms : int = 20
var audio_sample_size : int = 882
var total_samples : int = 0
var sample_duration : float = 0.0
var recording_buffer : Variant = null
var audio_sample_image : Image
var audio_sample_texture : ImageTexture
var generator_timestamp : float = 0.0
var generator_freq : float = 0.0
var wav_recording: AudioStreamWAV
var input_mix_rate: int = 44100
var audio_chunk_size_ms: int = 20
var audio_sample_size: int = 882
var total_samples: int = 0
var sample_duration: float = 0.0
var recording_buffer: Variant = null
var audio_sample_image: Image
var audio_sample_texture: ImageTexture
var generator_timestamp: float = 0.0
var generator_freq: float = 0.0


func _ready() -> void:
if not Input.has_method("start_microphone"):
$Status.text = "Error: requires PR#105244 to work"
input_mix_rate = int(AudioServer.get_input_mix_rate())
print("Input mix rate: ", input_mix_rate)
print("Output mix rate: ", AudioServer.get_mix_rate())
print("Project mix rate: ", ProjectSettings.get("audio/driver/mix_rate"))
$InputMixRate.text = "Mix rate: %d" % input_mix_rate
audio_sample_size = int(audio_chunk_size_ms*input_mix_rate/1000.0)
var blank_image : PackedVector2Array = PackedVector2Array()
blank_image.resize(audio_sample_size)
audio_sample_image = Image.create_from_data(audio_sample_size, 1, false, Image.FORMAT_RGF, blank_image.to_byte_array())
audio_sample_texture = ImageTexture.create_from_image(audio_sample_image)
$MicTexture.material.set_shader_parameter("audiosample", audio_sample_texture)
Comment on lines +20 to +30
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
input_mix_rate = int(AudioServer.get_input_mix_rate())
print("Input mix rate: ", input_mix_rate)
print("Output mix rate: ", AudioServer.get_mix_rate())
print("Project mix rate: ", ProjectSettings.get("audio/driver/mix_rate"))
$InputMixRate.text = "Mix rate: %d" % input_mix_rate
audio_sample_size = int(audio_chunk_size_ms*input_mix_rate/1000.0)
var blank_image : PackedVector2Array = PackedVector2Array()
blank_image.resize(audio_sample_size)
audio_sample_image = Image.create_from_data(audio_sample_size, 1, false, Image.FORMAT_RGF, blank_image.to_byte_array())
audio_sample_texture = ImageTexture.create_from_image(audio_sample_image)
$MicTexture.material.set_shader_parameter("audiosample", audio_sample_texture)
input_mix_rate = int(AudioServer.get_input_mix_rate())
print("Input mix rate: ", input_mix_rate)
print("Output mix rate: ", AudioServer.get_mix_rate())
print("Project mix rate: ", ProjectSettings.get("audio/driver/mix_rate"))
$InputMixRate.text = "Mix rate: %d" % input_mix_rate
audio_sample_size = int(audio_chunk_size_ms*input_mix_rate/1000.0)
var blank_image : PackedVector2Array = PackedVector2Array()
blank_image.resize(audio_sample_size)
audio_sample_image = Image.create_from_data(audio_sample_size, 1, false, Image.FORMAT_RGF, blank_image.to_byte_array())
audio_sample_texture = ImageTexture.create_from_image(audio_sample_image)
$MicTexture.material.set_shader_parameter("audiosample", audio_sample_texture)

Or similar, too dense as it stands


func _on_microphone_on_toggled(toggled_on : bool) -> void:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func _on_microphone_on_toggled(toggled_on : bool) -> void:
func _on_microphone_on_toggled(toggled_on: bool) -> void:

Leave two empty lines between methods, also spacing with type hints, for all

if toggled_on:
Input.start_microphone()
total_samples = 0
sample_duration = 0.0
else:
Input.stop_microphone()

func _on_mic_to_generator_toggled(toggled_on : bool) -> void:
if toggled_on:
$AudioGenerator.stream.mix_rate = input_mix_rate
$AudioGenerator.playing = toggled_on

func _process(delta : float) -> void:
sample_duration += delta
while Input.get_microphone_frames_available() >= audio_sample_size:
var audio_samples : PackedVector2Array = Input.get_microphone_buffer(audio_sample_size)
if audio_samples:
audio_sample_image.set_data(audio_sample_size, 1, false, Image.FORMAT_RGF, audio_samples.to_byte_array())
audio_sample_texture.update(audio_sample_image)
total_samples += 1
$SampleCount.text = "%.0f samples/sec" % (total_samples*audio_sample_size/sample_duration)
if recording_buffer != null:
recording_buffer.append(audio_samples)
if $MicToGenerator.button_pressed:
$AudioGenerator.get_stream_playback().push_buffer(audio_samples)
if generator_freq != 0.0:
Comment on lines +50 to +58
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
audio_sample_image.set_data(audio_sample_size, 1, false, Image.FORMAT_RGF, audio_samples.to_byte_array())
audio_sample_texture.update(audio_sample_image)
total_samples += 1
$SampleCount.text = "%.0f samples/sec" % (total_samples*audio_sample_size/sample_duration)
if recording_buffer != null:
recording_buffer.append(audio_samples)
if $MicToGenerator.button_pressed:
$AudioGenerator.get_stream_playback().push_buffer(audio_samples)
if generator_freq != 0.0:
audio_sample_image.set_data(audio_sample_size, 1, false, Image.FORMAT_RGF, audio_samples.to_byte_array())
audio_sample_texture.update(audio_sample_image)
total_samples += 1
$SampleCount.text = "%.0f samples/sec" % (total_samples*audio_sample_size/sample_duration)
if recording_buffer != null:
recording_buffer.append(audio_samples)
if $MicToGenerator.button_pressed:
$AudioGenerator.get_stream_playback().push_buffer(audio_samples)
if generator_freq != 0.0:

var gplayback : AudioStreamGeneratorPlayback = $AudioGenerator.get_stream_playback()
var gdt : float = 1.0/$AudioGenerator.stream.mix_rate
for i in range(gplayback.get_frames_available()):
var a : float = 0.5*sin(generator_timestamp*generator_freq*TAU)
gplayback.push_frame(Vector2(a, a))
generator_timestamp += gdt

func _on_record_button_toggled(toggled_on : bool) -> void:
total_samples = 0
sample_duration = 0.0
if toggled_on:
$PlayButton.disabled = true
$SaveButton.disabled = true
recording_buffer = [ ]
$RecordButton.text = "Stop"
$Status.text = "Status: Recording..."

else:
$PlayButton.disabled = false
$SaveButton.disabled = false
var recording_data : PackedByteArray = PackedByteArray()
var data_size : int = 4*audio_sample_size*len(recording_buffer)
recording_data.resize(44 + data_size)
recording_data.encode_u32(0, 0x46464952) # RIFF
recording_data.encode_u32(4, len(recording_data) - 8)
recording_data.encode_u32(8, 0x45564157) # WAVE
recording_data.encode_u32(12, 0x20746D66) # 'fmt '
recording_data.encode_u32(16, 16)
recording_data.encode_u16(20, 1)
recording_data.encode_u16(22, 2)
recording_data.encode_u32(24, input_mix_rate)
recording_data.encode_u32(28, input_mix_rate*4) # *16*2/8
recording_data.encode_u16(32, 4) # 16*2/8
recording_data.encode_u16(34, 16)
recording_data.encode_u32(36, 0x61746164) # 'data'
recording_data.encode_u32(40, data_size)
for i in range(len(recording_buffer)):
for j in range(audio_sample_size):
var k : int = 44 + 4*(i*audio_sample_size + j)
recording_data.encode_s16(k, clampi(recording_buffer[i][j].x*32768, -32768, 32767))
recording_data.encode_s16(k+2, clampi(recording_buffer[i][j].y*32768, -32768, 32767))
wav_recording = AudioStreamWAV.load_from_buffer(recording_data)
Comment on lines +78 to +100
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$SaveButton.disabled = false
var recording_data : PackedByteArray = PackedByteArray()
var data_size : int = 4*audio_sample_size*len(recording_buffer)
recording_data.resize(44 + data_size)
recording_data.encode_u32(0, 0x46464952) # RIFF
recording_data.encode_u32(4, len(recording_data) - 8)
recording_data.encode_u32(8, 0x45564157) # WAVE
recording_data.encode_u32(12, 0x20746D66) # 'fmt '
recording_data.encode_u32(16, 16)
recording_data.encode_u16(20, 1)
recording_data.encode_u16(22, 2)
recording_data.encode_u32(24, input_mix_rate)
recording_data.encode_u32(28, input_mix_rate*4) # *16*2/8
recording_data.encode_u16(32, 4) # 16*2/8
recording_data.encode_u16(34, 16)
recording_data.encode_u32(36, 0x61746164) # 'data'
recording_data.encode_u32(40, data_size)
for i in range(len(recording_buffer)):
for j in range(audio_sample_size):
var k : int = 44 + 4*(i*audio_sample_size + j)
recording_data.encode_s16(k, clampi(recording_buffer[i][j].x*32768, -32768, 32767))
recording_data.encode_s16(k+2, clampi(recording_buffer[i][j].y*32768, -32768, 32767))
wav_recording = AudioStreamWAV.load_from_buffer(recording_data)
$SaveButton.disabled = false
var recording_data : PackedByteArray = PackedByteArray()
var data_size : int = 4*audio_sample_size*len(recording_buffer)
recording_data.resize(44 + data_size)
recording_data.encode_u32(0, 0x46464952) # RIFF
recording_data.encode_u32(4, len(recording_data) - 8)
recording_data.encode_u32(8, 0x45564157) # WAVE
recording_data.encode_u32(12, 0x20746D66) # 'fmt '
recording_data.encode_u32(16, 16)
recording_data.encode_u16(20, 1)
recording_data.encode_u16(22, 2)
recording_data.encode_u32(24, input_mix_rate)
recording_data.encode_u32(28, input_mix_rate*4) # *16*2/8
recording_data.encode_u16(32, 4) # 16*2/8
recording_data.encode_u16(34, 16)
recording_data.encode_u32(36, 0x61746164) # 'data'
recording_data.encode_u32(40, data_size)
for i in range(len(recording_buffer)):
for j in range(audio_sample_size):
var k : int = 44 + 4*(i*audio_sample_size + j)
recording_data.encode_s16(k, clampi(recording_buffer[i][j].x*32768, -32768, 32767))
recording_data.encode_s16(k+2, clampi(recording_buffer[i][j].y*32768, -32768, 32767))
wav_recording = AudioStreamWAV.load_from_buffer(recording_data)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot see what's edited in this block. They look exactly the same!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra spacing to reduce clutter


$RecordButton.text = "Record"
$Status.text = ""
recording_buffer = null

func _on_play_button_pressed() -> void:
print_rich("\n[b]Playing recording:[/b] %s" % wav_recording)
$AudioWav.stream = wav_recording
$AudioWav.play()

func _on_play_music_toggled(toggled_on : bool) -> void:
if toggled_on:
$AudioMusic.play()
$PlayMusic.text = "Stop Music"
else:
$AudioMusic.stop()
$PlayMusic.text = "Play Music"

func _on_save_button_pressed() -> void:
var save_path: String = $SaveButton/Filename.text
wav_recording.save_to_wav(save_path)
$Status.text = "Status: Saved WAV file to: %s\n(%s)" % [save_path, ProjectSettings.globalize_path(save_path)]

func _on_open_user_folder_button_pressed() -> void:
OS.shell_open(ProjectSettings.globalize_path("user://"))

# 400Hz frequency can be used (from another device) to probe a stereo microphone
# response due to where there should be 8 wavelengths in the space of 20ms (2.5ms per wave).
# The wavelength is then 343/400=0.8575m long.
func _on_option_tone_item_selected(index : int) -> void:
if index != 0:
$AudioGenerator.playing = true
if not $MicToGenerator.button_pressed and not $PlayMusic.button_pressed:
generator_freq = int($OptionTone.get_item_text(index))
else:
generator_freq = 0.0
1 change: 1 addition & 0 deletions audio/mic_input/MicRecord.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://dbbfvbf6ronrp
24 changes: 24 additions & 0 deletions audio/mic_input/MicRecord.gdshader
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
shader_type canvas_item;
render_mode blend_mix;

uniform sampler2D audiosample : repeat_enable;
const float cfac = 4.0;
const float mfac = 2.0;
const float mdisp = 0.166667;
const float mthick = 0.05;
const float mtiltfac = 0.125;

void fragment() {
vec4 b = texture(audiosample, UV + vec2(-(UV.y-0.5)*mtiltfac, 0.0));
vec4 c = texture(audiosample, UV + vec2((UV.y-0.5)*mtiltfac, 0.0));
float s = (b.r + c.g)/2.0;
COLOR = vec4(0.1+max(s,0.0)*cfac, 0.1, 0.1+max(-s,0.0)*cfac, 1.0);

vec4 a = texture(audiosample, UV);
float dr = abs(UV.y*2.0 - 1.0 - (a.r + mdisp)*mfac);
float dg = abs(UV.y*2.0 - 1.0 - (a.g - mdisp)*mfac);
if (dg < mthick)
COLOR = vec4(1.0,1.0,0.9,1.0);
else if (dr < mthick)
COLOR = vec4(0.8,0.8,0.9,1.0);
Comment on lines +12 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vec4 b = texture(audiosample, UV + vec2(-(UV.y-0.5)*mtiltfac, 0.0));
vec4 c = texture(audiosample, UV + vec2((UV.y-0.5)*mtiltfac, 0.0));
float s = (b.r + c.g)/2.0;
COLOR = vec4(0.1+max(s,0.0)*cfac, 0.1, 0.1+max(-s,0.0)*cfac, 1.0);
vec4 a = texture(audiosample, UV);
float dr = abs(UV.y*2.0 - 1.0 - (a.r + mdisp)*mfac);
float dg = abs(UV.y*2.0 - 1.0 - (a.g - mdisp)*mfac);
if (dg < mthick)
COLOR = vec4(1.0,1.0,0.9,1.0);
else if (dr < mthick)
COLOR = vec4(0.8,0.8,0.9,1.0);
if (dg < mthick)
COLOR = vec4(1.0,1.0,0.9,1.0);
} else if (dr < mthick) {
COLOR = vec4(0.8,0.8,0.9,1.0);
}
Suggested change
vec4 b = texture(audiosample, UV + vec2(-(UV.y-0.5)*mtiltfac, 0.0));
vec4 c = texture(audiosample, UV + vec2((UV.y-0.5)*mtiltfac, 0.0));
float s = (b.r + c.g)/2.0;
COLOR = vec4(0.1+max(s,0.0)*cfac, 0.1, 0.1+max(-s,0.0)*cfac, 1.0);
vec4 a = texture(audiosample, UV);
float dr = abs(UV.y*2.0 - 1.0 - (a.r + mdisp)*mfac);
float dg = abs(UV.y*2.0 - 1.0 - (a.g - mdisp)*mfac);
if (dg < mthick)
COLOR = vec4(1.0,1.0,0.9,1.0);
else if (dr < mthick)
COLOR = vec4(0.8,0.8,0.9,1.0);
vec4 b = texture(audiosample, UV + vec2(-(UV.y-0.5)*mtiltfac, 0.0));
vec4 c = texture(audiosample, UV + vec2((UV.y-0.5)*mtiltfac, 0.0));
float s = (b.r + c.g)/2.0;
COLOR = vec4(0.1+max(s,0.0)*cfac, 0.1, 0.1+max(-s,0.0)*cfac, 1.0);
vec4 a = texture(audiosample, UV);
float dr = abs(UV.y*2.0 - 1.0 - (a.r + mdisp)*mfac);
float dg = abs(UV.y*2.0 - 1.0 - (a.g - mdisp)*mfac);
if (dg < mthick) {
COLOR = vec4(1.0,1.0,0.9,1.0);
} else if (dr < mthick) {
COLOR = vec4(0.8,0.8,0.9,1.0);
}

}
1 change: 1 addition & 0 deletions audio/mic_input/MicRecord.gdshader.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://cl4x5tyii4r6q
171 changes: 171 additions & 0 deletions audio/mic_input/MicRecord.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
[gd_scene load_steps=6 format=3 uid="uid://dvjlkpjvjxn0h"]

[ext_resource type="Script" uid="uid://dbbfvbf6ronrp" path="res://MicRecord.gd" id="1"]
[ext_resource type="AudioStream" uid="uid://c2re52petqrvx" path="res://Intro.ogg" id="2"]
[ext_resource type="Shader" uid="uid://cl4x5tyii4r6q" path="res://MicRecord.gdshader" id="3_vkk4n"]

[sub_resource type="AudioStreamGenerator" id="AudioStreamGenerator_tfvr1"]

[sub_resource type="ShaderMaterial" id="ShaderMaterial_m4htd"]
shader = ExtResource("3_vkk4n")

[node name="MicRecord" type="Control"]
layout_mode = 3
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -320.0
offset_top = -240.0
offset_right = 254.0
offset_bottom = 210.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1")

[node name="AudioWav" type="AudioStreamPlayer" parent="."]
autoplay = true

[node name="AudioMusic" type="AudioStreamPlayer" parent="."]
stream = ExtResource("2")
volume_db = -6.0

[node name="AudioGenerator" type="AudioStreamPlayer" parent="."]
stream = SubResource("AudioStreamGenerator_tfvr1")
bus = &"Generate"

[node name="Status" type="Label" parent="."]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 26.0
grow_horizontal = 2
text = "Status: "
horizontal_alignment = 1

[node name="MicrophoneOn" type="CheckBox" parent="."]
layout_mode = 0
offset_left = 5.0
offset_top = 50.0
offset_right = 154.0
offset_bottom = 81.0
tooltip_text = "Nothing works until you
turn the microphone on."
text = "Microphone On
"

[node name="MicToGenerator" type="CheckBox" parent="."]
layout_mode = 0
offset_left = 156.0
offset_top = 50.0
offset_right = 315.0
offset_bottom = 81.0
tooltip_text = "Warning: this will cause feedback
unless you use headphones"
text = "Mic to Output
"

[node name="InputMixRate" type="Label" parent="."]
layout_mode = 0
offset_left = 323.0
offset_top = 56.0
offset_right = 392.0
offset_bottom = 79.0
text = "Mix rate:"

[node name="SampleCount" type="Label" parent="."]
layout_mode = 0
offset_left = 460.0
offset_top = 56.0
offset_right = 542.0
offset_bottom = 79.0
text = "N-samples"

[node name="RecordButton" type="Button" parent="."]
layout_mode = 0
offset_left = 20.0
offset_top = 105.0
offset_right = 150.0
offset_bottom = 145.0
toggle_mode = true
text = "Record"

[node name="PlayButton" type="Button" parent="."]
layout_mode = 0
offset_left = 167.0
offset_top = 105.0
offset_right = 297.0
offset_bottom = 145.0
disabled = true
text = "Play"

[node name="PlayMusic" type="Button" parent="."]
layout_mode = 0
offset_left = 323.0
offset_top = 105.0
offset_right = 453.0
offset_bottom = 145.0
toggle_mode = true
text = "Play Music"

[node name="MicTexture" type="ColorRect" parent="."]
material = SubResource("ShaderMaterial_m4htd")
layout_mode = 0
offset_left = 20.0
offset_top = 161.0
offset_right = 548.0
offset_bottom = 250.0

[node name="SaveButton" type="Button" parent="."]
layout_mode = 0
offset_left = 26.0
offset_top = 295.0
offset_right = 156.0
offset_bottom = 335.0
disabled = true
text = "Save WAV To:"

[node name="Filename" type="LineEdit" parent="SaveButton"]
layout_mode = 0
offset_left = 150.0
offset_right = 477.0
offset_bottom = 40.0
text = "user://record.wav"
caret_blink = true

[node name="OpenUserFolderButton" type="Button" parent="."]
layout_mode = 1
offset_left = 28.0
offset_top = 349.0
offset_right = 191.0
offset_bottom = 389.0
text = "Open User Folder"

[node name="OptionTone" type="OptionButton" parent="."]
layout_mode = 0
offset_left = 474.0
offset_top = 109.0
offset_right = 568.0
offset_bottom = 140.0
selected = 0
item_count = 5
popup/item_0/text = "No tone"
popup/item_0/id = 0
popup/item_1/text = "200Hz"
popup/item_1/id = 1
popup/item_2/text = "400Hz"
popup/item_2/id = 2
popup/item_3/text = "1000Hz"
popup/item_3/id = 3
popup/item_4/text = "2000Hz"
popup/item_4/id = 4

[connection signal="toggled" from="MicrophoneOn" to="." method="_on_microphone_on_toggled"]
[connection signal="toggled" from="MicToGenerator" to="." method="_on_mic_to_generator_toggled"]
[connection signal="toggled" from="RecordButton" to="." method="_on_record_button_toggled"]
[connection signal="pressed" from="PlayButton" to="." method="_on_play_button_pressed"]
[connection signal="toggled" from="PlayMusic" to="." method="_on_play_music_toggled"]
[connection signal="pressed" from="SaveButton" to="." method="_on_save_button_pressed"]
[connection signal="pressed" from="OpenUserFolderButton" to="." method="_on_open_user_folder_button_pressed"]
[connection signal="item_selected" from="OptionTone" to="." method="_on_option_tone_item_selected"]
19 changes: 19 additions & 0 deletions audio/mic_input/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Audio Mic Input

This example shows how to read microphone audio input data
using the `PackedVector2Array Input.get_microphone_buffer(frames: int)`
function.

The data can be copied to an `AudioStreamGenerator`, saved to a WAV file, or
used as a `FORMAT_RGF` image by a GPU shader.

A sine wave tone generator is included that can be deployed on a second device
and used to probe the positional effects on a stereo microphone.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
and used to probe the positional effects on a stereo microphone.
and be used to probe the positional effects on a stereo microphone.


Language: GDScript

Renderer: Compatibility

## Screenshots

![image](https://github.com/user-attachments/assets/d85360dd-a0aa-4694-aad0-d570fd2a6a15)
14 changes: 14 additions & 0 deletions audio/mic_input/default_bus_layout.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://tuxl6tvrr2dv"]

[sub_resource type="AudioEffectReverb" id="AudioEffectReverb_j3pel"]
resource_name = "Reverb"

[resource]
bus/1/name = &"Generate"
bus/1/solo = false
bus/1/mute = false
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/1/effect/0/effect = SubResource("AudioEffectReverb_j3pel")
bus/1/effect/0/enabled = false
Binary file added audio/mic_input/icon.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading