Skip to main content

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 indoor_ambience_enabled: bool,
101    pub num_sfx_channels: usize,
102    pub num_ui_channels: usize,
103    pub music_spacing: f32,
104    pub subtitles: bool,
105    pub combat_music_enabled: bool,
106    /// The size of the sample buffer Kira uses. Increasing this may improve
107    /// audio performance at the cost of audio latency.
108    /// This is a versioned setting, so change the default value above and then
109    /// increment the second element to force reset it.
110    #[serde(default)]
111    pub buffer_size: Versioned<BufferSize, 1>,
112    /// Set to None to use the default samplerate determined by the game;
113    /// otherwise, use Some(samplerate); the game will attempt to force
114    /// samplerate to this.
115    pub sample_rate: Option<u32>,
116
117    /// Audio Device that Voxygen will use to play audio.
118    pub output: AudioOutput,
119}
120
121impl Default for AudioSettings {
122    fn default() -> Self {
123        Self {
124            master_volume: AudioVolume::new(0.8, false),
125            inactive_master_volume_perc: AudioVolume::new(0.5, false),
126            music_volume: AudioVolume::new(0.5, false),
127            sfx_volume: AudioVolume::new(0.8, false),
128            ambience_volume: AudioVolume::new(0.8, false),
129            num_sfx_channels: 32,
130            rain_ambience_enabled: true,
131            indoor_ambience_enabled: true,
132            num_ui_channels: 16,
133            music_spacing: 1.0,
134            subtitles: false,
135            output: AudioOutput::Automatic,
136            combat_music_enabled: false,
137            buffer_size: Versioned(BufferSize::default()),
138            sample_rate: None,
139        }
140    }
141}