diff --git a/icon.svg b/icon.svg
new file mode 100644
index 0000000..b370ceb
--- /dev/null
+++ b/icon.svg
@@ -0,0 +1 @@
+
diff --git a/icon.svg.import b/icon.svg.import
new file mode 100644
index 0000000..4b0198f
--- /dev/null
+++ b/icon.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dlbbl7reybbvh"
+path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.svg"
+dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/icons/mic_active.svg b/icons/mic_active.svg
new file mode 100644
index 0000000..aeffaf3
--- /dev/null
+++ b/icons/mic_active.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icons/mic_active.svg.import b/icons/mic_active.svg.import
new file mode 100644
index 0000000..727fb74
--- /dev/null
+++ b/icons/mic_active.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c2slehdr0kxo4"
+path="res://.godot/imported/mic_active.svg-18499b0b78a23d9ea53aa3a320fe1e2c.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icons/mic_active.svg"
+dest_files=["res://.godot/imported/mic_active.svg-18499b0b78a23d9ea53aa3a320fe1e2c.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/icons/mic_inactive.svg b/icons/mic_inactive.svg
new file mode 100644
index 0000000..43fe584
--- /dev/null
+++ b/icons/mic_inactive.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icons/mic_inactive.svg.import b/icons/mic_inactive.svg.import
new file mode 100644
index 0000000..d26babe
--- /dev/null
+++ b/icons/mic_inactive.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d1pmeyg5jhptu"
+path="res://.godot/imported/mic_inactive.svg-d6a42ee2c060cb2d9b17cec264926886.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icons/mic_inactive.svg"
+dest_files=["res://.godot/imported/mic_inactive.svg-d6a42ee2c060cb2d9b17cec264926886.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/project.godot b/project.godot
new file mode 100644
index 0000000..9490d2b
--- /dev/null
+++ b/project.godot
@@ -0,0 +1,25 @@
+; 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="VoIP"
+run/main_scene="res://ui/main_menu/main_menu.tscn"
+config/features=PackedStringArray("4.2", "Forward Plus")
+config/icon="res://icon.svg"
+
+[audio]
+
+buses/default_bus_layout="res://voip_setup.tres"
+driver/enable_input=true
+
+[dotnet]
+
+project/assembly_name="VoIP"
diff --git a/ui/main_menu/main_menu.tscn b/ui/main_menu/main_menu.tscn
new file mode 100644
index 0000000..4e65949
--- /dev/null
+++ b/ui/main_menu/main_menu.tscn
@@ -0,0 +1,47 @@
+[gd_scene load_steps=2 format=3 uid="uid://nw148tplcq6w"]
+
+[ext_resource type="Script" path="res://ui/main_menu/scripts/main_menu.gd" id="1_bwmj7"]
+
+[node name="MainMenu" 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_bwmj7")
+
+[node name="MarginContainer" type="MarginContainer" parent="."]
+layout_mode = 1
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+offset_left = -20.0
+offset_top = -20.0
+offset_right = 20.0
+offset_bottom = 20.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
+layout_mode = 2
+
+[node name="HostIP" type="LineEdit" parent="MarginContainer/VBoxContainer"]
+layout_mode = 2
+placeholder_text = "Host IP"
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="HostGame" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+text = "Host Game"
+
+[node name="JoinGame" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+text = "Join Game"
+
+[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/HostGame" to="." method="_on_host_game_pressed"]
+[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/JoinGame" to="." method="_on_join_game_pressed"]
diff --git a/ui/main_menu/scripts/main_menu.gd b/ui/main_menu/scripts/main_menu.gd
new file mode 100644
index 0000000..b0c61b2
--- /dev/null
+++ b/ui/main_menu/scripts/main_menu.gd
@@ -0,0 +1,98 @@
+extends Control
+
+#region Signals
+
+signal player_connected(peer_id, player_info)
+signal player_disconnected(peer_id)
+signal server_disconnected
+
+#endregion
+
+@onready var host_ip: LineEdit = $MarginContainer/VBoxContainer/HostIP
+const PORT: int = 7000
+const DEFAULT_SERVER_IP: String = "127.0.0.1"
+const MAX_CONNECTIONS: int = 20
+
+var players = {}
+
+var player_info = {"name": "Name"}
+var players_loaded: int = 0
+
+func _ready():
+ multiplayer.peer_connected.connect(_on_player_connected)
+ multiplayer.peer_disconnected.connect(_on_player_disconnected)
+ multiplayer.connected_to_server.connect(_on_connected_ok)
+ multiplayer.connection_failed.connect(_on_connected_fail)
+ multiplayer.server_disconnected.connect(_on_server_disconnected)
+
+func _on_host_game_pressed():
+ var peer = ENetMultiplayerPeer.new()
+ var error = peer.create_server(PORT, MAX_CONNECTIONS)
+ if error:
+ return error
+ multiplayer.multiplayer_peer = peer
+
+ players[1] = player_info
+ player_connected.emit(1, player_info)
+ load_game.rpc_id(1, "res://ui/main_scene/main_scene.tscn")
+
+func _on_join_game_pressed():
+ var address: String = host_ip.text
+ if address.is_empty():
+ address = DEFAULT_SERVER_IP
+ var peer = ENetMultiplayerPeer.new()
+ var error = peer.create_client(address, PORT)
+ if error:
+ return error
+ multiplayer.multiplayer_peer = peer
+
+func remove_multiplayer_peer():
+ multiplayer.multiplayer_peer = null
+
+#region Events
+
+@rpc("call_local", "reliable")
+func load_game(game_scene_path):
+ get_tree().change_scene_to_file(game_scene_path)
+
+@rpc("any_peer", "call_local", "reliable")
+func player_loaded():
+ if multiplayer.is_server():
+ players_loaded += 1
+ if players_loaded == players.size():
+ players_loaded = 0
+
+@rpc("any_peer", "reliable")
+func _register_player(new_player_info):
+ var new_player_id = multiplayer.get_remote_sender_id()
+ players[new_player_id] = new_player_info
+ player_connected.emit(new_player_id, new_player_info)
+
+#region Multiplayer Signal Handlers
+
+func _on_player_connected(id):
+ _register_player.rpc_id(id, player_info)
+
+func _on_player_disconnected(id):
+ players.erase(id)
+ player_disconnected.emit(id)
+
+func _on_connected_ok():
+ var peer_id = multiplayer.get_unique_id()
+ players[peer_id] = player_info
+ print("Connected: ", peer_id, " ", players[peer_id])
+ player_connected.emit(peer_id, player_info)
+
+ load_game.rpc_id(peer_id, "res://ui/main_scene/main_scene.tscn")
+
+func _on_connected_fail():
+ multiplayer.multiplayer_peer = null
+
+func _on_server_disconnected():
+ multiplayer.multiplayer_peer = null
+ players.clear()
+ server_disconnected.emit()
+
+#endregion
+
+#endregion
diff --git a/ui/main_scene/Microphone.gd b/ui/main_scene/Microphone.gd
new file mode 100644
index 0000000..56a06b0
--- /dev/null
+++ b/ui/main_scene/Microphone.gd
@@ -0,0 +1,25 @@
+extends AudioStreamPlayer
+
+var effect: AudioEffectCapture
+var recording
+var playback: AudioStreamGeneratorPlayback
+
+@onready var voip: AudioStreamPlayer = $"../VoIP"
+
+func _ready():
+ var idx = AudioServer.get_bus_index("Mic")
+ effect = AudioServer.get_bus_effect(idx, 0)
+
+ playback = voip.get_stream_playback()
+
+func _process(_delta):
+ var frames: PackedVector2Array
+
+ if effect.can_get_buffer(1024):
+ frames = effect.get_buffer(1024)
+ playback_voip.rpc(frames)
+
+
+@rpc("any_peer", "call_remote", "unreliable_ordered", 1)
+func playback_voip(frames: PackedVector2Array):
+ playback.push_buffer(frames)
diff --git a/ui/main_scene/main_scene.tscn b/ui/main_scene/main_scene.tscn
new file mode 100644
index 0000000..3db55e8
--- /dev/null
+++ b/ui/main_scene/main_scene.tscn
@@ -0,0 +1,116 @@
+[gd_scene load_steps=7 format=3 uid="uid://dvy8ub5r3mnjc"]
+
+[ext_resource type="Script" path="res://ui/main_scene/Microphone.gd" id="2_h65el"]
+
+[sub_resource type="SystemFont" id="SystemFont_dukv4"]
+font_names = PackedStringArray("JetBrains Mono NL")
+font_weight = 425
+
+[sub_resource type="LabelSettings" id="LabelSettings_jutwa"]
+font = SubResource("SystemFont_dukv4")
+
+[sub_resource type="LabelSettings" id="LabelSettings_bt5o0"]
+font_size = 11
+
+[sub_resource type="AudioStreamMicrophone" id="AudioStreamMicrophone_1rv7u"]
+
+[sub_resource type="AudioStreamGenerator" id="AudioStreamGenerator_a1tib"]
+
+[node name="MainScene" type="Control"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="MarginContainer" type="MarginContainer" parent="."]
+layout_mode = 1
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+offset_left = -20.0
+offset_top = -20.0
+offset_right = 20.0
+offset_bottom = 20.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
+custom_minimum_size = Vector2(400, 0)
+layout_mode = 2
+text = "Your Client is Now sending your microphone input over the network
+ to all other clients connected to the server."
+label_settings = SubResource("LabelSettings_jutwa")
+horizontal_alignment = 1
+vertical_alignment = 1
+autowrap_mode = 2
+
+[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer"]
+custom_minimum_size = Vector2(400, 0)
+layout_mode = 2
+text = "Note: I'm 99% sure this demo would get buggy with more than one client connected to the server since there is only one VoIP Playback. To solve this just spawn one per client."
+label_settings = SubResource("LabelSettings_bt5o0")
+horizontal_alignment = 1
+vertical_alignment = 1
+autowrap_mode = 2
+
+[node name="MarginContainer2" type="MarginContainer" parent="."]
+layout_mode = 1
+anchors_preset = 12
+anchor_top = 1.0
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 0
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer2"]
+custom_minimum_size = Vector2(0, 50)
+layout_mode = 2
+alignment = 1
+
+[node name="LinkButton" type="LinkButton" parent="MarginContainer2/HBoxContainer"]
+layout_mode = 2
+text = "YouTube"
+underline = 2
+uri = "https://youtube.com/@4musedtv"
+
+[node name="Control2" type="Control" parent="MarginContainer2/HBoxContainer"]
+custom_minimum_size = Vector2(30, 0)
+layout_mode = 2
+
+[node name="LinkButton2" type="LinkButton" parent="MarginContainer2/HBoxContainer"]
+layout_mode = 2
+text = "Twitter"
+underline = 2
+uri = "https://twitter.com/4musedWasTaken"
+
+[node name="Control" type="Control" parent="MarginContainer2/HBoxContainer"]
+custom_minimum_size = Vector2(30, 0)
+layout_mode = 2
+
+[node name="LinkButton3" type="LinkButton" parent="MarginContainer2/HBoxContainer"]
+layout_mode = 2
+text = "Twitch"
+underline = 2
+uri = "https://twitch.tv/4musedtv"
+
+[node name="Microphone" type="AudioStreamPlayer" parent="."]
+stream = SubResource("AudioStreamMicrophone_1rv7u")
+autoplay = true
+bus = &"Mic"
+script = ExtResource("2_h65el")
+
+[node name="VoIP" type="AudioStreamPlayer" parent="."]
+stream = SubResource("AudioStreamGenerator_a1tib")
+autoplay = true
+
+[node name="AudioListener3D" type="AudioListener3D" parent="."]
diff --git a/voip_setup.tres b/voip_setup.tres
new file mode 100644
index 0000000..6a63486
--- /dev/null
+++ b/voip_setup.tres
@@ -0,0 +1,20 @@
+[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://dr43jvdvgkbuo"]
+
+[sub_resource type="AudioEffectCapture" id="AudioEffectCapture_pihug"]
+resource_name = "Capture"
+
+[resource]
+bus/1/name = &"MicSink"
+bus/1/solo = false
+bus/1/mute = true
+bus/1/bypass_fx = false
+bus/1/volume_db = 0.0
+bus/1/send = &"Master"
+bus/2/name = &"Mic"
+bus/2/solo = false
+bus/2/mute = false
+bus/2/bypass_fx = false
+bus/2/volume_db = 0.0
+bus/2/send = &"MicSink"
+bus/2/effect/0/effect = SubResource("AudioEffectCapture_pihug")
+bus/2/effect/0/enabled = true