Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions C7/Audio/AudioLoader.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://d3ppdw6qcpc4k
138 changes: 138 additions & 0 deletions C7/Audio/AudioManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@

using System;
using C7Engine;
using Godot;
using Serilog;

[GlobalClass]
public partial class AudioManager : Node {
private ILogger log;

[Export] AudioStreamPlayer musicPlayer;
[Export] AudioStreamPlayer sfxAudioPlayer;
[Export] AudioStreamPlayer uiAudioPlayer;
[Export] AudioStreamPlayer ambienceAudioPlayer;

private PolyphonicAudioPlayer _polyMusicPlayer;
private PolyphonicAudioPlayer _polySfxAudioPlayer;
private PolyphonicAudioPlayer _polyUiAudioPlayer;
private PolyphonicAudioPlayer _polyAmbienceAudioPlayer;

private static string AudioSettingsSection = "audio";

public static string MusicBus = "Music";
public static string SfxAudioBus = "Sfx";
public static string UIAudioBus = "UI";
public static string AmbienceAudioBus = "Ambience";

private bool musicEnabled = true;
private bool sfxAudioEnabled = true;
private bool uiAudioEnabled = true;
private bool ambienceAudioEnabled = true;

public override void _Ready() {
log = LogManager.ForContext<AudioManager>();

musicEnabled = ConfigureVolume("musicVolume", MusicBus);
_polyMusicPlayer = new PolyphonicAudioPlayer(musicPlayer, 2);

sfxAudioEnabled = ConfigureVolume("sfxAudioVolume", SfxAudioBus);
_polySfxAudioPlayer = new PolyphonicAudioPlayer(sfxAudioPlayer, 32);

uiAudioEnabled = ConfigureVolume("uiAudioVolume", UIAudioBus);
_polyUiAudioPlayer = new PolyphonicAudioPlayer(uiAudioPlayer, 8);

ambienceAudioEnabled = ConfigureVolume("ambienceAudioVolume", AmbienceAudioBus);
_polyAmbienceAudioPlayer = new PolyphonicAudioPlayer(ambienceAudioPlayer, 8);
}

private bool ConfigureVolume(string volumeKey, string audioBus) {
try {
string volume = C7Settings.GetSettingValue(AudioSettingsSection, volumeKey);
float volumeDb = LogicalVolumeAsDecibel(volume, volumeKey);

if (volumeDb == float.MinValue) {
return false;
}

log.Debug("setting {volumeKey} to {volume}, which is {offset} decibel (offset)",
volumeKey, volume, volumeDb);

int busIndex = AudioServer.GetBusIndex(audioBus);
AudioServer.SetBusVolumeDb(busIndex, volumeDb);

return true;
} catch (ApplicationException ex) {
log.Error(ex, "could not configure {volumeKey}", volumeKey);
return false;
}
}

/**
* Godot uses a decibel offset volume system, described at https://docs.godotengine.org/en/stable/tutorials/audio/audio_buses.html
* This is what audio professionals would use, but is not intuitive to end users.
* In this system, a 6db difference halves or doubles the volume.
* Our users are probably more used to a 0% to 100% system.
* So this method converts between them.
*/
private float LogicalVolumeAsDecibel(string volume, string volumeKey) {
if (volume == null) {
//First run. Save the setting.
C7Settings.SetValue(AudioSettingsSection, volumeKey, "100");
C7Settings.SaveSettings();
return 0;
}
int userVolumeSetting = int.Parse(volume);
if (userVolumeSetting == 100) {
return 0;
} else if (userVolumeSetting == 0) {
return float.MinValue;
} else {
//Conversion math based on https://stackoverflow.com/a/37810295/3534605
return 20.0f * (float)(Math.Log10(userVolumeSetting / 100.0f));
}
}

// TODO: playlists, mixing, transitions
// See: https://www.youtube.com/watch?app=desktop&v=07Kyqqg31FI&t=346s

// TODO: polyphony via AudioStreamPolyphonic + AudioStreamPlaybackPolyphonic
// https://docs.godotengine.org/en/4.0/classes/class_audiostreampolyphonic.html

private long currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;

public void PlayMusic(string configKey) {
AudioStream stream = AudioLoader.Load(configKey);

if (stream == null)
return;

if (currentMusicId != AudioStreamPlaybackPolyphonic.InvalidId) {
_polyMusicPlayer.Stop(currentMusicId);
}

currentMusicId = _polyMusicPlayer.Play(stream);
}

public void StopMusic() {
_polyMusicPlayer.StopAll();
}

public void PlaySfxAudio(string configKey) {
var stream = AudioLoader.Load(configKey);
if (stream != null)
_polySfxAudioPlayer.Play(stream);
}

public void PlayUIAudio(string configKey) {
var stream = AudioLoader.Load(configKey);
if (stream != null)
_polyUiAudioPlayer.Play(stream);
}

public void PlayAmbienceAudio(string configKey) {
var stream = AudioLoader.Load(configKey);
if (stream != null)
_polyAmbienceAudioPlayer.Play(stream);
}
}
1 change: 1 addition & 0 deletions C7/Audio/AudioManager.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://eyk3k7dd7tcy
22 changes: 22 additions & 0 deletions C7/Audio/AudioManager.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[gd_scene load_steps=2 format=3 uid="uid://4hh28tdyqvfg"]

[ext_resource type="Script" uid="uid://eyk3k7dd7tcy" path="res://Audio/AudioManager.cs" id="1_l0aok"]

[node name="AudioManager" type="Node" node_paths=PackedStringArray("musicPlayer", "sfxAudioPlayer", "uiAudioPlayer", "ambienceAudioPlayer")]
script = ExtResource("1_l0aok")
musicPlayer = NodePath("MusicPlayer")
sfxAudioPlayer = NodePath("SfxAudioPlayer")
uiAudioPlayer = NodePath("UIAudioPlayer")
ambienceAudioPlayer = NodePath("AmbienceAudioPlayer")

[node name="MusicPlayer" type="AudioStreamPlayer" parent="."]
bus = &"Music"

[node name="SfxAudioPlayer" type="AudioStreamPlayer" parent="."]
bus = &"Sfx"

[node name="UIAudioPlayer" type="AudioStreamPlayer" parent="."]
bus = &"UI"

[node name="AmbienceAudioPlayer" type="AudioStreamPlayer" parent="."]
bus = &"Ambience"
31 changes: 31 additions & 0 deletions C7/Audio/PolyphonicAudioPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Godot;

public class PolyphonicAudioPlayer {
private readonly AudioStreamPlayer player;
private readonly AudioStreamPlaybackPolyphonic playback;

public PolyphonicAudioPlayer(AudioStreamPlayer player, int polyphony = 32) {
this.player = player;

player.Stream = new AudioStreamPolyphonic {
Polyphony = polyphony
};

player.Play();

playback = player.GetStreamPlayback()
as AudioStreamPlaybackPolyphonic;
}

public long Play(AudioStream stream) {
return playback.PlayStream(stream);
}

public void Stop(long id) {
playback.StopStream(id);
}

public void StopAll() {
player.Stop();
}
}
23 changes: 11 additions & 12 deletions C7/UIElements/MainMenu/MainMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ public partial class MainMenu : Node {
Civ3FileDialog LoadScenarioDialog;
[Export]
MenuButtonContainer ButtonContainer;
[Export]
AudioStreamPlayer player;

GlobalSingleton Global;
AudioManager AudioManager;

public override void _Ready() {
log = LogManager.ForContext<MainMenu>();
Expand All @@ -29,6 +28,8 @@ public override void _Ready() {

try {
DisplayTitleScreen();
AudioManager = GetNode<AudioManager>("/root/GlobalAudioManager");
PlayMusic();
} catch (Exception ex) {
log.Error(ex, "Could not set up the main menu");
}
Expand Down Expand Up @@ -148,16 +149,6 @@ public void _on_Exit_pressed() {
GetTree().Quit(); // no need to notify the scene tree
}

private void PlayButtonPressedSound() {
AudioStream stream = AudioLoader.Load("buttons.button_1");

if (stream == null)
return;

player.Stream = stream;
player.Play();
}

private void _on_SetCiv3Home_pressed() {
SetCiv3HomeDialog.Popup();
}
Expand All @@ -174,4 +165,12 @@ private void UseStandaloneModePressed() {
Global.ActivateGameMode(GamePaths.standalone);
DisplayTitleScreen();
}

private void PlayMusic() {
AudioManager.PlayMusic("menu.main_menu_1");
}

private void PlayButtonPressedSound() {
AudioManager.PlaySfxAudio("buttons.button_1");
Comment thread
ajhalme marked this conversation as resolved.
Outdated
}
}
62 changes: 0 additions & 62 deletions C7/UIElements/MainMenu/MainMenuMusicPlayer.cs

This file was deleted.

1 change: 0 additions & 1 deletion C7/UIElements/MainMenu/MainMenuMusicPlayer.cs.uid

This file was deleted.

8 changes: 2 additions & 6 deletions C7/UIElements/MainMenu/main_menu.tscn
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
[gd_scene load_steps=13 format=3 uid="uid://gnt0y3og7nk6"]
[gd_scene load_steps=12 format=3 uid="uid://gnt0y3og7nk6"]

[ext_resource type="Script" uid="uid://dgpuse88jc2hc" path="res://UIElements/MainMenu/MainMenu.cs" id="1_akneh"]
[ext_resource type="Texture2D" uid="uid://s55xvcaini8h" path="res://title-screen.png" id="2_erxyj"]
[ext_resource type="Script" uid="uid://ca14gkdccjfcg" path="res://UIElements/MainMenu/MenuButtonContainer.cs" id="3_t1nuq"]
[ext_resource type="FontFile" uid="uid://b1xkj8g82jbx5" path="res://Fonts/NotoSans-BoldItalic.ttf" id="3_x68dx"]
[ext_resource type="Texture2D" uid="uid://ovwv08a53d7k" path="res://title.png" id="4_brea7"]
[ext_resource type="Script" uid="uid://dauceqein40wj" path="res://UIElements/MainMenu/MainMenuMusicPlayer.cs" id="4_tqr50"]
[ext_resource type="PackedScene" uid="uid://bvncm1bgcii5e" path="res://UIElements/civ3_file_dialog.tscn" id="5_rw2g7"]

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_vbij8"]
Expand Down Expand Up @@ -204,17 +203,14 @@ offset_top = -48.0
grow_horizontal = 2
grow_vertical = 0
text = "OpenCiv3 0.3 \"Dutch 2\" © OpenCiv3 contributors
OpenCiv3 is not affiliated with civfanatics.com, Firaxis Games, BreakAway Games,
OpenCiv3 is not affiliated with civfanatics.com, Firaxis Games, BreakAway Games,
Hasbro Interactive, Infogrames Interactive, Atari Interactive, or Take-Two Interactive Software.
All trademarks are property of their respective owners."
label_settings = SubResource("LabelSettings_brea7")
horizontal_alignment = 1
vertical_alignment = 2
autowrap_mode = 3

[node name="MainMenuMusicPlayer" type="AudioStreamPlayer" parent="."]
script = ExtResource("4_tqr50")

[node name="SoundEffectPlayer" type="AudioStreamPlayer" parent="."]

[node name="SetCiv3HomeDialog" type="FileDialog" parent="."]
Expand Down
4 changes: 4 additions & 0 deletions C7/UIElements/NewGame/PlayerSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ private void PersistGameSettings(GameSetup gameSetup) {
}

private void StartGame() {
AudioManager audio = GetNode<AudioManager>("/root/GlobalAudioManager");
audio.StopMusic();
// TODO: switch to in-game playlist / music logic

GetTree().ChangeSceneToFile("res://C7Game.tscn");
}
}
27 changes: 27 additions & 0 deletions C7/default_bus_layout.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[gd_resource type="AudioBusLayout" format=3 uid="uid://cw11tyqth76rn"]

[resource]
bus/1/name = &"Music"
bus/1/solo = false
bus/1/mute = false
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/2/name = &"Sfx"
bus/2/solo = false
bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"
bus/3/name = &"UI"
bus/3/solo = false
bus/3/mute = false
bus/3/bypass_fx = false
bus/3/volume_db = 0.0
bus/3/send = &"Master"
bus/4/name = &"Ambience"
bus/4/solo = false
bus/4/mute = false
bus/4/bypass_fx = false
bus/4/volume_db = 0.0
bus/4/send = &"Master"
1 change: 1 addition & 0 deletions C7/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ config/icon="res://icon.png"

GlobalSingleton="*res://GlobalSingleton.cs"
LogManager="*res://LogManager.cs"
GlobalAudioManager="*res://Audio/AudioManager.tscn"

[display]

Expand Down
Loading