first commit

This commit is contained in:
pietru 2024-11-11 15:17:55 +01:00
commit 51c7cca0bf
10 changed files with 652 additions and 0 deletions

17
.gitignore vendored Normal file
View file

@ -0,0 +1,17 @@
records/
# Godot 4+ specific ignores
.godot/
# Godot-specific ignores
.import/
export.cfg
export_presets.cfg
# Imported translations (automatically generated from CSV files)
*.translation
# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

239
MicRecord.gd Normal file
View file

@ -0,0 +1,239 @@
extends Control
var effect: AudioEffectRecord
var recording: AudioStreamWAV
var stereo := true
var mix_rate := 44100 # This is the default mix rate on recordings.
var format := AudioStreamWAV.FORMAT_16_BITS # This is the default format on recordings.
# 2147483647
var noise_max_lvl := 2000000#10000000
func _ready() -> void:
var idx := AudioServer.get_bus_index("Record")
effect = AudioServer.get_bus_effect(idx, 2)
%Controls.visible=false
#region Record stuff
func _on_load_words_pressed() -> void:
if not FileAccess.file_exists(%SavePath.text.path_join("list.json")):
return
var txt = FileAccess.get_file_as_string(%SavePath.text.path_join("list.json"))
words=JSON.parse_string(txt)
for t in words:
%WordList.add_item(t)
func save_words():
var fl = FileAccess.open(%SavePath.text.path_join("list.json"),FileAccess.WRITE)
var txt = JSON.stringify(words,"\t")
fl.store_string(txt)
fl.close()
func _process(delta: float) -> void:
if Input.is_action_just_pressed("ui_right"):
if last_item_index!=null:
run_swap_code(last_item_index+1)
if Input.is_action_just_pressed("ui_left"):
if last_item_index!=null:
run_swap_code(last_item_index-1)
func run_swap_code(new_index):
if effect.is_recording_active():
start_new_record()
await get_tree().process_frame
_on_save_button_pressed()
if words.size()<=new_index:
new_index=0
if 0>new_index:
new_index=words.size()-1
%WordList.select(new_index)
%WordList.ensure_current_is_visible()
_on_item_list_item_selected(new_index)
var words :Array= []
func _on_add_word_btn_pressed() -> void:
if (%SoundName.text=="" or words.has(%SoundName.text)):
return
%WordList.add_item(%SoundName.text)
words.append(%SoundName.text)
%SoundName.text=""
save_words()
var last_item_index :int = -1
var last_item_text := ""
var last_item_path := ""
func _on_item_list_item_selected(index: int) -> void:
%Controls.visible=true
last_item_text=%WordList.get_item_text(index)
%WordName.text=last_item_text
last_item_index=index
last_item_path=%SavePath.text
last_item_path=last_item_path.path_join(last_item_text+".wav")
if FileAccess.file_exists(last_item_path):
recording=load(last_item_path)
func _on_record_button_pressed() -> void:
if effect.is_recording_active():
recording = effect.get_recording()
%PlayButton.disabled = false
%SaveButton.disabled = false
effect.set_recording_active(false)
recording.set_mix_rate(mix_rate)
recording.set_format(format)
recording.set_stereo(stereo)
remove_noise()
%RecordButton.text = "Record"
%Status.text = ""
else:
%PlayButton.disabled = true
%SaveButton.disabled = true
effect.set_recording_active(true)
%RecordButton.text = "Stop"
%Status.text = "Status: Recording..."
func start_new_record():
recording = effect.get_recording()
%PlayButton.disabled = false
%SaveButton.disabled = false
if recording!=null:
effect.set_recording_active(false)
recording.set_mix_rate(mix_rate)
recording.set_format(format)
recording.set_stereo(stereo)
remove_noise()
await get_tree().process_frame
effect.set_recording_active(true)
func remove_noise():
return
#var data := recording.data.to_int32_array()
#var new_data := PackedInt32Array()
#
#var offset = 0
#var uc
#for i in data:
#if i < noise_max_lvl:
#i=0
#new_data.append(i)
#recording.data=new_data.to_byte_array()
func _on_play_button_pressed() -> void:
print_rich("\n[b]Playing recording:[/b] %s" % recording)
print_rich("[b]Format:[/b] %s" % ("8-bit uncompressed" if recording.format == 0 else "16-bit uncompressed" if recording.format == 1 else "IMA ADPCM compressed"))
print_rich("[b]Mix rate:[/b] %s Hz" % recording.mix_rate)
print_rich("[b]Stereo:[/b] %s" % ("Yes" if recording.stereo else "No"))
var data := recording.get_data()
print_rich("[b]Size:[/b] %s bytes" % data.size())
$AudioStreamPlayer.stream = recording
$AudioStreamPlayer.play()
func _on_save_button_pressed() -> void:
if recording==null:
return
if not DirAccess.dir_exists_absolute(%SavePath.text):
DirAccess.make_dir_absolute(%SavePath.text)
if FileAccess.file_exists(last_item_path):
DirAccess.remove_absolute(last_item_path)
recording.save_to_wav(last_item_path)
%Status.text = "Status: Saved WAV file to: %s" % [last_item_text+".wav"]
func _on_delete_button_pressed() -> void:
if (last_item_index==null):
return
if DirAccess.dir_exists_absolute(%SavePath.text) and FileAccess.file_exists(last_item_path):
DirAccess.remove_absolute(last_item_path)
words.erase(last_item_text)
last_item_index=-1
last_item_text=""
last_item_path=""
%Controls.visible=false
save_words()
#endregion
#region PlanText stuff
func _on_load_text_btn_pressed() -> void:
if not FileAccess.file_exists(%WordsTXTPath.text):
return
var txt = FileAccess.get_file_as_string(%WordsTXTPath.text)
%TextWordsEdit.text=txt
func _on_add_words_btn_pressed() -> void:
var txt :String= %TextWordsEdit.text
txt=txt.replace("\n"," ").replace("\t"," ")
var wrds = txt.split(" ",false)
for wrd in wrds:
if !words.has(wrd):
%WordList.add_item(wrd)
words.append(wrd)
var play = false
func _on_play_text_btn_pressed() -> void:
play=!play
if play:
var txt :String= %TextWordsEdit.text
txt=txt.replace("\n"," ").replace("\t"," ")
var wrds = txt.split(" ",false)
for wrd in wrds:
var path = %SavePath.text.path_join(wrd+".wav")
if FileAccess.file_exists(path):
var stream = load(path)
$AudioStreamPlayer2.stream = stream
$AudioStreamPlayer2.play()
await $AudioStreamPlayer2.finished
play=false
else:
$AudioStreamPlayer2.stop()
#endregion
#region Aditional stuff
func _on_mix_rate_option_button_item_selected(index: int) -> void:
match index:
0:
mix_rate = 11025
1:
mix_rate = 16000
2:
mix_rate = 22050
3:
mix_rate = 32000
4:
mix_rate = 44100
5:
mix_rate = 48000
if recording != null:
recording.set_mix_rate(mix_rate)
func _on_format_option_button_item_selected(index: int) -> void:
match index:
0:
format = AudioStreamWAV.FORMAT_8_BITS
1:
format = AudioStreamWAV.FORMAT_16_BITS
2:
format = AudioStreamWAV.FORMAT_IMA_ADPCM
if recording != null:
recording.set_format(format)
func _on_stereo_check_button_toggled(button_pressed: bool) -> void:
stereo = button_pressed
if recording != null:
recording.set_stereo(stereo)
func _on_open_user_folder_button_pressed() -> void:
OS.shell_open(ProjectSettings.globalize_path(%SavePath.text))
#endregion

301
MicRecord.tscn Normal file
View file

@ -0,0 +1,301 @@
[gd_scene load_steps=4 format=3 uid="uid://dvjlkpjvjxn0h"]
[ext_resource type="Script" path="res://MicRecord.gd" id="1"]
[sub_resource type="AudioStreamMicrophone" id="1"]
[sub_resource type="LabelSettings" id="LabelSettings_7vfcs"]
font_size = 64
[node name="Scene" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1")
[node name="AudioStreamRecord" type="AudioStreamPlayer" parent="."]
stream = SubResource("1")
autoplay = true
bus = &"Record"
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
[node name="AudioStreamPlayer2" type="AudioStreamPlayer" parent="."]
[node name="TabContainer" type="TabContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
current_tab = 1
[node name="Record" type="VBoxContainer" parent="TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 0
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Record"]
layout_mode = 2
[node name="Status" type="Label" parent="TabContainer/Record/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
horizontal_alignment = 1
[node name="VSeparator" type="VSeparator" parent="TabContainer/Record/HBoxContainer"]
self_modulate = Color(1, 1, 1, 0)
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
[node name="FormatLabel" type="Label" parent="TabContainer/Record/HBoxContainer"]
layout_mode = 2
text = "Format:"
[node name="FormatOptionButton" type="OptionButton" parent="TabContainer/Record/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
selected = 1
item_count = 3
popup/item_0/text = "8-bit Uncompressed"
popup/item_1/text = "16-bit Uncompressed"
popup/item_1/id = 1
popup/item_2/text = "IMA ADPCM Compression"
popup/item_2/id = 2
[node name="VSeparator2" type="VSeparator" parent="TabContainer/Record/HBoxContainer"]
self_modulate = Color(1, 1, 1, 0)
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
[node name="MixRateLabel" type="Label" parent="TabContainer/Record/HBoxContainer"]
layout_mode = 2
text = "Mix rate:"
[node name="MixRateOptionButton" type="OptionButton" parent="TabContainer/Record/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
selected = 4
item_count = 6
popup/item_0/text = "11025 Hz"
popup/item_1/text = "16000 Hz"
popup/item_1/id = 1
popup/item_2/text = "22050 Hz"
popup/item_2/id = 2
popup/item_3/text = "32000 Hz"
popup/item_3/id = 3
popup/item_4/text = "44100 Hz"
popup/item_4/id = 4
popup/item_5/text = "48000 Hz"
popup/item_5/id = 5
[node name="VSeparator3" type="VSeparator" parent="TabContainer/Record/HBoxContainer"]
self_modulate = Color(1, 1, 1, 0)
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
[node name="StereoLabel" type="Label" parent="TabContainer/Record/HBoxContainer"]
layout_mode = 2
text = "Stereo:"
[node name="StereoCheckButton" type="CheckButton" parent="TabContainer/Record/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
button_pressed = true
[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Record"]
layout_mode = 2
[node name="Label" type="Label" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "World: "
horizontal_alignment = 2
vertical_alignment = 1
[node name="SoundName" type="LineEdit" parent="TabContainer/Record/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
caret_blink = true
[node name="AddWordBTN" type="Button" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Add Word"
[node name="VSeparator" type="VSeparator" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
[node name="VSeparator2" type="VSeparator" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
[node name="LoadWords" type="Button" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Load Words"
[node name="Label2" type="Label" parent="TabContainer/Record/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Save Folder Path: "
horizontal_alignment = 2
vertical_alignment = 1
[node name="SavePath" type="LineEdit" parent="TabContainer/Record/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "res://records"
caret_blink = true
[node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/Record"]
layout_mode = 2
size_flags_vertical = 3
[node name="WordList" type="ItemList" parent="TabContainer/Record/HBoxContainer3"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.5
[node name="Controls" type="VBoxContainer" parent="TabContainer/Record/HBoxContainer3"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 2.0
[node name="WordName" type="Label" parent="TabContainer/Record/HBoxContainer3/Controls"]
unique_name_in_owner = true
layout_mode = 2
text = "<=="
label_settings = SubResource("LabelSettings_7vfcs")
horizontal_alignment = 1
vertical_alignment = 1
[node name="HSeparator" type="HSeparator" parent="TabContainer/Record/HBoxContainer3/Controls"]
self_modulate = Color(1, 1, 1, 0)
custom_minimum_size = Vector2(0, 40)
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Record/HBoxContainer3/Controls"]
layout_mode = 2
alignment = 1
[node name="RecordButton" type="Button" parent="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Record"
[node name="PlayButton" type="Button" parent="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
disabled = true
text = "Play"
[node name="SaveButton" type="Button" parent="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
disabled = true
text = "Save"
[node name="OpenUserFolderButton" type="Button" parent="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer"]
layout_mode = 2
text = "Open User Folder"
[node name="HSeparator2" type="HSeparator" parent="TabContainer/Record/HBoxContainer3/Controls"]
self_modulate = Color(1, 1, 1, 0)
custom_minimum_size = Vector2(0, 40)
layout_mode = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Record/HBoxContainer3/Controls"]
layout_mode = 2
alignment = 2
[node name="DeleteButton" type="Button" parent="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer2"]
layout_mode = 2
text = "Delete"
[node name="PlanText" type="VBoxContainer" parent="TabContainer"]
layout_mode = 2
metadata/_tab_index = 1
[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/PlanText"]
layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="TabContainer/PlanText/HBoxContainer2"]
self_modulate = Color(1, 1, 1, 0)
layout_mode = 2
size_flags_horizontal = 3
[node name="PlayTextBTN" type="Button" parent="TabContainer/PlanText/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Play Text"
[node name="VSeparator2" type="VSeparator" parent="TabContainer/PlanText/HBoxContainer2"]
self_modulate = Color(1, 1, 1, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.7
[node name="AddWordsBTN" type="Button" parent="TabContainer/PlanText/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Add Words"
[node name="LoadTextBTN" type="Button" parent="TabContainer/PlanText/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Load Text"
[node name="Label2" type="Label" parent="TabContainer/PlanText/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Text File Path: "
horizontal_alignment = 2
vertical_alignment = 1
[node name="WordsTXTPath" type="LineEdit" parent="TabContainer/PlanText/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 1.5
text = "res://records/phrases.txt"
caret_blink = true
[node name="VSeparator3" type="VSeparator" parent="TabContainer/PlanText/HBoxContainer2"]
self_modulate = Color(1, 1, 1, 0)
layout_mode = 2
size_flags_horizontal = 3
[node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/PlanText"]
layout_mode = 2
size_flags_vertical = 3
[node name="TextWordsEdit" type="TextEdit" parent="TabContainer/PlanText/HBoxContainer3"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Text to read load worlds"
[connection signal="item_selected" from="TabContainer/Record/HBoxContainer/FormatOptionButton" to="." method="_on_format_option_button_item_selected"]
[connection signal="item_selected" from="TabContainer/Record/HBoxContainer/MixRateOptionButton" to="." method="_on_mix_rate_option_button_item_selected"]
[connection signal="toggled" from="TabContainer/Record/HBoxContainer/StereoCheckButton" to="." method="_on_stereo_check_button_toggled"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer2/AddWordBTN" to="." method="_on_add_word_btn_pressed"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer2/LoadWords" to="." method="_on_load_words_pressed"]
[connection signal="item_selected" from="TabContainer/Record/HBoxContainer3/WordList" to="." method="_on_item_list_item_selected"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer/RecordButton" to="." method="_on_record_button_pressed"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer/PlayButton" to="." method="_on_play_button_pressed"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer/SaveButton" to="." method="_on_save_button_pressed"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer/OpenUserFolderButton" to="." method="_on_open_user_folder_button_pressed"]
[connection signal="pressed" from="TabContainer/Record/HBoxContainer3/Controls/HBoxContainer2/DeleteButton" to="." method="_on_delete_button_pressed"]
[connection signal="pressed" from="TabContainer/PlanText/HBoxContainer2/PlayTextBTN" to="." method="_on_play_text_btn_pressed"]
[connection signal="pressed" from="TabContainer/PlanText/HBoxContainer2/AddWordsBTN" to="." method="_on_add_words_btn_pressed"]
[connection signal="pressed" from="TabContainer/PlanText/HBoxContainer2/LoadTextBTN" to="." method="_on_load_text_btn_pressed"]

0
README.md Normal file
View file

26
default_bus_layout.tres Normal file
View file

@ -0,0 +1,26 @@
[gd_resource type="AudioBusLayout" load_steps=4 format=3 uid="uid://tuxl6tvrr2dv"]
[sub_resource type="AudioEffectFilter" id="AudioEffectFilter_081mb"]
resource_name = "Filter"
gain = 4.0
[sub_resource type="AudioEffectPitchShift" id="AudioEffectPitchShift_r6ahm"]
resource_name = "PitchShift"
pitch_scale = 0.85
[sub_resource type="AudioEffectRecord" id="AudioEffectRecord_fo272"]
resource_name = "Record"
[resource]
bus/1/name = &"Record"
bus/1/solo = false
bus/1/mute = true
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/1/effect/0/effect = SubResource("AudioEffectFilter_081mb")
bus/1/effect/0/enabled = true
bus/1/effect/1/effect = SubResource("AudioEffectPitchShift_r6ahm")
bus/1/effect/1/enabled = true
bus/1/effect/2/effect = SubResource("AudioEffectRecord_fo272")
bus/1/effect/2/enabled = true

BIN
icon.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

34
icon.webp.import Normal file
View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://brwp8bimc75uu"
path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.webp"
dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

35
project.godot Normal file
View file

@ -0,0 +1,35 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Announcer Recorder Helper"
config/description="Based on record audio demo.
Helps record words for black mesa like announcer system."
config/tags=PackedStringArray("audio", "gui", "tool")
run/main_scene="res://MicRecord.tscn"
config/features=PackedStringArray("4.3")
run/low_processor_mode=true
config/icon="res://icon.webp"
[audio]
driver/enable_input=true
enable_audio_input=true
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
window/vsync/vsync_mode=0

0
screenshots/.gdignore Normal file
View file

BIN
screenshots/mic_record.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB