1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#include "AudioSettings.hxx"
19#include "Settings.hxx"
20
21namespace {
22 uInt32 lboundInt(int x, int defaultValue)
23 {
24 return x <= 0 ? defaultValue : x;
25 }
26
27 AudioSettings::Preset normalizedPreset(int numericPreset)
28 {
29 return (
30 numericPreset >= static_cast<int>(AudioSettings::Preset::custom) &&
31 numericPreset <= static_cast<int>(AudioSettings::Preset::ultraQualityMinimalLag)
32 ) ? static_cast<AudioSettings::Preset>(numericPreset) : AudioSettings::DEFAULT_PRESET;
33 }
34
35 AudioSettings::ResamplingQuality normalizeResamplingQuality(int numericResamplingQuality)
36 {
37 return (
38 numericResamplingQuality >= static_cast<int>(AudioSettings::ResamplingQuality::nearestNeightbour) &&
39 numericResamplingQuality <= static_cast<int>(AudioSettings::ResamplingQuality::lanczos_3)
40 ) ? static_cast<AudioSettings::ResamplingQuality>(numericResamplingQuality) : AudioSettings::DEFAULT_RESAMPLING_QUALITY;
41 }
42}
43
44// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45AudioSettings::AudioSettings(Settings& settings)
46 : mySettings(settings),
47 myIsPersistent(true)
48{
49 setPreset(normalizedPreset(mySettings.getInt(SETTING_PRESET)));
50}
51
52// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
53void AudioSettings::normalize(Settings& settings)
54{
55 int settingPreset = settings.getInt(SETTING_PRESET);
56 Preset preset = normalizedPreset(settingPreset);
57 if (static_cast<int>(preset) != settingPreset) settings.setValue(SETTING_PRESET, static_cast<int>(DEFAULT_PRESET));
58
59 switch (settings.getInt(SETTING_SAMPLE_RATE)) {
60 case 44100:
61 case 48000:
62 case 96000:
63 break;
64
65 default:
66 settings.setValue(SETTING_SAMPLE_RATE, DEFAULT_SAMPLE_RATE);
67 break;
68 }
69
70 switch (settings.getInt(SETTING_FRAGMENT_SIZE)) {
71 case 128:
72 case 256:
73 case 512:
74 case 1024:
75 case 2048:
76 case 4096:
77 break;
78
79 default:
80 settings.setValue(SETTING_FRAGMENT_SIZE, DEFAULT_FRAGMENT_SIZE);
81 break;
82 }
83
84 int settingBufferSize = settings.getInt(SETTING_BUFFER_SIZE);
85 if (settingBufferSize < 0 || settingBufferSize > MAX_BUFFER_SIZE) settings.setValue(SETTING_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
86
87 int settingHeadroom = settings.getInt(SETTING_HEADROOM);
88 if (settingHeadroom < 0 || settingHeadroom > MAX_HEADROOM) settings.setValue(SETTING_HEADROOM, DEFAULT_HEADROOM);
89
90 int settingResamplingQuality = settings.getInt(SETTING_RESAMPLING_QUALITY);
91 ResamplingQuality resamplingQuality = normalizeResamplingQuality(settingResamplingQuality);
92 if (static_cast<int>(resamplingQuality) != settingResamplingQuality)
93 settings.setValue(SETTING_RESAMPLING_QUALITY, static_cast<int>(DEFAULT_RESAMPLING_QUALITY));
94
95 int settingVolume = settings.getInt(SETTING_VOLUME);
96 if (settingVolume < 0 || settingVolume > 100) settings.setValue(SETTING_VOLUME, DEFAULT_VOLUME);
97}
98
99// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100AudioSettings::Preset AudioSettings::preset()
101{
102 updatePresetFromSettings();
103 return myPreset;
104}
105
106// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107uInt32 AudioSettings::sampleRate()
108{
109 updatePresetFromSettings();
110 return customSettings() ? lboundInt(mySettings.getInt(SETTING_SAMPLE_RATE), DEFAULT_SAMPLE_RATE) : myPresetSampleRate;
111}
112
113// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114uInt32 AudioSettings::fragmentSize()
115{
116 updatePresetFromSettings();
117 return customSettings() ? lboundInt(mySettings.getInt(SETTING_FRAGMENT_SIZE), DEFAULT_FRAGMENT_SIZE) : myPresetFragmentSize;
118}
119
120// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121uInt32 AudioSettings::bufferSize()
122{
123 updatePresetFromSettings();
124 // 0 is a valid value -> keep it
125 return customSettings() ? lboundInt(mySettings.getInt(SETTING_BUFFER_SIZE), 0) : myPresetBufferSize;
126}
127
128// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129uInt32 AudioSettings::headroom()
130{
131 updatePresetFromSettings();
132 // 0 is a valid value -> keep it
133 return customSettings() ? lboundInt(mySettings.getInt(SETTING_HEADROOM), 0) : myPresetHeadroom;
134}
135
136// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137AudioSettings::ResamplingQuality AudioSettings::resamplingQuality()
138{
139 updatePresetFromSettings();
140 return customSettings() ? normalizeResamplingQuality(mySettings.getInt(SETTING_RESAMPLING_QUALITY)) : myPresetResamplingQuality;
141}
142
143// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144bool AudioSettings::stereo() const
145{
146 // 0 is a valid value -> keep it
147 return mySettings.getBool(SETTING_STEREO);
148}
149
150// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151uInt32 AudioSettings::volume() const
152{
153 // 0 is a valid value -> keep it
154 return lboundInt(mySettings.getInt(SETTING_VOLUME), 0);
155}
156
157// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158bool AudioSettings::enabled() const
159{
160 return mySettings.getBool(SETTING_ENABLED);
161}
162
163// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164uInt32 AudioSettings::dpcPitch() const
165{
166 return lboundInt(mySettings.getInt(SETTING_DPC_PITCH), 10000);
167}
168
169// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170void AudioSettings::setPreset(AudioSettings::Preset preset)
171{
172 if (preset == myPreset) return;
173 myPreset = preset;
174
175 switch (myPreset) {
176 case Preset::custom:
177 break;
178
179 case Preset::lowQualityMediumLag:
180 myPresetSampleRate = 44100;
181 myPresetFragmentSize = 1024;
182 myPresetBufferSize = 6;
183 myPresetHeadroom = 5;
184 myPresetResamplingQuality = ResamplingQuality::nearestNeightbour;
185 break;
186
187 case Preset::highQualityMediumLag:
188 myPresetSampleRate = 44100;
189 myPresetFragmentSize = 1024;
190 myPresetBufferSize = 6;
191 myPresetHeadroom = 5;
192 myPresetResamplingQuality = ResamplingQuality::lanczos_2;
193 break;
194
195 case Preset::highQualityLowLag:
196 myPresetSampleRate = 48000;
197 myPresetFragmentSize = 512;
198 myPresetBufferSize = 3;
199 myPresetHeadroom = 2;
200 myPresetResamplingQuality = ResamplingQuality::lanczos_2;
201 break;
202
203 case Preset::ultraQualityMinimalLag:
204 myPresetSampleRate = 96000;
205 myPresetFragmentSize = 128;
206 myPresetBufferSize = 0;
207 myPresetHeadroom = 0;
208 myPresetResamplingQuality = ResamplingQuality::lanczos_3;
209 break;
210
211 default:
212 throw runtime_error("invalid preset");
213 }
214
215 if (myIsPersistent) mySettings.setValue(SETTING_PRESET, static_cast<int>(myPreset));
216}
217
218// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
219void AudioSettings::setSampleRate(uInt32 sampleRate)
220{
221 if (!myIsPersistent) return;
222
223 mySettings.setValue(SETTING_SAMPLE_RATE, sampleRate);
224 normalize(mySettings);
225}
226
227// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
228void AudioSettings::setFragmentSize(uInt32 fragmentSize)
229{
230 if (!myIsPersistent) return;
231
232 mySettings.setValue(SETTING_FRAGMENT_SIZE, fragmentSize);
233 normalize(mySettings);
234}
235
236// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
237void AudioSettings::setBufferSize(uInt32 bufferSize)
238{
239 if (!myIsPersistent) return;
240
241 mySettings.setValue(SETTING_BUFFER_SIZE, bufferSize);
242 normalize(mySettings);
243}
244
245// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
246void AudioSettings::setHeadroom(uInt32 headroom)
247{
248 if (!myIsPersistent) return;
249
250 mySettings.setValue(SETTING_HEADROOM, headroom);
251 normalize(mySettings);
252}
253
254// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255void AudioSettings::setResamplingQuality(AudioSettings::ResamplingQuality resamplingQuality)
256{
257 if (!myIsPersistent) return;
258
259 mySettings.setValue(SETTING_RESAMPLING_QUALITY, static_cast<int>(resamplingQuality));
260 normalize(mySettings);
261}
262
263// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264void AudioSettings::setStereo(bool allROMs)
265{
266 if(!myIsPersistent) return;
267
268 mySettings.setValue(SETTING_STEREO, allROMs);
269}
270
271// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
272void AudioSettings::setDpcPitch(uInt32 pitch)
273{
274 if (!myIsPersistent) return;
275
276 mySettings.setValue(SETTING_DPC_PITCH, pitch);
277}
278
279// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
280void AudioSettings::setVolume(uInt32 volume)
281{
282 if (!myIsPersistent) return;
283
284 mySettings.setValue(SETTING_VOLUME, volume);
285 normalize(mySettings);
286}
287
288// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
289void AudioSettings::setEnabled(bool isEnabled)
290{
291 if (!myIsPersistent) return;
292
293 mySettings.setValue(SETTING_ENABLED, isEnabled);
294}
295
296// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
297void AudioSettings::setPersistent(bool isPersistent)
298{
299 myIsPersistent = isPersistent;
300}
301
302// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
303bool AudioSettings::customSettings() const
304{
305 return myPreset == Preset::custom;
306}
307
308// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309void AudioSettings::updatePresetFromSettings()
310{
311 if (!myIsPersistent) return;
312
313 setPreset(normalizedPreset(mySettings.getInt(SETTING_PRESET)));
314}
315