veloren_voxygen/settings/
audio.rs

1use std::{fmt::Debug, ops::Deref};
2use tracing::warn;
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, Serialize, Deserialize)]
7pub enum AudioOutput {
8    /// Veloren's audio system wont work on some systems,
9    /// so you can use this to disable it, and allow the
10    /// game to function
11    // If this option is disabled, functions in the rodio
12    // library MUST NOT be called.
13    Off,
14    #[serde(other)]
15    Automatic,
16}
17
18impl AudioOutput {
19    pub fn is_enabled(&self) -> bool { !matches!(self, Self::Off) }
20}
21
22#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
23pub struct AudioVolume {
24    pub volume: f32,
25    pub muted: bool,
26}
27
28impl AudioVolume {
29    pub fn new(volume: f32, muted: bool) -> Self { Self { volume, muted } }
30
31    pub fn get_checked(&self) -> f32 {
32        match self.muted {
33            true => 0.0,
34            false => self.volume,
35        }
36    }
37}
38
39/// A versioned setting field. If the current version does not match the version
40/// read, it resets the value to its default automatically and writes it to the
41/// file as well. Takes the form `Versioned<[type], [current version]>`.
42#[derive(Copy, Clone, Debug, Default)]
43pub struct Versioned<T, const CURRENT: usize>(pub T);
44
45impl<T: Serialize, const CURRENT: usize> Serialize for Versioned<T, CURRENT> {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: serde::Serializer,
49    {
50        (CURRENT, &self.0).serialize(serializer)
51    }
52}
53
54impl<'de, T: Deserialize<'de> + Default + Debug, const CURRENT: usize> Deserialize<'de>
55    for Versioned<T, CURRENT>
56{
57    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58    where
59        D: serde::Deserializer<'de>,
60    {
61        let deserialized = <(usize, T)>::deserialize(deserializer)?;
62        let old_ver = deserialized.0;
63        if old_ver != CURRENT {
64            let new = T::default();
65            warn!("New default setting detected (ver. {old_ver} -> {CURRENT}), setting to {new:?}",);
66            Ok(Versioned(new))
67        } else {
68            Ok(Versioned(deserialized.1))
69        }
70    }
71}
72
73impl<T, const CURRENT: usize> Deref for Versioned<T, CURRENT> {
74    type Target = T;
75
76    fn deref(&self) -> &Self::Target { &self.0 }
77}
78
79#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
80pub struct BufferSize {
81    pub samples: usize,
82}
83
84impl Default for BufferSize {
85    fn default() -> Self { Self { samples: 2048 } }
86}
87
88/// `AudioSettings` controls the volume of different audio subsystems and which
89/// device is used.
90#[derive(Clone, Debug, Serialize, Deserialize)]
91#[serde(default)]
92pub struct AudioSettings {
93    pub master_volume: AudioVolume,
94    #[serde(rename = "inactive_master_volume")]
95    pub inactive_master_volume_perc: AudioVolume,
96    pub music_volume: AudioVolume,
97    pub sfx_volume: AudioVolume,
98    pub ambience_volume: AudioVolume,
99    pub rain_ambience_enabled: bool,
100    pub num_sfx_channels: usize,
101    pub num_ui_channels: usize,
102    pub music_spacing: f32,
103    pub subtitles: bool,
104    pub combat_music_enabled: bool,
105    /// The size of the sample buffer Kira uses. Increasing this may improve
106    /// audio performance at the cost of audio latency.
107    /// This is a versioned setting, so change the default value above and then
108    /// increment the second element to force reset it.
109    #[serde(default)]
110    pub buffer_size: Versioned<BufferSize, 1>,
111    /// Set to None to use the default samplerate determined by the game;
112    /// otherwise, use Some(samplerate); the game will attempt to force
113    /// samplerate to this.
114    pub sample_rate: Option<u32>,
115
116    /// Audio Device that Voxygen will use to play audio.
117    pub output: AudioOutput,
118}
119
120impl Default for AudioSettings {
121    fn default() -> Self {
122        Self {
123            master_volume: AudioVolume::new(0.8, false),
124            inactive_master_volume_perc: AudioVolume::new(0.5, false),
125            music_volume: AudioVolume::new(0.5, false),
126            sfx_volume: AudioVolume::new(0.8, false),
127            ambience_volume: AudioVolume::new(0.8, false),
128            num_sfx_channels: 32,
129            rain_ambience_enabled: true,
130            num_ui_channels: 16,
131            music_spacing: 1.0,
132            subtitles: false,
133            output: AudioOutput::Automatic,
134            combat_music_enabled: false,
135            buffer_size: Versioned(BufferSize::default()),
136            sample_rate: None,
137        }
138    }
139}