From b103b84ecd84b688b9bce2e6a8adb8314b166d81 Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Wed, 23 Oct 2024 18:32:32 +0100 Subject: [PATCH 1/6] more print statementws --- example/radiomqtt/member.gd | 4 ++-- example/radiomqtt/member.tscn | 6 +++++- example/radiomqtt/radiomqtt.gd | 5 ++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/example/radiomqtt/member.gd b/example/radiomqtt/member.gd index e12f2f8..009c5dc 100644 --- a/example/radiomqtt/member.gd +++ b/example/radiomqtt/member.gd @@ -35,7 +35,7 @@ func _ready(): audiostream = AudioStreamGenerator.new() $AudioStreamPlayer.stream = audiostream else: - assert (audiostream.resource_local_to_scene) + assert (audiostream.resource_local_to_scene, "AudioStreamGenerator must be local_to_scene") $AudioStreamPlayer.play() if audiostream.is_class("AudioStreamOpusChunked"): @@ -44,7 +44,7 @@ func _ready(): #audiostreamopyschunkedplayback.begin_resample() elif audiostream.is_class("AudioStreamGenerator"): if ClassDB.can_instantiate("AudioStreamOpusChunked"): - audiostreamopuschunked = ClassDB.instantiate("AudioStreamOpusChunked").new() + audiostreamopuschunked = ClassDB.instantiate("AudioStreamOpusChunked") audiostreamgeneratorplayback = $AudioStreamPlayer.get_stream_playback() else: printerr("Incorrect AudioStream type ", audiostream) diff --git a/example/radiomqtt/member.tscn b/example/radiomqtt/member.tscn index 8833c9e..305f313 100644 --- a/example/radiomqtt/member.tscn +++ b/example/radiomqtt/member.tscn @@ -1,8 +1,11 @@ -[gd_scene load_steps=5 format=3 uid="uid://c1ibcb1toyerh"] +[gd_scene load_steps=6 format=3 uid="uid://c1ibcb1toyerh"] [ext_resource type="Script" path="res://radiomqtt/member.gd" id="1_o3hks"] [ext_resource type="Texture2D" uid="uid://cvyjsyigutxbh" path="res://icon.png" id="2_atirx"] +[sub_resource type="AudioStreamGenerator" id="AudioStreamGenerator_t5boe"] +resource_local_to_scene = true + [sub_resource type="Shader" id="Shader_022wp"] code = "// NOTE: Shader automatically converted from Godot Engine 4.3.beta's CanvasItemMaterial. @@ -35,6 +38,7 @@ color = Color(0.423529, 0, 0.423529, 1) script = ExtResource("1_o3hks") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] +stream = SubResource("AudioStreamGenerator_t5boe") bus = &"SpeechBus" [node name="Label" type="Label" parent="."] diff --git a/example/radiomqtt/radiomqtt.gd b/example/radiomqtt/radiomqtt.gd index 17aa27f..0b14b04 100644 --- a/example/radiomqtt/radiomqtt.gd +++ b/example/radiomqtt/radiomqtt.gd @@ -392,13 +392,13 @@ func _on_sav_options_item_selected(index): pass # Replace with function body. if index == 1: var f = FileAccess.open(saveplaybackfile, FileAccess.WRITE) - print("Saving to file", f.get_path_absolute()) + prints("Saving to file:", f.get_path_absolute()) f.store_var({"audiosamplerate":audiosamplerate, "recordedsamples":recordedsamples}) f.close() elif index == 2: var f = FileAccess.open(saveplaybackfile, FileAccess.READ) - print("Loading from file", f.get_path_absolute()) + prints("Loading from file:", f.get_path_absolute()) var dat = f.get_var() if audiosamplerate != dat["audiosamplerate"]: prints(" sample rates disagree!!", dat["audiosamplerate"], audiosamplerate) @@ -407,7 +407,6 @@ func _on_sav_options_item_selected(index): $HBoxPlaycount/VBoxExpt/SavOptions.select(0) - func _on_frame_duration_item_selected(_index): updatesamplerates() From 8204237b01c4ac0e36c9cb52ebc8bfd765082c4a Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Wed, 23 Oct 2024 19:25:23 +0100 Subject: [PATCH 2/6] we have set a mix_rate onto the opus stream --- example/radiomqtt/member.gd | 1 + example/radiomqtt/member.tscn | 4 ++-- example/radiomqtt/radiomqtt.gd | 2 ++ src/audio_effect_opus_chunked.cpp | 7 ++++--- src/audio_stream_opus_chunked.cpp | 14 ++++++++++++-- src/audio_stream_opus_chunked.h | 6 +++++- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/example/radiomqtt/member.gd b/example/radiomqtt/member.gd index 009c5dc..7678620 100644 --- a/example/radiomqtt/member.gd +++ b/example/radiomqtt/member.gd @@ -76,6 +76,7 @@ func processheaderpacket(h): audiostreamopuschunked.audiosamplesize = audiosamplesize audiostreamopuschunked.opussamplerate = opussamplerate audiostreamopuschunked.audiosamplerate = audiosamplerate + audiostreamopuschunked.mix_rate = AudioServer.get_mix_rate() audiobuffersize = audiostreamopuschunked.audiosamplesize*audiostreamopuschunked.audiosamplechunks print("createdecoder ", opussamplerate, " ", opusframesize, " ", audiosamplerate, " ", audiosamplesize) #$AudioStreamPlayer.play() diff --git a/example/radiomqtt/member.tscn b/example/radiomqtt/member.tscn index 305f313..3929631 100644 --- a/example/radiomqtt/member.tscn +++ b/example/radiomqtt/member.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://radiomqtt/member.gd" id="1_o3hks"] [ext_resource type="Texture2D" uid="uid://cvyjsyigutxbh" path="res://icon.png" id="2_atirx"] -[sub_resource type="AudioStreamGenerator" id="AudioStreamGenerator_t5boe"] +[sub_resource type="AudioStreamOpusChunked" id="AudioStreamOpusChunked_l61p2"] resource_local_to_scene = true [sub_resource type="Shader" id="Shader_022wp"] @@ -38,7 +38,7 @@ color = Color(0.423529, 0, 0.423529, 1) script = ExtResource("1_o3hks") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] -stream = SubResource("AudioStreamGenerator_t5boe") +stream = SubResource("AudioStreamOpusChunked_l61p2") bus = &"SpeechBus" [node name="Label" type="Label" parent="."] diff --git a/example/radiomqtt/radiomqtt.gd b/example/radiomqtt/radiomqtt.gd index 0b14b04..ced5977 100644 --- a/example/radiomqtt/radiomqtt.gd +++ b/example/radiomqtt/radiomqtt.gd @@ -38,6 +38,8 @@ var visemes = [ "sil", "PP", "FF", "TH", "DD", "kk", "CH", "SS", "nn", "RR", "aa var possibleusernames = ["Alice", "Beth", "Cath", "Dan", "Earl", "Fred", "George", "Harry", "Ivan", "John", "Kevin", "Larry", "Martin", "Oliver", "Peter", "Quentin", "Robert", "Samuel", "Thomas", "Ulrik", "Victor", "Wayne", "Xavier", "Youngs", "Zephir"] func _ready(): + print("AudioServer.get_mix_rate()=", AudioServer.get_mix_rate()) + print("ProjectSettings.get_setting_with_override(\"audio/driver/mix_rate\")=", ProjectSettings.get_setting_with_override("audio/driver/mix_rate")) $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = AudioServer.get_mix_rate() if $VBoxFrameLength/HBoxOpusFrame/FrameDuration.selected == -1: $VBoxFrameLength/HBoxOpusFrame/FrameDuration.select(3) diff --git a/src/audio_effect_opus_chunked.cpp b/src/audio_effect_opus_chunked.cpp index 23108a7..2266aba 100644 --- a/src/audio_effect_opus_chunked.cpp +++ b/src/audio_effect_opus_chunked.cpp @@ -48,11 +48,12 @@ void AudioEffectOpusChunked::_bind_methods() { ClassDB::bind_method(D_METHOD("get_audiosamplesize"), &AudioEffectOpusChunked::get_audiosamplesize); ClassDB::bind_method(D_METHOD("set_audiosamplechunks", "audiosamplechunks"), &AudioEffectOpusChunked::set_audiosamplechunks); ClassDB::bind_method(D_METHOD("get_audiosamplechunks"), &AudioEffectOpusChunked::get_audiosamplechunks); - ADD_PROPERTY(PropertyInfo(Variant::INT, "opussamplerate", PROPERTY_HINT_RANGE, "8000,48000,4000"), "set_opussamplerate", "get_opussamplerate"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "opussamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_opussamplerate", "get_opussamplerate"); ADD_PROPERTY(PropertyInfo(Variant::INT, "opusframesize", PROPERTY_HINT_RANGE, "20,2880,2"), "set_opusframesize", "get_opusframesize"); ADD_PROPERTY(PropertyInfo(Variant::INT, "opusbitrate", PROPERTY_HINT_RANGE, "3000,24000,1000"), "set_opusbitrate", "get_opusbitrate"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplerate", PROPERTY_HINT_RANGE, "8000,96000,100"), "set_audiosamplerate", "get_audiosamplerate"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_audiosamplerate", "get_audiosamplerate"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplesize", PROPERTY_HINT_RANGE, "10,4000,1"), "set_audiosamplesize", "get_audiosamplesize"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplechunks", PROPERTY_HINT_RANGE, "1,200,1"), "set_audiosamplechunks", "get_audiosamplechunks"); @@ -214,7 +215,7 @@ void AudioEffectOpusChunked::process(const AudioFrame *p_src_frames, AudioFrame drop_chunk(); discardedchunks += 1; if (!Engine::get_singleton()->is_editor_hint()) - if ((discardedchunks < 50) || ((discardedchunks % 1000) == 0)) + if ((discardedchunks < 5) || ((discardedchunks % 1000) == 0)) godot::UtilityFunctions::prints("Discarding chunk", discardedchunks, bufferend, (chunknumber + 1)*audiosamplesize); } } diff --git a/src/audio_stream_opus_chunked.cpp b/src/audio_stream_opus_chunked.cpp index 6d76ce5..e44307d 100644 --- a/src/audio_stream_opus_chunked.cpp +++ b/src/audio_stream_opus_chunked.cpp @@ -46,13 +46,18 @@ void AudioStreamOpusChunked::_bind_methods() { ClassDB::bind_method(D_METHOD("get_audiosamplesize"), &AudioStreamOpusChunked::get_audiosamplesize); ClassDB::bind_method(D_METHOD("set_audiosamplechunks", "audiosamplechunks"), &AudioStreamOpusChunked::set_audiosamplechunks); ClassDB::bind_method(D_METHOD("get_audiosamplechunks"), &AudioStreamOpusChunked::get_audiosamplechunks); - ADD_PROPERTY(PropertyInfo(Variant::INT, "opussamplerate", PROPERTY_HINT_RANGE, "8000,48000,4000"), "set_opussamplerate", "get_opussamplerate"); + ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamOpusChunked::set_mix_rate); + ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamOpusChunked::get_mix_rate); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "opussamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_opussamplerate", "get_opussamplerate"); ADD_PROPERTY(PropertyInfo(Variant::INT, "opusframesize", PROPERTY_HINT_RANGE, "20,2880,2"), "set_opusframesize", "get_opusframesize"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplerate", PROPERTY_HINT_RANGE, "8000,96000,100"), "set_audiosamplerate", "get_audiosamplerate"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_audiosamplerate", "get_audiosamplerate"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplesize", PROPERTY_HINT_RANGE, "10,4000,1"), "set_audiosamplesize", "get_audiosamplesize"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplechunks", PROPERTY_HINT_RANGE, "1,200,1"), "set_audiosamplechunks", "get_audiosamplechunks"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate"); + ClassDB::bind_method(D_METHOD("chunk_space_available"), &AudioStreamOpusChunked::chunk_space_available); ClassDB::bind_method(D_METHOD("queue_length_frames"), &AudioStreamOpusChunked::queue_length_frames); ClassDB::bind_method(D_METHOD("push_audio_chunk", "audiochunk"), &AudioStreamOpusChunked::push_audio_chunk); @@ -276,6 +281,11 @@ int32_t AudioStreamPlaybackOpusChunked::_mix_resampled(AudioFrame *buffer, int32 return frames; } +double AudioStreamPlaybackOpusChunked::_get_stream_sampling_rate() const { + return base->mix_rate; +}; + + void AudioStreamPlaybackOpusChunked::_start(double p_from_pos) { if (mixed == 0.0) { begin_resample(); diff --git a/src/audio_stream_opus_chunked.h b/src/audio_stream_opus_chunked.h index e4a126c..6c3ef70 100644 --- a/src/audio_stream_opus_chunked.h +++ b/src/audio_stream_opus_chunked.h @@ -63,7 +63,7 @@ class AudioStreamPlaybackOpusChunked : public AudioStreamPlaybackResampled { public: virtual int32_t _mix_resampled(AudioFrame *dst_buffer, int32_t frame_count) override; - virtual double _get_stream_sampling_rate() const override { return 44100.0F; }; + virtual double _get_stream_sampling_rate() const override; virtual void _start(double p_from_pos = 0.0) override; virtual void _stop() override; @@ -88,6 +88,8 @@ class AudioStreamOpusChunked : public AudioStream { int audiosamplerate = 44100; int audiosamplesize = 881; PackedVector2Array Daudioresampledbuffer; + + float mix_rate = 44100.0; PackedVector2Array audiosamplebuffer; int audiosamplechunks = 50; @@ -131,6 +133,8 @@ class AudioStreamOpusChunked : public AudioStream { int get_audiosamplesize() { return audiosamplesize; }; void set_audiosamplechunks(int laudiosamplechunks) { resetdecoder(); audiosamplechunks = laudiosamplechunks; }; int get_audiosamplechunks() { return audiosamplechunks; }; + void set_mix_rate(int lmix_rate) { resetdecoder(); mix_rate = lmix_rate; }; + int get_mix_rate() { return mix_rate; }; AudioStreamOpusChunked() {;}; ~AudioStreamOpusChunked() { resetdecoder(); }; From 368d5d8d35d2c0cc056c6db4a90fe2585f424120 Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Wed, 23 Oct 2024 21:48:54 +0100 Subject: [PATCH 3/6] try to add the submodule back in --- godot-cpp | 1 + 1 file changed, 1 insertion(+) create mode 160000 godot-cpp diff --git a/godot-cpp b/godot-cpp new file mode 160000 index 0000000..a4f9d22 --- /dev/null +++ b/godot-cpp @@ -0,0 +1 @@ +Subproject commit a4f9d22ac54e05ca6a41d54a59afd7555cb7d292 From 8713e10a6b9016d0a18a21f667aeae2184ced0ab Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Wed, 23 Oct 2024 21:58:43 +0100 Subject: [PATCH 4/6] return with error when buffer sizes don't match --- src/audio_stream_opus_chunked.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/audio_stream_opus_chunked.cpp b/src/audio_stream_opus_chunked.cpp index e44307d..e1052d9 100644 --- a/src/audio_stream_opus_chunked.cpp +++ b/src/audio_stream_opus_chunked.cpp @@ -166,8 +166,10 @@ void AudioStreamOpusChunked::push_audio_chunk(const PackedVector2Array& audiochu else return; } - if (audiochunk.size() != audiosamplesize) - godot::UtilityFunctions::print("Warning mismatch expected audiochunk size"); + if (audiochunk.size() != audiosamplesize) { + godot::UtilityFunctions::printerr("Error mismatch expected audiochunk size"); + return; + } for (int i = 0; i < audiochunk.size(); i++) audiosamplebuffer.set(buffertail + i, audiochunk[i]); chunknumber += 1; @@ -237,8 +239,10 @@ PackedVector2Array AudioStreamOpusChunked::resample_chunk(const PackedVector2Arr else return audiopreresampledbuffer; } - if (resampledaudio.size() != opusframesize) + if (resampledaudio.size() != opusframesize) { godot::UtilityFunctions::printerr("Error mismatch resampledaudio size"); + return PackedVector2Array(); + } if (audiosamplesize == opusframesize) { return resampledaudio; } From 4d9051fe9c9e436423a942e45c87dc7e15b83b10 Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Thu, 24 Oct 2024 15:01:42 +0100 Subject: [PATCH 5/6] moved around so as to access the mix_rate and take out audiosamplerate from the opus header --- example/default_bus_layout.tres | 7 +- example/radiomqtt/member.gd | 36 ++-- example/radiomqtt/radiomqtt.gd | 77 ++++---- example/radiomqtt/radiomqtt.tscn | 300 ++++++++++++++++++------------- 4 files changed, 244 insertions(+), 176 deletions(-) diff --git a/example/default_bus_layout.tres b/example/default_bus_layout.tres index 1758bfc..6fa6a3e 100644 --- a/example/default_bus_layout.tres +++ b/example/default_bus_layout.tres @@ -1,9 +1,12 @@ -[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://orx4iw038t0c"] +[gd_resource type="AudioBusLayout" load_steps=3 format=3 uid="uid://orx4iw038t0c"] [sub_resource type="AudioEffectPitchShift" id="AudioEffectPitchShift_jq6ag"] resource_name = "PitchShift" fft_size = 1 +[sub_resource type="AudioEffectOpusChunked" id="AudioEffectOpusChunked_4km5k"] +resource_name = "OpusChunked" + [resource] bus/1/name = &"SpeechBus" bus/1/solo = false @@ -19,3 +22,5 @@ bus/2/mute = true bus/2/bypass_fx = false bus/2/volume_db = 0.0 bus/2/send = &"Master" +bus/2/effect/0/effect = SubResource("AudioEffectOpusChunked_4km5k") +bus/2/effect/0/enabled = true diff --git a/example/radiomqtt/member.gd b/example/radiomqtt/member.gd index 7678620..7b3ace4 100644 --- a/example/radiomqtt/member.gd +++ b/example/radiomqtt/member.gd @@ -11,6 +11,7 @@ var opusframesize : int = 0 # 960 var audiosamplesize : int = 0 # 882 var opussamplerate : int = 48000 var audiosamplerate : int = 44100 +var mix_rate : int = 44100 var prefixbyteslength : int = 0 var mqttpacketencodebase64 : bool = false @@ -24,6 +25,8 @@ var audioserveroutputlatency = 0.015 var audiobufferregulationtime = 0.7 var audiobufferregulationpitch = 1.4 +var playbackstarttime = -1.0 + func _ready(): var audiostream = $AudioStreamPlayer.stream if audiostream == null: @@ -54,18 +57,17 @@ func setname(lname): $Label.text = name func processheaderpacket(h): - print(h["audiosamplesize"], " ss ", h["opusframesize"]) - #h["audiosamplesize"] = 400; h["audiosamplerate"] = 40000 - #print("setting audiosamplesize wrong on receive ", h) + var radiomqtt = get_node("../..") + audiosamplerate = radiomqtt.get_node("VBoxPlayback/HBoxStream/SampleRate").value + mix_rate = radiomqtt.get_node("VBoxPlayback/HBoxStream/MixRate").value prefixbyteslength = h["prefixbyteslength"] mqttpacketencodebase64 = (h.get("mqttpacketencoding") == "base64") chunkcount = 0 - if opusframesize != h["opusframesize"] or audiosamplesize != h["audiosamplesize"] or (h.has("uncompressedresampledaudiorate") != (resampledpacketsbuffer != null)): + if opusframesize != h["opusframesize"] or opussamplerate != h["opussamplerate"] or (h.has("uncompressedresampledaudiorate") != (resampledpacketsbuffer != null)): opusframesize = h["opusframesize"] - audiosamplesize = h["audiosamplesize"] opussamplerate = h["opussamplerate"] - audiosamplerate = h["audiosamplerate"] - + var frametimems = opusframesize*1000.0/opussamplerate + audiosamplesize = int(audiosamplerate*frametimems/1000.0) if h.has("uncompressedresampledaudiorate"): resampledpacketsbuffer = [ ] opusframesize = h["uncompressedresampledframesize"] @@ -73,16 +75,19 @@ func processheaderpacket(h): resampledpacketsbuffer = null if audiostreamopuschunked != null: audiostreamopuschunked.opusframesize = opusframesize - audiostreamopuschunked.audiosamplesize = audiosamplesize audiostreamopuschunked.opussamplerate = opussamplerate - audiostreamopuschunked.audiosamplerate = audiosamplerate - audiostreamopuschunked.mix_rate = AudioServer.get_mix_rate() - audiobuffersize = audiostreamopuschunked.audiosamplesize*audiostreamopuschunked.audiosamplechunks - print("createdecoder ", opussamplerate, " ", opusframesize, " ", audiosamplerate, " ", audiosamplesize) - #$AudioStreamPlayer.play() + if audiostreamopuschunked != null and (audiostreamopuschunked.audiosamplesize != audiosamplesize or audiostreamopuschunked.audiosamplerate != audiosamplerate or audiostreamopuschunked.mix_rate != mix_rate): + audiostreamopuschunked.audiosamplesize = audiosamplesize + audiostreamopuschunked.audiosamplerate = audiosamplerate + audiostreamopuschunked.mix_rate = mix_rate + audiobuffersize = audiostreamopuschunked.audiosamplesize*audiostreamopuschunked.audiosamplechunks + print("createdecoder ", opussamplerate, " ", opusframesize, " ", audiosamplerate, " ", audiosamplesize) + #$AudioStreamPlayer.play() setupaudioshader() + + if opusframesize != 0 and audiostreamopuschunked == null: print("Compressed opus stream received that we cannot decompress") audioserveroutputlatency = AudioServer.get_output_latency() @@ -147,6 +152,11 @@ func _process(delta): $Node/ColorRectBackground.visible = true timedelaytohide = 0.1 + if playbackstarttime != -1.0 and audiostreamopuschunked.queue_length_frames() == 0: + var playbackduration = Time.get_ticks_msec() - playbackstarttime + audioserveroutputlatency + playbackstarttime = -1.0 + print("--- Playback time: ", playbackduration/1000.0) + var bufferlengthtime = audioserveroutputlatency + audiostreamopuschunked.queue_length_frames()*1.0/audiosamplerate if audiobufferregulationtime == 3600: pass diff --git a/example/radiomqtt/radiomqtt.gd b/example/radiomqtt/radiomqtt.gd index ced5977..3f23125 100644 --- a/example/radiomqtt/radiomqtt.gd +++ b/example/radiomqtt/radiomqtt.gd @@ -40,20 +40,20 @@ var possibleusernames = ["Alice", "Beth", "Cath", "Dan", "Earl", "Fred", "George func _ready(): print("AudioServer.get_mix_rate()=", AudioServer.get_mix_rate()) print("ProjectSettings.get_setting_with_override(\"audio/driver/mix_rate\")=", ProjectSettings.get_setting_with_override("audio/driver/mix_rate")) - $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = AudioServer.get_mix_rate() + $VBoxPlayback/HBoxStream/MixRate.value = AudioServer.get_mix_rate() + $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = ProjectSettings.get_setting_with_override("audio/driver/mix_rate") + if $VBoxFrameLength/HBoxOpusFrame/FrameDuration.selected == -1: $VBoxFrameLength/HBoxOpusFrame/FrameDuration.select(3) - if $VBoxFrameLength/HBoxOpusFrame/SampleRate.selected == -1: - $VBoxFrameLength/HBoxOpusFrame/SampleRate.select(4) - if $VBoxFrameLength/HBoxAudioFrame/ResampleState.selected == -1: - $VBoxFrameLength/HBoxAudioFrame/ResampleState.select(1) - if $VBoxFrameLength/HBoxBitRate/BitRate.selected == -1: - $VBoxFrameLength/HBoxBitRate/BitRate.select(2) - if $VBoxFrameLength/HBoxBitRate/BitRate.selected == -1: - $VBoxFrameLength/HBoxBitRate/BitRate.select(2) + if $VBoxFrameLength/HBoxOpusBitRate/SampleRate.selected == -1: + $VBoxFrameLength/HBoxOpusBitRate/SampleRate.select(4) + if $VBoxFrameLength/HBoxOpusFrame/ResampleState.selected == -1: + $VBoxFrameLength/HBoxOpusFrame/ResampleState.select(1) + if $VBoxFrameLength/HBoxOpusBitRate/BitRate.selected == -1: + $VBoxFrameLength/HBoxOpusBitRate/BitRate.select(2) if not ClassDB.can_instantiate("AudioEffectOpusChunked"): - $VBoxFrameLength/HBoxAudioFrame/ResampleState.select(0) - $VBoxFrameLength/HBoxAudioFrame/ResampleState.disabled = true + $VBoxFrameLength/HBoxOpusFrame/ResampleState.select(0) + $VBoxFrameLength/HBoxOpusFrame/ResampleState.disabled = true $TwovoipWarning.visible = true assert ($AudioStreamMicrophone.bus == "MicrophoneBus") @@ -113,8 +113,8 @@ func resamplerecordedsamples(orgsamples, newsamplesize): func updatesamplerates(): frametimems = float($VBoxFrameLength/HBoxOpusFrame/FrameDuration.text) - opusbitrate = int($VBoxFrameLength/HBoxBitRate/BitRate.text) - opussamplerate = int($VBoxFrameLength/HBoxOpusFrame/SampleRate.text)*1000 + opusbitrate = int($VBoxFrameLength/HBoxOpusBitRate/BitRate.text) + opussamplerate = int($VBoxFrameLength/HBoxOpusBitRate/SampleRate.text)*1000 audiosamplerate = $VBoxFrameLength/HBoxAudioFrame/SampleRate.value if audioopuschunkedeffect != null: audioopuschunkedeffect.audiosamplerate = audiosamplerate @@ -123,11 +123,11 @@ func updatesamplerates(): opusframesize = int(opussamplerate*frametimems/1000.0) audioopuschunkedeffect.opusframesize = opusframesize $HBoxBigButtons/VBoxPTT/Denoise.disabled = not (audioopuschunkedeffect.denoiser_available() and opussamplerate == 48000) - $VBoxFrameLength/HBoxAudioFrame/ResampleState.set_item_disabled(2, not (audiosamplerate == 44100 and opussamplerate == 48000)) + $VBoxFrameLength/HBoxOpusFrame/ResampleState.set_item_disabled(2, not (audiosamplerate == 44100 and opussamplerate == 48000)) opusframesize = int(opussamplerate*frametimems/1000.0) if audioopuschunkedeffect != null: audioopuschunkedeffect.opusframesize = opusframesize - var resamplestate = $VBoxFrameLength/HBoxAudioFrame/ResampleState.get_selected_id() + var resamplestate = $VBoxFrameLength/HBoxOpusFrame/ResampleState.get_selected_id() audiosamplesize = int(audiosamplerate*frametimems/1000) if resamplestate == 0: # uncompressed opusframesize = 0 @@ -141,10 +141,10 @@ func updatesamplerates(): audioopuschunkedeffect.audiosamplesize = audiosamplesize mqttpacketencodebase64 = $HBoxMosquitto/base64.button_pressed - $VBoxFrameLength/HBoxOpusFrame/LabFrameLength.text = "%d opus samples at" % opusframesize - $VBoxFrameLength/HBoxAudioFrame/LabFrameLength.text = "%d samples at" % audiosamplesize - recordedheader = { "opusframesize":opusframesize, "audiosamplesize":audiosamplesize, - "opussamplerate":opussamplerate, "audiosamplerate":audiosamplerate, + $VBoxFrameLength/HBoxOpusBitRate/LabFrameLength.text = "%d samples" % opusframesize + $VBoxFrameLength/HBoxAudioFrame/LabFrameLength.text = "%d samples" % audiosamplesize + recordedheader = { "opusframesize":opusframesize, + "opussamplerate":opussamplerate, "prefixbyteslength":prefixbyteslength, "mqttpacketencoding":"base64" if mqttpacketencodebase64 else "binary" } if len(recordedsamples) != 0 and len(recordedsamples[0]) != audiosamplesize: @@ -158,7 +158,7 @@ func updatesamplerates(): var opuspacket = audioopuschunkedeffect.chunk_to_opus_packet(prefixbytes, s, $HBoxBigButtons/VBoxPTT/Denoise.button_pressed) recordedopuspackets.append(opuspacket) recordedopuspacketsMemSize += opuspacket.size() - $HBoxPlaycount/GridContainer/FrameCount.text = str(len(recordedopuspackets)) + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = str(len(recordedopuspackets)) if resamplestate == 3: print("Uncomp resampled only applies to resampling of recorded message, not applied to transmitted message") @@ -168,17 +168,17 @@ func updatesamplerates(): var resampledchunk = audioopuschunkedeffect.chunk_resample(s, $HBoxBigButtons/VBoxPTT/Denoise.button_pressed and (opussamplerate == 48000), false) recordedresampledpackets.append(resampledchunk) recordedopuspacketsMemSize = len(recordedresampledpackets)*len(recordedresampledpackets[0])*4 - $HBoxPlaycount/GridContainer/FrameCount.text = "1" + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = "1" recordedheader["uncompressedresampledaudiorate"] = opussamplerate recordedheader["uncompressedresampledframesize"] = int(opussamplerate*frametimems/1000.0) else: if len(recordedsamples): recordedopuspacketsMemSize = len(recordedsamples)*len(recordedsamples[0])*4 - $HBoxPlaycount/GridContainer/FrameCount.text = "1" + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = "1" - $HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) + $VBoxPlayback/HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) var tm = len(recordedsamples)*frametimems*0.001 - $HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm if tm else 0)) + $VBoxPlayback/HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm if tm else 0)) setupaudioshader() func setupaudioshader(): @@ -219,11 +219,11 @@ func starttalking(): recordedsamples = [ ] recordedopuspackets = [ ] recordedresampledpackets = null - $HBoxPlaycount/GridContainer/FrameCount.text = str(0) - $HBoxPlaycount/GridContainer/TimeSecs.text = str(0) + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = str(0) + $VBoxPlayback/HBoxPlaycount/GridContainer/TimeSecs.text = str(0) recordedopuspacketsMemSize = 0 - $HBoxPlaycount/GridContainer/Totalbytes.text = str(0) - $HBoxPlaycount/GridContainer/Bytespersec.text = str(0) + $VBoxPlayback/HBoxPlaycount/GridContainer/Totalbytes.text = str(0) + $VBoxPlayback/HBoxPlaycount/GridContainer/Bytespersec.text = str(0) print("start talking") $MQTTnetwork.transportaudiopacketjson(recordedheader) @@ -263,7 +263,7 @@ func _input(event): func _process(_delta): var talking = $HBoxBigButtons/VBoxPTT/PTT.button_pressed if talking: - $HBoxPlaycount/GridContainer/TimeSecs.text = "%.1f" % ((Time.get_ticks_msec() - talkingstarttime)*0.001) + $VBoxPlayback/HBoxPlaycount/GridContainer/TimeSecs.text = "%.1f" % ((Time.get_ticks_msec() - talkingstarttime)*0.001) if talking and not currentlytalking: if not $AudioStreamMicrophone.playing: $AudioStreamMicrophone.play() @@ -312,11 +312,11 @@ func _process(_delta): if len(recordedopuspackets) < maxrecordedsamples: recordedopuspackets.append(opuspacket) $MQTTnetwork.transportaudiopacket(opuspacket, mqttpacketencodebase64) - $HBoxPlaycount/GridContainer/FrameCount.text = str(len(recordedopuspackets)) + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = str(len(recordedopuspackets)) recordedopuspacketsMemSize += opuspacket.size() - $HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) + $VBoxPlayback/HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) var tm = len(recordedopuspackets)*audioopuschunkedeffect.audiosamplesize*1.0/audioopuschunkedeffect.audiosamplerate - $HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm)) + $VBoxPlayback/HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm)) else: $MQTTnetwork.transportaudiopacket(var_to_bytes(audiosamples), mqttpacketencodebase64) audioopuschunkedeffect.drop_chunk() @@ -348,10 +348,10 @@ func _process(_delta): var rawpacket = var_to_bytes(audiosamples) recordedopuspacketsMemSize += rawpacket.size() $MQTTnetwork.transportaudiopacket(rawpacket, mqttpacketencodebase64) - $HBoxPlaycount/GridContainer/FrameCount.text = str(framecount) - $HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) + $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = str(framecount) + $VBoxPlayback/HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) var tm = framecount*audiosamplesize*1.0/audiosamplerate - $HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm)) + $VBoxPlayback/HBoxPlaycount/GridContainer/Bytespersec.text = str(int(recordedopuspacketsMemSize/tm)) else: if audioopuschunkedeffect != null: @@ -365,10 +365,10 @@ func endtalking(): func _on_play_pressed(): if audioeffectpitchshift != null: - var speedup = $HBoxPlaycount/VBoxExpt/StreamSpeedup.value + var speedup = $VBoxPlayback/HBoxStream/StreamSpeedup.value AudioServer.set_bus_effect_enabled(speechbusidx, audioeffectpitchshiftidx, (speedup != 1.0)) SelfMember.get_node("AudioStreamPlayer").pitch_scale = speedup - #audioeffectpitchshift.pitch_scale = 1.0/speedup + audioeffectpitchshift.pitch_scale = 1.0/speedup if recordedresampledpackets != null: SelfMember.processheaderpacket(recordedheader.duplicate()) @@ -388,6 +388,7 @@ func _on_play_pressed(): SelfMember.processheaderpacket(recordedheader.duplicate()) assert (SelfMember.resampledpacketsbuffer == null) SelfMember.audiopacketsbuffer = lrecordedsamples + SelfMember.playbackstarttime = Time.get_ticks_msec() var saveplaybackfile = "user://savedplayback.dat" func _on_sav_options_item_selected(index): @@ -406,7 +407,7 @@ func _on_sav_options_item_selected(index): prints(" sample rates disagree!!", dat["audiosamplerate"], audiosamplerate) recordedsamples = dat["recordedsamples"] f.close() - $HBoxPlaycount/VBoxExpt/SavOptions.select(0) + $VBoxPlayback/HBoxPlaycount/VBoxExpt/SavOptions.select(0) func _on_frame_duration_item_selected(_index): diff --git a/example/radiomqtt/radiomqtt.tscn b/example/radiomqtt/radiomqtt.tscn index 3140842..75b5e51 100644 --- a/example/radiomqtt/radiomqtt.tscn +++ b/example/radiomqtt/radiomqtt.tscn @@ -61,6 +61,9 @@ shader_parameter/drawresampled = false shader_parameter/voice = ExtResource("3_eh2h5") shader_parameter/voice_resampled = ExtResource("3_eh2h5") +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_onpxr"] +bg_color = Color(0.427451, 0.439216, 0, 1) + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_67wxx"] bg_color = Color(0.290196, 0.505882, 0.490196, 1) @@ -71,9 +74,6 @@ corner_radius_top_right = 15 corner_radius_bottom_right = 15 corner_radius_bottom_left = 15 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_onpxr"] -bg_color = Color(0.427451, 0.439216, 0, 1) - [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7rhvb"] bg_color = Color(0.470588, 0.211765, 0.533333, 1) @@ -271,7 +271,133 @@ color = Color(0.713257, 0.108138, 0.396675, 1) custom_minimum_size = Vector2(0, 20) layout_mode = 2 -[node name="Label2" type="Label" parent="."] +[node name="VBoxFrameLength" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxFrameLength"] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 +theme_override_font_sizes/font_size = 20 +theme_override_styles/normal = SubResource("StyleBoxFlat_onpxr") +text = "LibOpus compression and resampling" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HBoxOpusFrame" type="HBoxContainer" parent="VBoxFrameLength"] +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="LabFrameDuration" type="Label" parent="VBoxFrameLength/HBoxOpusFrame"] +layout_mode = 2 +text = "Frame duration" + +[node name="FrameDuration" type="OptionButton" parent="VBoxFrameLength/HBoxOpusFrame"] +layout_mode = 2 +item_count = 6 +popup/item_0/text = "2.5ms" +popup/item_1/text = "5ms" +popup/item_1/id = 1 +popup/item_2/text = "10ms" +popup/item_2/id = 2 +popup/item_3/text = "20ms" +popup/item_3/id = 3 +popup/item_4/text = "40ms" +popup/item_4/id = 4 +popup/item_5/text = "60ms" +popup/item_5/id = 5 + +[node name="ResampleState" type="OptionButton" parent="VBoxFrameLength/HBoxOpusFrame"] +layout_mode = 2 +item_count = 4 +popup/item_0/text = "Uncompressed" +popup/item_1/text = "Speex Resample" +popup/item_1/id = 1 +popup/item_2/text = "44.1kHz as 48kHz" +popup/item_2/id = 2 +popup/item_3/text = "Uncomp resampled" +popup/item_3/id = 3 + +[node name="HBoxAudioFrame" type="HBoxContainer" parent="VBoxFrameLength"] +layout_mode = 2 + +[node name="LabAudioSampler" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 +text = "Mic Audio Frame:" + +[node name="LabSampleRate" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 +text = "Sample Rate" + +[node name="SampleRate" type="SpinBox" parent="VBoxFrameLength/HBoxAudioFrame"] +custom_minimum_size = Vector2(95, 0) +layout_mode = 2 +min_value = 8000.0 +max_value = 96000.0 +step = 100.0 +value = 44100.0 +suffix = "Hz" + +[node name="LabFrameLength" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 +text = "0 samples" + +[node name="HBoxOpusBitRate" type="HBoxContainer" parent="VBoxFrameLength"] +layout_mode = 2 + +[node name="LabOpus" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +text = "Opus Frame:" + +[node name="LabSampleRate" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +text = "Sample Rate" + +[node name="SampleRate" type="OptionButton" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +item_count = 7 +popup/item_0/text = "8KHz" +popup/item_1/text = "12KHz" +popup/item_1/id = 1 +popup/item_2/text = "16KHz" +popup/item_2/id = 2 +popup/item_3/text = "24KHz" +popup/item_3/id = 3 +popup/item_4/text = "48KHz" +popup/item_4/id = 4 +popup/item_5/text = "4KHz" +popup/item_5/id = 5 +popup/item_6/text = "2KHz" +popup/item_6/id = 6 + +[node name="LabBitRate" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +text = "Bit Rate" + +[node name="BitRate" type="OptionButton" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +item_count = 5 +popup/item_0/text = "24000" +popup/item_1/text = "12000" +popup/item_1/id = 1 +popup/item_2/text = "10000" +popup/item_2/id = 2 +popup/item_3/text = "6000" +popup/item_3/id = 3 +popup/item_4/text = "3000" +popup/item_4/id = 4 + +[node name="LabFrameLength" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] +layout_mode = 2 +text = "0 samples" + +[node name="HSeparator4" type="HSeparator" parent="."] +custom_minimum_size = Vector2(0, 20) +layout_mode = 2 + +[node name="VBoxPlayback" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label2" type="Label" parent="VBoxPlayback"] custom_minimum_size = Vector2(0, 40) layout_mode = 2 theme_override_font_sizes/font_size = 20 @@ -280,41 +406,32 @@ text = "Recording Playback" horizontal_alignment = 1 vertical_alignment = 1 -[node name="Label3" type="RichTextLabel" parent="."] +[node name="Label3" type="RichTextLabel" parent="VBoxPlayback"] layout_mode = 2 bbcode_enabled = true text = "Playback the current recording after compression at different rates defined below. Compression is applied to the original raw recording." fit_content = true -[node name="HBoxPlaycount" type="HBoxContainer" parent="."] +[node name="HBoxPlaycount" type="HBoxContainer" parent="VBoxPlayback"] layout_mode = 2 size_flags_horizontal = 4 size_flags_stretch_ratio = 0.14 tooltip_text = "Speedup" -[node name="Play" type="Button" parent="HBoxPlaycount"] +[node name="Play" type="Button" parent="VBoxPlayback/HBoxPlaycount"] custom_minimum_size = Vector2(60, 0) layout_mode = 2 theme_override_styles/normal = SubResource("StyleBoxFlat_icid5") text = "Play " -[node name="VBoxExpt" type="VBoxContainer" parent="HBoxPlaycount"] +[node name="VBoxExpt" type="VBoxContainer" parent="VBoxPlayback/HBoxPlaycount"] layout_mode = 2 size_flags_horizontal = 0 size_flags_vertical = 0 -[node name="StreamSpeedup" type="SpinBox" parent="HBoxPlaycount/VBoxExpt"] -layout_mode = 2 -size_flags_horizontal = 0 -tooltip_text = "Playback speed -(experimental)" -min_value = 0.1 -max_value = 3.0 -step = 0.1 -value = 1.0 - -[node name="SavOptions" type="OptionButton" parent="HBoxPlaycount/VBoxExpt"] +[node name="SavOptions" type="OptionButton" parent="VBoxPlayback/HBoxPlaycount/VBoxExpt"] +visible = false layout_mode = 2 selected = 0 item_count = 4 @@ -326,158 +443,93 @@ popup/item_2/id = 2 popup/item_3/text = "Transmit" popup/item_3/id = 3 -[node name="VSeparator" type="VSeparator" parent="HBoxPlaycount"] +[node name="VSeparator" type="VSeparator" parent="VBoxPlayback/HBoxPlaycount"] custom_minimum_size = Vector2(20, 0) layout_mode = 2 -[node name="GridContainer" type="GridContainer" parent="HBoxPlaycount"] +[node name="GridContainer" type="GridContainer" parent="VBoxPlayback/HBoxPlaycount"] layout_mode = 2 columns = 4 -[node name="Label2" type="Label" parent="HBoxPlaycount/GridContainer"] +[node name="Label2" type="Label" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 text = "Time (s):" -[node name="TimeSecs" type="LineEdit" parent="HBoxPlaycount/GridContainer"] +[node name="TimeSecs" type="LineEdit" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 text = "0" editable = false -[node name="Label3" type="Label" parent="HBoxPlaycount/GridContainer"] +[node name="Label3" type="Label" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 text = "Bytes:" -[node name="Totalbytes" type="LineEdit" parent="HBoxPlaycount/GridContainer"] +[node name="Totalbytes" type="LineEdit" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 editable = false -[node name="Label" type="Label" parent="HBoxPlaycount/GridContainer"] +[node name="Label" type="Label" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 text = "Frames:" -[node name="FrameCount" type="LineEdit" parent="HBoxPlaycount/GridContainer"] +[node name="FrameCount" type="LineEdit" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 editable = false -[node name="Label4" type="Label" parent="HBoxPlaycount/GridContainer"] +[node name="Label4" type="Label" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 text = "Bytes/s:" -[node name="Bytespersec" type="LineEdit" parent="HBoxPlaycount/GridContainer"] +[node name="Bytespersec" type="LineEdit" parent="VBoxPlayback/HBoxPlaycount/GridContainer"] layout_mode = 2 editable = false -[node name="HSeparator4" type="HSeparator" parent="."] -custom_minimum_size = Vector2(0, 10) -layout_mode = 2 - -[node name="VBoxFrameLength" type="VBoxContainer" parent="."] -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxFrameLength"] -custom_minimum_size = Vector2(0, 40) -layout_mode = 2 -theme_override_font_sizes/font_size = 20 -theme_override_styles/normal = SubResource("StyleBoxFlat_onpxr") -text = "LibOpus compression and resampling" -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="HBoxOpusFrame" type="HBoxContainer" parent="VBoxFrameLength"] -layout_mode = 2 -size_flags_horizontal = 0 - -[node name="LabFrameDuration" type="Label" parent="VBoxFrameLength/HBoxOpusFrame"] -layout_mode = 2 -text = "Frame duration" - -[node name="FrameDuration" type="OptionButton" parent="VBoxFrameLength/HBoxOpusFrame"] -layout_mode = 2 -item_count = 6 -popup/item_0/text = "2.5ms" -popup/item_1/text = "5ms" -popup/item_1/id = 1 -popup/item_2/text = "10ms" -popup/item_2/id = 2 -popup/item_3/text = "20ms" -popup/item_3/id = 3 -popup/item_4/text = "40ms" -popup/item_4/id = 4 -popup/item_5/text = "60ms" -popup/item_5/id = 5 - -[node name="LabFrameLength" type="Label" parent="VBoxFrameLength/HBoxOpusFrame"] +[node name="HBoxStream" type="HBoxContainer" parent="VBoxPlayback"] layout_mode = 2 -text = "0 samples at" -[node name="SampleRate" type="OptionButton" parent="VBoxFrameLength/HBoxOpusFrame"] +[node name="LabelStream" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -item_count = 7 -popup/item_0/text = "8KHz" -popup/item_1/text = "12KHz" -popup/item_1/id = 1 -popup/item_2/text = "16KHz" -popup/item_2/id = 2 -popup/item_3/text = "24KHz" -popup/item_3/id = 3 -popup/item_4/text = "48KHz" -popup/item_4/id = 4 -popup/item_5/text = "4KHz" -popup/item_5/id = 5 -popup/item_6/text = "2KHz" -popup/item_6/id = 6 +text = "Out: " -[node name="HBoxAudioFrame" type="HBoxContainer" parent="VBoxFrameLength"] -layout_mode = 2 - -[node name="LabAudioSampler" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +[node name="LabelSamplerate" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -text = "Audio sampler" +text = "sample rate" -[node name="ResampleState" type="OptionButton" parent="VBoxFrameLength/HBoxAudioFrame"] +[node name="SampleRate" type="SpinBox" parent="VBoxPlayback/HBoxStream"] +custom_minimum_size = Vector2(95, 0) layout_mode = 2 -item_count = 4 -popup/item_0/text = "Uncompressed" -popup/item_1/text = "Speex Resample" -popup/item_1/id = 1 -popup/item_2/text = "44.1kHz as 48kHz" -popup/item_2/id = 2 -popup/item_3/text = "Uncomp resampled" -popup/item_3/id = 3 +min_value = 8000.0 +max_value = 96000.0 +step = 100.0 +value = 44100.0 +suffix = "Hz" -[node name="LabFrameLength" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +[node name="LabelMixrate" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -text = "---" +text = "mix rate" -[node name="SampleRate" type="SpinBox" parent="VBoxFrameLength/HBoxAudioFrame"] +[node name="MixRate" type="SpinBox" parent="VBoxPlayback/HBoxStream"] custom_minimum_size = Vector2(95, 0) layout_mode = 2 min_value = 8000.0 max_value = 96000.0 step = 100.0 value = 44100.0 -editable = false suffix = "Hz" -[node name="HBoxBitRate" type="HBoxContainer" parent="VBoxFrameLength"] -layout_mode = 2 - -[node name="LabBitRate" type="Label" parent="VBoxFrameLength/HBoxBitRate"] +[node name="LabelSpeedup" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -text = "Opus Bit Rate" +text = "speed up" -[node name="BitRate" type="OptionButton" parent="VBoxFrameLength/HBoxBitRate"] +[node name="StreamSpeedup" type="SpinBox" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -item_count = 5 -popup/item_0/text = "24000" -popup/item_1/text = "12000" -popup/item_1/id = 1 -popup/item_2/text = "10000" -popup/item_2/id = 2 -popup/item_3/text = "6000" -popup/item_3/id = 3 -popup/item_4/text = "3000" -popup/item_4/id = 4 +size_flags_horizontal = 0 +tooltip_text = "Playback speed +(experimental)" +min_value = 0.1 +max_value = 3.0 +step = 0.1 +value = 1.0 [node name="HSeparator5" type="HSeparator" parent="."] custom_minimum_size = Vector2(0, 20) @@ -670,12 +722,12 @@ text = "sil" [connection signal="button_down" from="HBoxBigButtons/VBoxVox/Silence" to="HBoxMicTalk" method="_on_silence_button_down"] [connection signal="toggled" from="HBoxMicTalk/MicWorking" to="." method="_on_mic_working_toggled"] [connection signal="value_changed" from="HBoxMicTalk/HSliderVox" to="HBoxMicTalk" method="_on_h_slider_vox_value_changed"] -[connection signal="pressed" from="HBoxPlaycount/Play" to="." method="_on_play_pressed"] -[connection signal="item_selected" from="HBoxPlaycount/VBoxExpt/SavOptions" to="." method="_on_sav_options_item_selected"] [connection signal="item_selected" from="VBoxFrameLength/HBoxOpusFrame/FrameDuration" to="." method="_on_frame_duration_item_selected"] -[connection signal="item_selected" from="VBoxFrameLength/HBoxOpusFrame/SampleRate" to="." method="_on_sample_rate_item_selected"] -[connection signal="item_selected" from="VBoxFrameLength/HBoxAudioFrame/ResampleState" to="." method="_on_resample_state_item_selected"] -[connection signal="item_selected" from="VBoxFrameLength/HBoxBitRate/BitRate" to="." method="_on_option_button_item_selected"] +[connection signal="item_selected" from="VBoxFrameLength/HBoxOpusFrame/ResampleState" to="." method="_on_resample_state_item_selected"] +[connection signal="item_selected" from="VBoxFrameLength/HBoxOpusBitRate/SampleRate" to="." method="_on_sample_rate_item_selected"] +[connection signal="item_selected" from="VBoxFrameLength/HBoxOpusBitRate/BitRate" to="." method="_on_option_button_item_selected"] +[connection signal="pressed" from="VBoxPlayback/HBoxPlaycount/Play" to="." method="_on_play_pressed"] +[connection signal="item_selected" from="VBoxPlayback/HBoxPlaycount/VBoxExpt/SavOptions" to="." method="_on_sav_options_item_selected"] [connection signal="broker_connection_failed" from="MQTTnetwork/MQTT" to="MQTTnetwork" method="_on_mqtt_broker_connection_failed"] [connection signal="toggled" from="MQTTnetwork/Connect" to="MQTTnetwork" method="_on_connect_toggled"] [connection signal="item_selected" from="MQTTnetwork/GridContainer/presets" to="MQTTnetwork" method="_on_mqtt_broker_item_selected"] From a71f425339c4a39a8289254f8536b981e0e61967 Mon Sep 17 00:00:00 2001 From: Julian Todd Date: Fri, 25 Oct 2024 23:11:46 +0100 Subject: [PATCH 6/6] debugging the different options and setting working for web --- example/default_bus_layout.tres | 7 +- example/export_presets.cfg | 2 +- example/radiomqtt/member.gd | 23 ++--- example/radiomqtt/member.tscn | 6 +- example/radiomqtt/radiomqtt.gd | 155 ++++++++++++++++-------------- example/radiomqtt/radiomqtt.tscn | 59 ++++++------ src/audio_effect_opus_chunked.cpp | 9 +- 7 files changed, 133 insertions(+), 128 deletions(-) diff --git a/example/default_bus_layout.tres b/example/default_bus_layout.tres index 6fa6a3e..1758bfc 100644 --- a/example/default_bus_layout.tres +++ b/example/default_bus_layout.tres @@ -1,12 +1,9 @@ -[gd_resource type="AudioBusLayout" load_steps=3 format=3 uid="uid://orx4iw038t0c"] +[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://orx4iw038t0c"] [sub_resource type="AudioEffectPitchShift" id="AudioEffectPitchShift_jq6ag"] resource_name = "PitchShift" fft_size = 1 -[sub_resource type="AudioEffectOpusChunked" id="AudioEffectOpusChunked_4km5k"] -resource_name = "OpusChunked" - [resource] bus/1/name = &"SpeechBus" bus/1/solo = false @@ -22,5 +19,3 @@ bus/2/mute = true bus/2/bypass_fx = false bus/2/volume_db = 0.0 bus/2/send = &"Master" -bus/2/effect/0/effect = SubResource("AudioEffectOpusChunked_4km5k") -bus/2/effect/0/enabled = true diff --git a/example/export_presets.cfg b/example/export_presets.cfg index 766607f..e227573 100644 --- a/example/export_presets.cfg +++ b/example/export_presets.cfg @@ -683,7 +683,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="" +export_path="../../releases/twovoipweb/index.html" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false diff --git a/example/radiomqtt/member.gd b/example/radiomqtt/member.gd index 7b3ace4..5a64d9c 100644 --- a/example/radiomqtt/member.gd +++ b/example/radiomqtt/member.gd @@ -63,31 +63,25 @@ func processheaderpacket(h): prefixbyteslength = h["prefixbyteslength"] mqttpacketencodebase64 = (h.get("mqttpacketencoding") == "base64") chunkcount = 0 - if opusframesize != h["opusframesize"] or opussamplerate != h["opussamplerate"] or (h.has("uncompressedresampledaudiorate") != (resampledpacketsbuffer != null)): + if opusframesize != h["opusframesize"] or opussamplerate != h["opussamplerate"] or \ + ((audiostreamopuschunked != null) and (audiostreamopuschunked.audiosamplesize != audiosamplesize or audiostreamopuschunked.audiosamplerate != audiosamplerate or \ + audiostreamopuschunked.mix_rate != mix_rate)): opusframesize = h["opusframesize"] opussamplerate = h["opussamplerate"] var frametimems = opusframesize*1000.0/opussamplerate audiosamplesize = int(audiosamplerate*frametimems/1000.0) - if h.has("uncompressedresampledaudiorate"): - resampledpacketsbuffer = [ ] - opusframesize = h["uncompressedresampledframesize"] - else: - resampledpacketsbuffer = null + resampledpacketsbuffer = null if audiostreamopuschunked != null: audiostreamopuschunked.opusframesize = opusframesize audiostreamopuschunked.opussamplerate = opussamplerate - - if audiostreamopuschunked != null and (audiostreamopuschunked.audiosamplesize != audiosamplesize or audiostreamopuschunked.audiosamplerate != audiosamplerate or audiostreamopuschunked.mix_rate != mix_rate): - audiostreamopuschunked.audiosamplesize = audiosamplesize - audiostreamopuschunked.audiosamplerate = audiosamplerate - audiostreamopuschunked.mix_rate = mix_rate - audiobuffersize = audiostreamopuschunked.audiosamplesize*audiostreamopuschunked.audiosamplechunks + audiostreamopuschunked.audiosamplesize = audiosamplesize + audiostreamopuschunked.audiosamplerate = audiosamplerate + audiostreamopuschunked.mix_rate = mix_rate + audiobuffersize = audiostreamopuschunked.audiosamplesize*audiostreamopuschunked.audiosamplechunks print("createdecoder ", opussamplerate, " ", opusframesize, " ", audiosamplerate, " ", audiosamplesize) #$AudioStreamPlayer.play() setupaudioshader() - - if opusframesize != 0 and audiostreamopuschunked == null: print("Compressed opus stream received that we cannot decompress") audioserveroutputlatency = AudioServer.get_output_latency() @@ -96,6 +90,7 @@ func processheaderpacket(h): func setupaudioshader(): var audiosampleframedata : PackedVector2Array audiosampleframedata.resize(audiosamplesize) + assert (audiosamplesize != 0) audiosampleframetextureimage = Image.create_from_data(audiosamplesize, 1, false, Image.FORMAT_RGF, audiosampleframedata.to_byte_array()) audiosampleframetexture = ImageTexture.create_from_image(audiosampleframetextureimage) assert (audiosampleframetexture != null) diff --git a/example/radiomqtt/member.tscn b/example/radiomqtt/member.tscn index 3929631..8833c9e 100644 --- a/example/radiomqtt/member.tscn +++ b/example/radiomqtt/member.tscn @@ -1,11 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://c1ibcb1toyerh"] +[gd_scene load_steps=5 format=3 uid="uid://c1ibcb1toyerh"] [ext_resource type="Script" path="res://radiomqtt/member.gd" id="1_o3hks"] [ext_resource type="Texture2D" uid="uid://cvyjsyigutxbh" path="res://icon.png" id="2_atirx"] -[sub_resource type="AudioStreamOpusChunked" id="AudioStreamOpusChunked_l61p2"] -resource_local_to_scene = true - [sub_resource type="Shader" id="Shader_022wp"] code = "// NOTE: Shader automatically converted from Godot Engine 4.3.beta's CanvasItemMaterial. @@ -38,7 +35,6 @@ color = Color(0.423529, 0, 0.423529, 1) script = ExtResource("1_o3hks") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] -stream = SubResource("AudioStreamOpusChunked_l61p2") bus = &"SpeechBus" [node name="Label" type="Label" parent="."] diff --git a/example/radiomqtt/radiomqtt.gd b/example/radiomqtt/radiomqtt.gd index 3f23125..ca5d716 100644 --- a/example/radiomqtt/radiomqtt.gd +++ b/example/radiomqtt/radiomqtt.gd @@ -13,10 +13,12 @@ var audioopuschunkedeffect # : AudioEffectOpusChunked # values to use when AudioEffectOpusChunked cannot be instantiated var frametimems : float = 20 var opusbitrate : int = 0 -var opusframesize : int = 20 var audiosamplerate : int = 44100 -var opussamplerate : int = 48000 var audiosamplesize : int = 882 +var audioresamplerate : int = 48000 +var audioresamplesize : int = 960 +var opussamplerate : int = 48000 +var opusframesize : int = 960 var prefixbyteslength : int = 0 var mqttpacketencodebase64 : bool = false @@ -41,20 +43,24 @@ func _ready(): print("AudioServer.get_mix_rate()=", AudioServer.get_mix_rate()) print("ProjectSettings.get_setting_with_override(\"audio/driver/mix_rate\")=", ProjectSettings.get_setting_with_override("audio/driver/mix_rate")) $VBoxPlayback/HBoxStream/MixRate.value = AudioServer.get_mix_rate() - $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = ProjectSettings.get_setting_with_override("audio/driver/mix_rate") + if ProjectSettings.get_setting_with_override("audio/driver/mix_rate") != 0: + $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = ProjectSettings.get_setting_with_override("audio/driver/mix_rate") + $VBoxPlayback/HBoxStream/SampleRate.value = ProjectSettings.get_setting_with_override("audio/driver/mix_rate") + else: + $VBoxFrameLength/HBoxAudioFrame/SampleRate.value = AudioServer.get_mix_rate() + $VBoxPlayback/HBoxStream/SampleRate.value = AudioServer.get_mix_rate() if $VBoxFrameLength/HBoxOpusFrame/FrameDuration.selected == -1: $VBoxFrameLength/HBoxOpusFrame/FrameDuration.select(3) if $VBoxFrameLength/HBoxOpusBitRate/SampleRate.selected == -1: $VBoxFrameLength/HBoxOpusBitRate/SampleRate.select(4) - if $VBoxFrameLength/HBoxOpusFrame/ResampleState.selected == -1: - $VBoxFrameLength/HBoxOpusFrame/ResampleState.select(1) + if $VBoxFrameLength/HBoxOpusBitRate/BitRate.selected == -1: $VBoxFrameLength/HBoxOpusBitRate/BitRate.select(2) if not ClassDB.can_instantiate("AudioEffectOpusChunked"): - $VBoxFrameLength/HBoxOpusFrame/ResampleState.select(0) - $VBoxFrameLength/HBoxOpusFrame/ResampleState.disabled = true $TwovoipWarning.visible = true + $VBoxFrameLength/HBoxAudioFrame/ResampleRate.value = $VBoxFrameLength/HBoxAudioFrame/SampleRate.value + $VBoxFrameLength/HBoxOpusBitRate/SampleRate.disabled = true assert ($AudioStreamMicrophone.bus == "MicrophoneBus") var audioeffectonmic : AudioEffect = null @@ -113,68 +119,67 @@ func resamplerecordedsamples(orgsamples, newsamplesize): func updatesamplerates(): frametimems = float($VBoxFrameLength/HBoxOpusFrame/FrameDuration.text) - opusbitrate = int($VBoxFrameLength/HBoxOpusBitRate/BitRate.text) - opussamplerate = int($VBoxFrameLength/HBoxOpusBitRate/SampleRate.text)*1000 audiosamplerate = $VBoxFrameLength/HBoxAudioFrame/SampleRate.value - if audioopuschunkedeffect != null: - audioopuschunkedeffect.audiosamplerate = audiosamplerate - audioopuschunkedeffect.opussamplerate = opussamplerate - audioopuschunkedeffect.opusbitrate = opusbitrate - opusframesize = int(opussamplerate*frametimems/1000.0) - audioopuschunkedeffect.opusframesize = opusframesize - $HBoxBigButtons/VBoxPTT/Denoise.disabled = not (audioopuschunkedeffect.denoiser_available() and opussamplerate == 48000) - $VBoxFrameLength/HBoxOpusFrame/ResampleState.set_item_disabled(2, not (audiosamplerate == 44100 and opussamplerate == 48000)) + audiosamplesize = int(audiosamplerate*frametimems/1000.0) + audioresamplerate = $VBoxFrameLength/HBoxAudioFrame/ResampleRate.value + audioresamplesize = int(audioresamplerate*frametimems/1000.0) + opussamplerate = int($VBoxFrameLength/HBoxOpusBitRate/SampleRate.text)*1000 opusframesize = int(opussamplerate*frametimems/1000.0) + + print("aaa audiosamplesize ", audiosamplesize, " audiosamplerate ", audiosamplerate) + + var noopuscompression = false + if opussamplerate == audioresamplerate: + $VBoxFrameLength/HBoxOpusBitRate/Compressed.disabled = false + if not $VBoxFrameLength/HBoxOpusBitRate/Compressed.button_pressed: + noopuscompression = true + else: + $VBoxFrameLength/HBoxOpusBitRate/Compressed.disabled = true + noopuscompression = true + opusbitrate = int($VBoxFrameLength/HBoxOpusBitRate/BitRate.text) + if audioopuschunkedeffect != null: - audioopuschunkedeffect.opusframesize = opusframesize - var resamplestate = $VBoxFrameLength/HBoxOpusFrame/ResampleState.get_selected_id() - audiosamplesize = int(audiosamplerate*frametimems/1000) - if resamplestate == 0: # uncompressed - opusframesize = 0 - elif resamplestate == 1: # Speexresample - pass - elif resamplestate == 2: # 441.1k as 48k fakery - audiosamplesize = opusframesize - elif resamplestate == 3: # uncompressed resampled - opusframesize = 0 - if audioopuschunkedeffect != null: + audioopuschunkedeffect.audiosamplerate = audiosamplerate audioopuschunkedeffect.audiosamplesize = audiosamplesize + audioopuschunkedeffect.opussamplerate = audioresamplerate + audioopuschunkedeffect.opusframesize = audioresamplesize + $HBoxBigButtons/VBoxPTT/Denoise.disabled = not (audioopuschunkedeffect.denoiser_available() and audioresamplerate == 48000) + audioopuschunkedeffect.opusbitrate = opusbitrate + else: + $VBoxFrameLength/HBoxOpusBitRate/Compressed.disabled = true + $HBoxBigButtons/VBoxPTT/Denoise.disabled = true mqttpacketencodebase64 = $HBoxMosquitto/base64.button_pressed - $VBoxFrameLength/HBoxOpusBitRate/LabFrameLength.text = "%d samples" % opusframesize $VBoxFrameLength/HBoxAudioFrame/LabFrameLength.text = "%d samples" % audiosamplesize - recordedheader = { "opusframesize":opusframesize, - "opussamplerate":opussamplerate, + $VBoxFrameLength/HBoxAudioFrame/LabResampleFrameLength.text = "%d samples" % audioresamplesize + recordedheader = { "opusframesize":audioresamplesize, + "opussamplerate":audioresamplerate, "prefixbyteslength":prefixbyteslength, "mqttpacketencoding":"base64" if mqttpacketencodebase64 else "binary" } if len(recordedsamples) != 0 and len(recordedsamples[0]) != audiosamplesize: recordedsamples = resamplerecordedsamples(recordedsamples, audiosamplesize) var prefixbytes = PackedByteArray() recordedopuspacketsMemSize = 0 - recordedopuspackets = [ ] + recordedopuspackets = null recordedresampledpackets = null - if opusframesize != 0: + if not noopuscompression: + recordedopuspackets = [ ] for s in recordedsamples: var opuspacket = audioopuschunkedeffect.chunk_to_opus_packet(prefixbytes, s, $HBoxBigButtons/VBoxPTT/Denoise.button_pressed) recordedopuspackets.append(opuspacket) recordedopuspacketsMemSize += opuspacket.size() $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = str(len(recordedopuspackets)) - - if resamplestate == 3: - print("Uncomp resampled only applies to resampling of recorded message, not applied to transmitted message") - recordedresampledpackets = [ ] - if len(recordedsamples): - for s in recordedsamples: - var resampledchunk = audioopuschunkedeffect.chunk_resample(s, $HBoxBigButtons/VBoxPTT/Denoise.button_pressed and (opussamplerate == 48000), false) - recordedresampledpackets.append(resampledchunk) - recordedopuspacketsMemSize = len(recordedresampledpackets)*len(recordedresampledpackets[0])*4 - $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = "1" - recordedheader["uncompressedresampledaudiorate"] = opussamplerate - recordedheader["uncompressedresampledframesize"] = int(opussamplerate*frametimems/1000.0) else: - if len(recordedsamples): - recordedopuspacketsMemSize = len(recordedsamples)*len(recordedsamples[0])*4 + recordedresampledpackets = [ ] + var denoise = not $HBoxBigButtons/VBoxPTT/Denoise.disabled and $HBoxBigButtons/VBoxPTT/Denoise.button_pressed + for s in recordedsamples: + if audioopuschunkedeffect: + recordedresampledpackets.append(audioopuschunkedeffect.chunk_resample(s, denoise, false)) + else: + recordedresampledpackets.append(s) $VBoxPlayback/HBoxPlaycount/GridContainer/FrameCount.text = "1" + if len(recordedresampledpackets): + recordedopuspacketsMemSize = len(recordedresampledpackets)*len(recordedresampledpackets[0])*4 $VBoxPlayback/HBoxPlaycount/GridContainer/Totalbytes.text = str(recordedopuspacketsMemSize) var tm = len(recordedsamples)*frametimems*0.001 @@ -190,10 +195,10 @@ func setupaudioshader(): audiosampleframetexture = ImageTexture.create_from_image(audiosampleframetextureimage) assert (audiosampleframetexture != null) $HBoxMicTalk/HSliderVox/ColorRectBackground.material.set_shader_parameter("voice", audiosampleframetexture) - if audioopuschunkedeffect.opusframesize != 0: + if opusframesize != 0: var audioresampledframedata_blank = PackedVector2Array() - audioresampledframedata_blank.resize(audioopuschunkedeffect.opusframesize) - audioresampledframetextureimage = Image.create_from_data(audioopuschunkedeffect.opusframesize, 1, false, Image.FORMAT_RGF, audioresampledframedata_blank.to_byte_array()) + audioresampledframedata_blank.resize(opusframesize) + audioresampledframetextureimage = Image.create_from_data(opusframesize, 1, false, Image.FORMAT_RGF, audioresampledframedata_blank.to_byte_array()) audioresampledframetexture = ImageTexture.create_from_image(audioresampledframetextureimage) assert (audioresampledframetexture != null) $HBoxMicTalk/HSliderVox/ColorRectBackground.material.set_shader_parameter("voice_resampled", audioresampledframetexture) @@ -236,8 +241,8 @@ func starttalking(): leadtimems -= frametimems Dundroppedchunks += 1 print("Undropped ", Dundroppedchunks, " chunks") - #if opusframesize != 0: - audioopuschunkedeffect.flush_opus_encoder(false) + if opusframesize != 0: + audioopuschunkedeffect.flush_opus_encoder(false) func _on_mic_working_toggled(toggled_on): print("_on_mic_working_toggled ", $AudioStreamMicrophone.playing, " to ", toggled_on) @@ -338,7 +343,7 @@ func _process(_delta): if currentlytalking: recordedsamples.append(audiosamples) var framecount = len(recordedsamples) - if opusframesize != 0: + if opusframesize != 0 and audioopuschunkedeffect != null: var opuspacket = audioopuschunkedeffect.chunk_to_opus_packet(prefixbytes, audiosamples, $HBoxBigButtons/VBoxPTT/Denoise.button_pressed) recordedopuspackets.append(opuspacket) framecount = len(recordedopuspackets) @@ -370,26 +375,21 @@ func _on_play_pressed(): SelfMember.get_node("AudioStreamPlayer").pitch_scale = speedup audioeffectpitchshift.pitch_scale = 1.0/speedup - if recordedresampledpackets != null: - SelfMember.processheaderpacket(recordedheader.duplicate()) - assert (SelfMember.resampledpacketsbuffer != null) - SelfMember.resampledpacketsbuffer = recordedresampledpackets.duplicate() - elif recordedopuspackets: - SelfMember.processheaderpacket(recordedheader.duplicate()) - assert (SelfMember.resampledpacketsbuffer == null) + var h = recordedheader.duplicate() + if recordedopuspackets: + SelfMember.processheaderpacket(h) + SelfMember.resampledpacketsbuffer = null SelfMember.opuspacketsbuffer = recordedopuspackets.duplicate() - else: - var lrecordedsamples = [ ] - if $HBoxBigButtons/VBoxPTT/Denoise.button_pressed and audioopuschunkedeffect.opusframesize != 0: - for s in recordedsamples: - lrecordedsamples.append(audioopuschunkedeffect.chunk_resample_denoise(s, true)) - else: - lrecordedsamples = recordedsamples.duplicate() - SelfMember.processheaderpacket(recordedheader.duplicate()) - assert (SelfMember.resampledpacketsbuffer == null) - SelfMember.audiopacketsbuffer = lrecordedsamples + elif recordedresampledpackets != null: + SelfMember.processheaderpacket(h) + SelfMember.resampledpacketsbuffer = recordedresampledpackets.duplicate() + elif recordedsamples and SelfMember.audiostreamgeneratorplayback != null: + SelfMember.audiosamplesize = audiosamplesize + SelfMember.audiopacketsbuffer = recordedsamples.duplicate() + SelfMember.playbackstarttime = Time.get_ticks_msec() + var saveplaybackfile = "user://savedplayback.dat" func _on_sav_options_item_selected(index): pass # Replace with function body. @@ -397,7 +397,7 @@ func _on_sav_options_item_selected(index): var f = FileAccess.open(saveplaybackfile, FileAccess.WRITE) prints("Saving to file:", f.get_path_absolute()) f.store_var({"audiosamplerate":audiosamplerate, - "recordedsamples":recordedsamples}) + "recordedsamples":recordedsamples}) f.close() elif index == 2: var f = FileAccess.open(saveplaybackfile, FileAccess.READ) @@ -414,6 +414,8 @@ func _on_frame_duration_item_selected(_index): updatesamplerates() func _on_sample_rate_item_selected(index): + $VBoxFrameLength/HBoxAudioFrame/ResampleRate.value = int($VBoxFrameLength/HBoxOpusBitRate/SampleRate.text)*1000 + $VBoxFrameLength/HBoxOpusBitRate/Compressed.button_pressed = true updatesamplerates() func _on_resample_state_item_selected(_index): @@ -431,3 +433,12 @@ func _on_denoise_toggled(toggled_on): func _on_base_64_toggled(toggled_on): updatesamplerates() + +func _on_compressed_toggled(toggled_on): + updatesamplerates() + +func _on_resample_rate_value_changed(value): + updatesamplerates() + +func _on_sample_rate_value_changed(value): + updatesamplerates() diff --git a/example/radiomqtt/radiomqtt.tscn b/example/radiomqtt/radiomqtt.tscn index 75b5e51..a52db25 100644 --- a/example/radiomqtt/radiomqtt.tscn +++ b/example/radiomqtt/radiomqtt.tscn @@ -306,34 +306,18 @@ popup/item_4/id = 4 popup/item_5/text = "60ms" popup/item_5/id = 5 -[node name="ResampleState" type="OptionButton" parent="VBoxFrameLength/HBoxOpusFrame"] -layout_mode = 2 -item_count = 4 -popup/item_0/text = "Uncompressed" -popup/item_1/text = "Speex Resample" -popup/item_1/id = 1 -popup/item_2/text = "44.1kHz as 48kHz" -popup/item_2/id = 2 -popup/item_3/text = "Uncomp resampled" -popup/item_3/id = 3 - [node name="HBoxAudioFrame" type="HBoxContainer" parent="VBoxFrameLength"] layout_mode = 2 -[node name="LabAudioSampler" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] -layout_mode = 2 -text = "Mic Audio Frame:" - [node name="LabSampleRate" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] layout_mode = 2 -text = "Sample Rate" +text = "Mic sampled" [node name="SampleRate" type="SpinBox" parent="VBoxFrameLength/HBoxAudioFrame"] custom_minimum_size = Vector2(95, 0) layout_mode = 2 -min_value = 8000.0 +min_value = 20.0 max_value = 96000.0 -step = 100.0 value = 44100.0 suffix = "Hz" @@ -341,6 +325,25 @@ suffix = "Hz" layout_mode = 2 text = "0 samples" +[node name="VSeparator" type="VSeparator" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 + +[node name="LabResampleRate" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 +text = "Resampled:" + +[node name="ResampleRate" type="SpinBox" parent="VBoxFrameLength/HBoxAudioFrame"] +custom_minimum_size = Vector2(95, 0) +layout_mode = 2 +min_value = 20.0 +max_value = 96000.0 +value = 48000.0 +suffix = "Hz" + +[node name="LabResampleFrameLength" type="Label" parent="VBoxFrameLength/HBoxAudioFrame"] +layout_mode = 2 +text = "0 samples" + [node name="HBoxOpusBitRate" type="HBoxContainer" parent="VBoxFrameLength"] layout_mode = 2 @@ -354,7 +357,8 @@ text = "Sample Rate" [node name="SampleRate" type="OptionButton" parent="VBoxFrameLength/HBoxOpusBitRate"] layout_mode = 2 -item_count = 7 +allow_reselect = true +item_count = 5 popup/item_0/text = "8KHz" popup/item_1/text = "12KHz" popup/item_1/id = 1 @@ -364,10 +368,6 @@ popup/item_3/text = "24KHz" popup/item_3/id = 3 popup/item_4/text = "48KHz" popup/item_4/id = 4 -popup/item_5/text = "4KHz" -popup/item_5/id = 5 -popup/item_6/text = "2KHz" -popup/item_6/id = 6 [node name="LabBitRate" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] layout_mode = 2 @@ -386,9 +386,10 @@ popup/item_3/id = 3 popup/item_4/text = "3000" popup/item_4/id = 4 -[node name="LabFrameLength" type="Label" parent="VBoxFrameLength/HBoxOpusBitRate"] +[node name="Compressed" type="CheckButton" parent="VBoxFrameLength/HBoxOpusBitRate"] layout_mode = 2 -text = "0 samples" +button_pressed = true +text = "Compressed" [node name="HSeparator4" type="HSeparator" parent="."] custom_minimum_size = Vector2(0, 20) @@ -419,7 +420,7 @@ size_flags_stretch_ratio = 0.14 tooltip_text = "Speedup" [node name="Play" type="Button" parent="VBoxPlayback/HBoxPlaycount"] -custom_minimum_size = Vector2(60, 0) +custom_minimum_size = Vector2(80, 0) layout_mode = 2 theme_override_styles/normal = SubResource("StyleBoxFlat_icid5") text = "Play @@ -489,7 +490,7 @@ layout_mode = 2 [node name="LabelStream" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 -text = "Out: " +text = "Play" [node name="LabelSamplerate" type="Label" parent="VBoxPlayback/HBoxStream"] layout_mode = 2 @@ -723,9 +724,11 @@ text = "sil" [connection signal="toggled" from="HBoxMicTalk/MicWorking" to="." method="_on_mic_working_toggled"] [connection signal="value_changed" from="HBoxMicTalk/HSliderVox" to="HBoxMicTalk" method="_on_h_slider_vox_value_changed"] [connection signal="item_selected" from="VBoxFrameLength/HBoxOpusFrame/FrameDuration" to="." method="_on_frame_duration_item_selected"] -[connection signal="item_selected" from="VBoxFrameLength/HBoxOpusFrame/ResampleState" to="." method="_on_resample_state_item_selected"] +[connection signal="value_changed" from="VBoxFrameLength/HBoxAudioFrame/SampleRate" to="." method="_on_sample_rate_value_changed"] +[connection signal="value_changed" from="VBoxFrameLength/HBoxAudioFrame/ResampleRate" to="." method="_on_resample_rate_value_changed"] [connection signal="item_selected" from="VBoxFrameLength/HBoxOpusBitRate/SampleRate" to="." method="_on_sample_rate_item_selected"] [connection signal="item_selected" from="VBoxFrameLength/HBoxOpusBitRate/BitRate" to="." method="_on_option_button_item_selected"] +[connection signal="toggled" from="VBoxFrameLength/HBoxOpusBitRate/Compressed" to="." method="_on_compressed_toggled"] [connection signal="pressed" from="VBoxPlayback/HBoxPlaycount/Play" to="." method="_on_play_pressed"] [connection signal="item_selected" from="VBoxPlayback/HBoxPlaycount/VBoxExpt/SavOptions" to="." method="_on_sav_options_item_selected"] [connection signal="broker_connection_failed" from="MQTTnetwork/MQTT" to="MQTTnetwork" method="_on_mqtt_broker_connection_failed"] diff --git a/src/audio_effect_opus_chunked.cpp b/src/audio_effect_opus_chunked.cpp index 2266aba..5820b3c 100644 --- a/src/audio_effect_opus_chunked.cpp +++ b/src/audio_effect_opus_chunked.cpp @@ -495,7 +495,7 @@ float AudioEffectOpusChunked::denoise_single_chunk(float* pdenoisedaudioresample } } } else { - godot::UtilityFunctions::prints("Warning: noise framesize", rnnoiseframesize, "does not divide opusframesize", opusframesize); + godot::UtilityFunctions::printerr("Warning: noise framesize", rnnoiseframesize, "does not divide opusframesize", opusframesize); for (int i = 0; i < opusframesize; i++) { pdenoisedaudioresamples[i*2] = paudiosamples[i*2]; pdenoisedaudioresamples[i*2 + 1] = paudiosamples[i*2 + 1]; @@ -509,12 +509,17 @@ PackedByteArray AudioEffectOpusChunked::opus_frame_to_opus_packet(const PackedBy unsigned char* popusbytes = opusbytebuffer.ptrw(); int nprefbytes = prefixbytes.size(); if (nprefbytes > MAXPREFIXBYTES) { - godot::UtilityFunctions::prints("Warning: prefixbytes too long"); + godot::UtilityFunctions::printerr("Error: prefixbytes longer than ", MAXPREFIXBYTES); nprefbytes = 0; + return PackedByteArray(); } if (nprefbytes != 0) { memcpy(popusbytes, prefixbytes.ptr(), nprefbytes); } + if (opusencoder == NULL) { + godot::UtilityFunctions::printerr("Error: opusencoder is null"); + return PackedByteArray(); + } int bytepacketsize = opus_encode_float(opusencoder, paudiosamples, opusframesize, popusbytes + nprefbytes, opusbytebuffer.size() - nprefbytes); return opusbytebuffer.slice(0, nprefbytes + bytepacketsize);