mirror of https://github.com/stella-emu/stella.git
Major audio settings overhaul.
This commit is contained in:
parent
d127865dee
commit
ef5261689a
|
@ -53,6 +53,11 @@
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"__mutex_base": "cpp",
|
"__mutex_base": "cpp",
|
||||||
"mutex": "cpp",
|
"mutex": "cpp",
|
||||||
"condition_variable": "cpp"
|
"condition_variable": "cpp",
|
||||||
|
"*.ins": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"ostream": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "AudioSettings.hxx"
|
||||||
|
#include "Settings.hxx"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
uInt32 convertInt(int x, int defaultValue)
|
||||||
|
{
|
||||||
|
return x <= defaultValue ? defaultValue : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSettings::Preset normalizedPreset(int numericPreset)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
numericPreset >= static_cast<int>(AudioSettings::Preset::custom) &&
|
||||||
|
numericPreset <= static_cast<int>(AudioSettings::Preset::veryHighQualityVeryLowLag)
|
||||||
|
) ? static_cast<AudioSettings::Preset>(numericPreset) : AudioSettings::DEFAULT_PRESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSettings::ResamplingQuality normalizeResamplingQuality(int numericResamplingQuality)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
numericResamplingQuality >= static_cast<int>(AudioSettings::ResamplingQuality::nearestNeightbour) &&
|
||||||
|
numericResamplingQuality <= static_cast<int>(AudioSettings::ResamplingQuality::lanczos_3)
|
||||||
|
) ? static_cast<AudioSettings::ResamplingQuality>(numericResamplingQuality) : AudioSettings::DEFAULT_RESAMPLING_QUALITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
AudioSettings::AudioSettings(Settings* settings)
|
||||||
|
: mySettings(settings)
|
||||||
|
{
|
||||||
|
setPreset(normalizedPreset(mySettings->getInt(SETTING_PRESET)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::normalize(Settings& settings)
|
||||||
|
{
|
||||||
|
int settingPreset = settings.getInt(SETTING_PRESET);
|
||||||
|
Preset preset = normalizedPreset(settingPreset);
|
||||||
|
if (static_cast<int>(preset) != settingPreset) settings.setValue(SETTING_PRESET, static_cast<int>(DEFAULT_PRESET));
|
||||||
|
|
||||||
|
switch (settings.getInt(SETTING_SAMPLE_RATE)) {
|
||||||
|
case 44100:
|
||||||
|
case 48000:
|
||||||
|
case 96000:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
settings.setValue(SETTING_SAMPLE_RATE, DEFAULT_SAMPLE_RATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (settings.getInt(SETTING_FRAGMENT_SIZE)) {
|
||||||
|
case 128:
|
||||||
|
case 256:
|
||||||
|
case 512:
|
||||||
|
case 1024:
|
||||||
|
case 2048:
|
||||||
|
case 4096:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
settings.setValue(SETTING_FRAGMENT_SIZE, DEFAULT_FRAGMENT_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int settingBufferSize = settings.getInt(SETTING_BUFFER_SIZE);
|
||||||
|
if (settingBufferSize < 0 || settingBufferSize > 20) settings.setValue(SETTING_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
|
||||||
|
|
||||||
|
int settingHeadroom = settings.getInt(SETTING_HEADROOM);
|
||||||
|
if (settingHeadroom < 0 || settingHeadroom > 20) settings.setValue(SETTING_HEADROOM, DEFAULT_HEADROOM);
|
||||||
|
|
||||||
|
int settingResamplingQuality = settings.getInt(SETTING_RESAMPLING_QUALITY);
|
||||||
|
ResamplingQuality resamplingQuality = normalizeResamplingQuality(settingResamplingQuality);
|
||||||
|
if (static_cast<int>(resamplingQuality) != settingResamplingQuality)
|
||||||
|
settings.setValue(SETTING_RESAMPLING_QUALITY, static_cast<int>(DEFAULT_RESAMPLING_QUALITY));
|
||||||
|
|
||||||
|
int settingVolume = settings.getInt(SETTING_VOLUME);
|
||||||
|
if (settingVolume < 0 || settingVolume > 100) settings.setValue(SETTING_VOLUME, DEFAULT_VOLUME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
AudioSettings::Preset AudioSettings::preset()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
return myPreset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 AudioSettings::sampleRate()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
return customSettings() ? convertInt(mySettings->getInt(SETTING_SAMPLE_RATE), DEFAULT_SAMPLE_RATE) : myPresetSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 AudioSettings::fragmentSize()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
return customSettings() ? convertInt(mySettings->getInt(SETTING_FRAGMENT_SIZE), DEFAULT_FRAGMENT_SIZE) : myPresetFragmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 AudioSettings::bufferSize()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
// 0 is a valid value -> keep it
|
||||||
|
return customSettings() ? convertInt(mySettings->getInt(SETTING_BUFFER_SIZE), 0) : myPresetBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 AudioSettings::headroom()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
// 0 is a valid value -> keep it
|
||||||
|
return customSettings() ? convertInt(mySettings->getInt(SETTING_HEADROOM), 0) : myPresetHeadroom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
AudioSettings::ResamplingQuality AudioSettings::resamplingQuality()
|
||||||
|
{
|
||||||
|
updatePresetFromSettings();
|
||||||
|
return customSettings() ? normalizeResamplingQuality(mySettings->getInt(SETTING_RESAMPLING_QUALITY)) : myPresetResamplingQuality;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 AudioSettings::volume() const
|
||||||
|
{
|
||||||
|
// 0 is a valid value -> keep it
|
||||||
|
return convertInt(mySettings->getInt(SETTING_VOLUME), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool AudioSettings::enabled() const
|
||||||
|
{
|
||||||
|
return mySettings->getBool(SETTING_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setPreset(AudioSettings::Preset preset)
|
||||||
|
{
|
||||||
|
if (preset == myPreset) return;
|
||||||
|
myPreset = preset;
|
||||||
|
|
||||||
|
switch (myPreset) {
|
||||||
|
case Preset::custom:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preset::lowQualityMediumLag:
|
||||||
|
myPresetSampleRate = 44100;
|
||||||
|
myPresetFragmentSize = 1024;
|
||||||
|
myPresetBufferSize = 4;
|
||||||
|
myPresetHeadroom = 3;
|
||||||
|
myPresetResamplingQuality = ResamplingQuality::nearestNeightbour;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preset::highQualityMediumLag:
|
||||||
|
myPresetSampleRate = 44100;
|
||||||
|
myPresetFragmentSize = 1024;
|
||||||
|
myPresetBufferSize = 4;
|
||||||
|
myPresetHeadroom = 3;
|
||||||
|
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preset::highQualityLowLag:
|
||||||
|
myPresetSampleRate = 48000;
|
||||||
|
myPresetFragmentSize = 512;
|
||||||
|
myPresetBufferSize = 2;
|
||||||
|
myPresetHeadroom = 1;
|
||||||
|
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preset::veryHighQualityVeryLowLag:
|
||||||
|
myPresetSampleRate = 96000;
|
||||||
|
myPresetFragmentSize = 128;
|
||||||
|
myPresetBufferSize = 0;
|
||||||
|
myPresetHeadroom = 0;
|
||||||
|
myPresetResamplingQuality = ResamplingQuality::lanczos_3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("invalid preset");
|
||||||
|
}
|
||||||
|
|
||||||
|
mySettings->setValue(SETTING_PRESET, static_cast<int>(myPreset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setSampleRate(uInt32 sampleRate)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_SAMPLE_RATE, sampleRate);
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setFragmentSize(uInt32 fragmentSize)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_FRAGMENT_SIZE, fragmentSize);
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setBufferSize(uInt32 bufferSize)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_BUFFER_SIZE, bufferSize);
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setHeadroom(uInt32 headroom)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_HEADROOM, headroom);
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setResamplingQuality(AudioSettings::ResamplingQuality resamplingQuality)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_RESAMPLING_QUALITY, static_cast<int>(resamplingQuality));
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setVolume(uInt32 volume)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_VOLUME, volume);
|
||||||
|
normalize(*mySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::setEnabled(bool isEnabled)
|
||||||
|
{
|
||||||
|
mySettings->setValue(SETTING_ENABLED, isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool AudioSettings::customSettings() const
|
||||||
|
{
|
||||||
|
return myPreset == Preset::custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AudioSettings::updatePresetFromSettings()
|
||||||
|
{
|
||||||
|
setPreset(normalizedPreset(mySettings->getInt(SETTING_PRESET)));
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef AUDIO_PARAMTERS_HXX
|
||||||
|
#define AUDIO_PARAMTERS_HXX
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
|
||||||
|
class AudioSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Preset {
|
||||||
|
custom = 1,
|
||||||
|
lowQualityMediumLag = 2,
|
||||||
|
highQualityMediumLag = 3,
|
||||||
|
highQualityLowLag = 4,
|
||||||
|
veryHighQualityVeryLowLag = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ResamplingQuality {
|
||||||
|
nearestNeightbour = 1,
|
||||||
|
lanczos_2 = 2,
|
||||||
|
lanczos_3 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr const char* SETTING_PRESET = "audio.preset";
|
||||||
|
static constexpr const char* SETTING_SAMPLE_RATE = "audio.sample_rate";
|
||||||
|
static constexpr const char* SETTING_FRAGMENT_SIZE = "audio.fragment_size";
|
||||||
|
static constexpr const char* SETTING_BUFFER_SIZE = "audio.buffer_size";
|
||||||
|
static constexpr const char* SETTING_HEADROOM = "audio.headroom";
|
||||||
|
static constexpr const char* SETTING_RESAMPLING_QUALITY = "audio.resampling_quality";
|
||||||
|
static constexpr const char* SETTING_VOLUME = "audio.volume";
|
||||||
|
static constexpr const char* SETTING_ENABLED = "audio.enabled";
|
||||||
|
|
||||||
|
static constexpr Preset DEFAULT_PRESET = Preset::highQualityMediumLag;
|
||||||
|
static constexpr uInt32 DEFAULT_SAMPLE_RATE = 44100;
|
||||||
|
static constexpr uInt32 DEFAULT_FRAGMENT_SIZE = 512;
|
||||||
|
static constexpr uInt32 DEFAULT_BUFFER_SIZE = 3;
|
||||||
|
static constexpr uInt32 DEFAULT_HEADROOM = 2;
|
||||||
|
static constexpr ResamplingQuality DEFAULT_RESAMPLING_QUALITY = ResamplingQuality::lanczos_2;
|
||||||
|
static constexpr uInt32 DEFAULT_VOLUME = 80;
|
||||||
|
static constexpr bool DEFAULT_ENABLED = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AudioSettings() = default;
|
||||||
|
|
||||||
|
AudioSettings(Settings* mySettings);
|
||||||
|
|
||||||
|
static void initialize(Settings& settings);
|
||||||
|
|
||||||
|
static void normalize(Settings& settings);
|
||||||
|
|
||||||
|
Preset preset();
|
||||||
|
|
||||||
|
uInt32 sampleRate();
|
||||||
|
|
||||||
|
uInt32 fragmentSize();
|
||||||
|
|
||||||
|
uInt32 bufferSize();
|
||||||
|
|
||||||
|
uInt32 headroom();
|
||||||
|
|
||||||
|
ResamplingQuality resamplingQuality();
|
||||||
|
|
||||||
|
uInt32 volume() const;
|
||||||
|
|
||||||
|
bool enabled() const;
|
||||||
|
|
||||||
|
void setPreset(Preset preset);
|
||||||
|
|
||||||
|
void setSampleRate(uInt32 sampleRate);
|
||||||
|
|
||||||
|
void setFragmentSize(uInt32 fragmentSize);
|
||||||
|
|
||||||
|
void setBufferSize(uInt32 bufferSize);
|
||||||
|
|
||||||
|
void setHeadroom(uInt32 headroom);
|
||||||
|
|
||||||
|
void setResamplingQuality(ResamplingQuality resamplingQuality);
|
||||||
|
|
||||||
|
void setVolume(uInt32 volume);
|
||||||
|
|
||||||
|
void setEnabled(bool isEnabled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool customSettings() const;
|
||||||
|
|
||||||
|
void updatePresetFromSettings();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Settings* mySettings;
|
||||||
|
|
||||||
|
Preset myPreset;
|
||||||
|
|
||||||
|
uInt32 myPresetSampleRate;
|
||||||
|
uInt32 myPresetFragmentSize;
|
||||||
|
uInt32 myPresetBufferSize;
|
||||||
|
uInt32 myPresetHeadroom;
|
||||||
|
ResamplingQuality myPresetResamplingQuality;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AUDIO_PARAMTERS_HXX
|
|
@ -50,6 +50,8 @@
|
||||||
#include "SoundNull.hxx"
|
#include "SoundNull.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class AudioSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class deals with the different framebuffer/sound/event
|
This class deals with the different framebuffer/sound/event
|
||||||
implementations for the various ports of Stella, and always returns a
|
implementations for the various ports of Stella, and always returns a
|
||||||
|
@ -108,10 +110,10 @@ class MediaFactory
|
||||||
return make_unique<FrameBufferSDL2>(osystem);
|
return make_unique<FrameBufferSDL2>(osystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unique_ptr<Sound> createAudio(OSystem& osystem)
|
static unique_ptr<Sound> createAudio(OSystem& osystem, AudioSettings& audioSettings)
|
||||||
{
|
{
|
||||||
#ifdef SOUND_SUPPORT
|
#ifdef SOUND_SUPPORT
|
||||||
return make_unique<SoundSDL2>(osystem);
|
return make_unique<SoundSDL2>(osystem, audioSettings);
|
||||||
#else
|
#else
|
||||||
return make_unique<SoundNull>(osystem);
|
return make_unique<SoundNull>(osystem);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -86,7 +86,7 @@ class SoundNull : public Sound
|
||||||
|
|
||||||
@param percent The new volume percentage level for the sound device
|
@param percent The new volume percentage level for the sound device
|
||||||
*/
|
*/
|
||||||
void setVolume(Int32 percent) override { }
|
void setVolume(uInt32 percent) override { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adjusts the volume of the sound device based on the given direction.
|
Adjusts the volume of the sound device based on the given direction.
|
||||||
|
|
|
@ -30,16 +30,18 @@
|
||||||
#include "SoundSDL2.hxx"
|
#include "SoundSDL2.hxx"
|
||||||
#include "AudioQueue.hxx"
|
#include "AudioQueue.hxx"
|
||||||
#include "EmulationTiming.hxx"
|
#include "EmulationTiming.hxx"
|
||||||
|
#include "AudioSettings.hxx"
|
||||||
#include "audio/SimpleResampler.hxx"
|
#include "audio/SimpleResampler.hxx"
|
||||||
#include "audio/LanczosResampler.hxx"
|
#include "audio/LanczosResampler.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SoundSDL2::SoundSDL2(OSystem& osystem)
|
SoundSDL2::SoundSDL2(OSystem& osystem, AudioSettings& audioSettings)
|
||||||
: Sound(osystem),
|
: Sound(osystem),
|
||||||
myIsInitializedFlag(false),
|
myIsInitializedFlag(false),
|
||||||
myVolume(100),
|
myVolume(100),
|
||||||
myVolumeFactor(0xffff),
|
myVolumeFactor(0xffff),
|
||||||
myCurrentFragment(nullptr)
|
myCurrentFragment(nullptr),
|
||||||
|
myAudioSettings(audioSettings)
|
||||||
{
|
{
|
||||||
myOSystem.logMessage("SoundSDL2::SoundSDL2 started ...", 2);
|
myOSystem.logMessage("SoundSDL2::SoundSDL2 started ...", 2);
|
||||||
|
|
||||||
|
@ -48,10 +50,10 @@ SoundSDL2::SoundSDL2(OSystem& osystem)
|
||||||
// This fixes a bug most prevalent with ATI video cards in Windows,
|
// This fixes a bug most prevalent with ATI video cards in Windows,
|
||||||
// whereby sound stopped working after the first video change
|
// whereby sound stopped working after the first video change
|
||||||
SDL_AudioSpec desired;
|
SDL_AudioSpec desired;
|
||||||
desired.freq = myOSystem.settings().getInt("freq");
|
desired.freq = myAudioSettings.sampleRate();
|
||||||
desired.format = AUDIO_F32SYS;
|
desired.format = AUDIO_F32SYS;
|
||||||
desired.channels = 2;
|
desired.channels = 2;
|
||||||
desired.samples = myOSystem.settings().getInt("fragsize");
|
desired.samples = myAudioSettings.fragmentSize();
|
||||||
desired.callback = callback;
|
desired.callback = callback;
|
||||||
desired.userdata = static_cast<void*>(this);
|
desired.userdata = static_cast<void*>(this);
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ SoundSDL2::~SoundSDL2()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void SoundSDL2::setEnabled(bool state)
|
void SoundSDL2::setEnabled(bool state)
|
||||||
{
|
{
|
||||||
myOSystem.settings().setValue("sound", state);
|
myAudioSettings.setEnabled(state);
|
||||||
|
|
||||||
myOSystem.logMessage(state ? "SoundSDL2::setEnabled(true)" :
|
myOSystem.logMessage(state ? "SoundSDL2::setEnabled(true)" :
|
||||||
"SoundSDL2::setEnabled(false)", 2);
|
"SoundSDL2::setEnabled(false)", 2);
|
||||||
|
@ -110,7 +112,7 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
|
||||||
myOSystem.logMessage("SoundSDL2::open started ...", 2);
|
myOSystem.logMessage("SoundSDL2::open started ...", 2);
|
||||||
mute(true);
|
mute(true);
|
||||||
|
|
||||||
if(!myOSystem.settings().getBool("sound"))
|
if(!myAudioSettings.enabled())
|
||||||
{
|
{
|
||||||
myOSystem.logMessage("Sound disabled\n", 1);
|
myOSystem.logMessage("Sound disabled\n", 1);
|
||||||
return;
|
return;
|
||||||
|
@ -121,7 +123,7 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
|
||||||
myCurrentFragment = nullptr;
|
myCurrentFragment = nullptr;
|
||||||
|
|
||||||
// Adjust volume to that defined in settings
|
// Adjust volume to that defined in settings
|
||||||
setVolume(myOSystem.settings().getInt("volume"));
|
setVolume(myAudioSettings.volume());
|
||||||
|
|
||||||
// Show some info
|
// Show some info
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
@ -171,11 +173,11 @@ void SoundSDL2::reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void SoundSDL2::setVolume(Int32 percent)
|
void SoundSDL2::setVolume(uInt32 percent)
|
||||||
{
|
{
|
||||||
if(myIsInitializedFlag && (percent >= 0) && (percent <= 100))
|
if(myIsInitializedFlag && (percent <= 100))
|
||||||
{
|
{
|
||||||
myOSystem.settings().setValue("volume", percent);
|
myAudioSettings.setVolume(percent);
|
||||||
myVolume = percent;
|
myVolume = percent;
|
||||||
|
|
||||||
SDL_LockAudio();
|
SDL_LockAudio();
|
||||||
|
@ -213,7 +215,7 @@ void SoundSDL2::adjustVolume(Int8 direction)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 SoundSDL2::getFragmentSize() const
|
uInt32 SoundSDL2::getFragmentSize() const
|
||||||
{
|
{
|
||||||
return myHardwareSpec.size;
|
return myHardwareSpec.samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -253,24 +255,26 @@ void SoundSDL2::initResampler()
|
||||||
Resampler::Format formatTo =
|
Resampler::Format formatTo =
|
||||||
Resampler::Format(myHardwareSpec.freq, myHardwareSpec.samples, myHardwareSpec.channels > 1);
|
Resampler::Format(myHardwareSpec.freq, myHardwareSpec.samples, myHardwareSpec.channels > 1);
|
||||||
|
|
||||||
int quality = myOSystem.settings().getInt("resampling.quality");
|
|
||||||
|
|
||||||
switch (quality) {
|
switch (myAudioSettings.resamplingQuality()) {
|
||||||
case 1:
|
case AudioSettings::ResamplingQuality::nearestNeightbour:
|
||||||
myResampler = make_unique<SimpleResampler>(formatFrom, formatTo, nextFragmentCallback);
|
myResampler = make_unique<SimpleResampler>(formatFrom, formatTo, nextFragmentCallback);
|
||||||
(cerr << "resampling quality 1: using nearest neighbor resampling\n").flush();
|
(cerr << "resampling quality 1: using nearest neighbor resampling\n").flush();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case AudioSettings::ResamplingQuality::lanczos_2:
|
||||||
case 2:
|
|
||||||
(cerr << "resampling quality 2: using nearest Lanczos resampling, a = 2\n").flush();
|
(cerr << "resampling quality 2: using nearest Lanczos resampling, a = 2\n").flush();
|
||||||
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 2);
|
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case AudioSettings::ResamplingQuality::lanczos_3:
|
||||||
(cerr << "resampling quality 3: using nearest Lanczos resampling, a = 3\n").flush();
|
(cerr << "resampling quality 3: using nearest Lanczos resampling, a = 3\n").flush();
|
||||||
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 3);
|
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("invalid resampling quality");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
class OSystem;
|
class OSystem;
|
||||||
class AudioQueue;
|
class AudioQueue;
|
||||||
class EmulationTiming;
|
class EmulationTiming;
|
||||||
|
class AudioSettings;
|
||||||
|
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ class SoundSDL2 : public Sound
|
||||||
Create a new sound object. The init method must be invoked before
|
Create a new sound object. The init method must be invoked before
|
||||||
using the object.
|
using the object.
|
||||||
*/
|
*/
|
||||||
SoundSDL2(OSystem& osystem);
|
SoundSDL2(OSystem& osystem, AudioSettings& audioSettings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor
|
Destructor
|
||||||
|
@ -88,7 +89,7 @@ class SoundSDL2 : public Sound
|
||||||
|
|
||||||
@param percent The new volume percentage level for the sound device
|
@param percent The new volume percentage level for the sound device
|
||||||
*/
|
*/
|
||||||
void setVolume(Int32 percent) override;
|
void setVolume(uInt32 percent) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adjusts the volume of the sound device based on the given direction.
|
Adjusts the volume of the sound device based on the given direction.
|
||||||
|
@ -137,6 +138,8 @@ class SoundSDL2 : public Sound
|
||||||
|
|
||||||
unique_ptr<Resampler> myResampler;
|
unique_ptr<Resampler> myResampler;
|
||||||
|
|
||||||
|
AudioSettings& myAudioSettings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Callback function invoked by the SDL Audio library when it needs data
|
// Callback function invoked by the SDL Audio library when it needs data
|
||||||
static void callback(void* udata, uInt8* stream, int len);
|
static void callback(void* udata, uInt8* stream, int len);
|
||||||
|
|
|
@ -16,7 +16,8 @@ MODULE_OBJS := \
|
||||||
src/common/SoundSDL2.o \
|
src/common/SoundSDL2.o \
|
||||||
src/common/StateManager.o \
|
src/common/StateManager.o \
|
||||||
src/common/ZipHandler.o \
|
src/common/ZipHandler.o \
|
||||||
src/common/AudioQueue.o
|
src/common/AudioQueue.o \
|
||||||
|
src/common/AudioSettings.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/common
|
src/common
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
#include "AudioQueue.hxx"
|
#include "AudioQueue.hxx"
|
||||||
|
#include "AudioSettings.hxx"
|
||||||
#include "frame-manager/FrameManager.hxx"
|
#include "frame-manager/FrameManager.hxx"
|
||||||
#include "frame-manager/FrameLayoutDetector.hxx"
|
#include "frame-manager/FrameLayoutDetector.hxx"
|
||||||
#include "frame-manager/YStartDetector.hxx"
|
#include "frame-manager/YStartDetector.hxx"
|
||||||
|
@ -76,7 +77,7 @@ namespace {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
const Properties& props)
|
const Properties& props, AudioSettings& audioSettings)
|
||||||
: myOSystem(osystem),
|
: myOSystem(osystem),
|
||||||
myEvent(osystem.eventHandler().event()),
|
myEvent(osystem.eventHandler().event()),
|
||||||
myProperties(props),
|
myProperties(props),
|
||||||
|
@ -85,7 +86,8 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
myCurrentFormat(0), // Unknown format @ start,
|
myCurrentFormat(0), // Unknown format @ start,
|
||||||
myAutodetectedYstart(0),
|
myAutodetectedYstart(0),
|
||||||
myUserPaletteDefined(false),
|
myUserPaletteDefined(false),
|
||||||
myConsoleTiming(ConsoleTiming::ntsc)
|
myConsoleTiming(ConsoleTiming::ntsc),
|
||||||
|
myAudioSettings(audioSettings)
|
||||||
{
|
{
|
||||||
// Load user-defined palette for this ROM
|
// Load user-defined palette for this ROM
|
||||||
loadUserPalette();
|
loadUserPalette();
|
||||||
|
@ -553,8 +555,15 @@ void Console::initializeAudio()
|
||||||
{
|
{
|
||||||
myOSystem.sound().close();
|
myOSystem.sound().close();
|
||||||
|
|
||||||
myEmulationTiming.updatePlaybackPeriod(myOSystem.sound().getSampleRate());
|
myEmulationTiming
|
||||||
myEmulationTiming.updatePlaybackPeriod(myOSystem.sound().getFragmentSize());
|
.updatePlaybackRate(myOSystem.sound().getSampleRate())
|
||||||
|
.updatePlaybackPeriod(myOSystem.sound().getFragmentSize())
|
||||||
|
.updateAudioQueueExtraFragments(myAudioSettings.bufferSize())
|
||||||
|
.updateAudioQueueHeadroom(myAudioSettings.headroom());
|
||||||
|
|
||||||
|
(cout << "sample rate: " << myOSystem.sound().getSampleRate() << std::endl).flush();
|
||||||
|
(cout << "fragment size: " << myOSystem.sound().getFragmentSize() << std::endl).flush();
|
||||||
|
(cout << "prebuffer fragment count: " << myEmulationTiming.prebufferFragmentCount() << std::endl).flush();
|
||||||
|
|
||||||
createAudioQueue();
|
createAudioQueue();
|
||||||
myTIA->setAudioQueue(myAudioQueue);
|
myTIA->setAudioQueue(myAudioQueue);
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Cartridge;
|
||||||
class CompuMate;
|
class CompuMate;
|
||||||
class Debugger;
|
class Debugger;
|
||||||
class AudioQueue;
|
class AudioQueue;
|
||||||
|
class AudioSettings;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Control.hxx"
|
#include "Control.hxx"
|
||||||
|
@ -80,7 +81,7 @@ class Console : public Serializable
|
||||||
@param props The properties for the cartridge
|
@param props The properties for the cartridge
|
||||||
*/
|
*/
|
||||||
Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
const Properties& props);
|
const Properties& props, AudioSettings& audioSettings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor
|
Destructor
|
||||||
|
@ -423,9 +424,12 @@ class Console : public Serializable
|
||||||
ConsoleTiming myConsoleTiming;
|
ConsoleTiming myConsoleTiming;
|
||||||
|
|
||||||
// Emulation timing provider. This ties together the timing of the core emulation loop
|
// Emulation timing provider. This ties together the timing of the core emulation loop
|
||||||
// and the audio synthesis parameters
|
// and the parameters that govern audio synthesis
|
||||||
EmulationTiming myEmulationTiming;
|
EmulationTiming myEmulationTiming;
|
||||||
|
|
||||||
|
// The audio settings
|
||||||
|
AudioSettings& myAudioSettings;
|
||||||
|
|
||||||
// Table of RGB values for NTSC, PAL and SECAM
|
// Table of RGB values for NTSC, PAL and SECAM
|
||||||
static uInt32 ourNTSCPalette[256];
|
static uInt32 ourNTSCPalette[256];
|
||||||
static uInt32 ourPALPalette[256];
|
static uInt32 ourPALPalette[256];
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uInt32 AUDIO_HALF_FRAMES_PER_FRAGMENT = 1;
|
constexpr uInt32 AUDIO_HALF_FRAMES_PER_FRAGMENT = 1;
|
||||||
constexpr uInt32 QUEUE_CAPACITY_EXTRA_FRAGMENTS = 1;
|
|
||||||
constexpr uInt32 PREBUFFER_EXTRA_FRAGMENT_COUNT = 2;
|
|
||||||
|
|
||||||
uInt32 discreteDivCeil(uInt32 n, uInt32 d)
|
uInt32 discreteDivCeil(uInt32 n, uInt32 d)
|
||||||
{
|
{
|
||||||
|
@ -32,25 +30,44 @@ namespace {
|
||||||
EmulationTiming::EmulationTiming(FrameLayout frameLayout) :
|
EmulationTiming::EmulationTiming(FrameLayout frameLayout) :
|
||||||
myFrameLayout(frameLayout),
|
myFrameLayout(frameLayout),
|
||||||
myPlaybackRate(44100),
|
myPlaybackRate(44100),
|
||||||
myPlaybackPeriod(512)
|
myPlaybackPeriod(512),
|
||||||
|
myAudioQueueExtraFragments(1),
|
||||||
|
myAudioQueueHeadroom(2)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EmulationTiming::updateFrameLayout(FrameLayout frameLayout)
|
EmulationTiming& EmulationTiming::updateFrameLayout(FrameLayout frameLayout)
|
||||||
{
|
{
|
||||||
myFrameLayout = frameLayout;
|
myFrameLayout = frameLayout;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EmulationTiming::updatePlaybackRate(uInt32 playbackRate)
|
EmulationTiming& EmulationTiming::updatePlaybackRate(uInt32 playbackRate)
|
||||||
{
|
{
|
||||||
myPlaybackRate = playbackRate;
|
myPlaybackRate = playbackRate;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EmulationTiming::updatePlaybackPeriod(uInt32 playbackPeriod)
|
EmulationTiming& EmulationTiming::updatePlaybackPeriod(uInt32 playbackPeriod)
|
||||||
{
|
{
|
||||||
myPlaybackPeriod = playbackPeriod;
|
myPlaybackPeriod = playbackPeriod;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
EmulationTiming& EmulationTiming::updateAudioQueueExtraFragments(uInt32 audioQueueExtraFragments)
|
||||||
|
{
|
||||||
|
myAudioQueueExtraFragments = audioQueueExtraFragments;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
EmulationTiming& EmulationTiming::updateAudioQueueHeadroom(uInt32 audioQueueHeadroom)
|
||||||
|
{
|
||||||
|
myAudioQueueHeadroom = audioQueueHeadroom;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -124,11 +141,11 @@ uInt32 EmulationTiming::audioQueueCapacity() const
|
||||||
{
|
{
|
||||||
uInt32 minCapacity = discreteDivCeil(maxCyclesPerTimeslice() * audioSampleRate(), audioFragmentSize() * cyclesPerSecond());
|
uInt32 minCapacity = discreteDivCeil(maxCyclesPerTimeslice() * audioSampleRate(), audioFragmentSize() * cyclesPerSecond());
|
||||||
|
|
||||||
return std::max(prebufferFragmentCount(), minCapacity) + QUEUE_CAPACITY_EXTRA_FRAGMENTS;
|
return std::max(prebufferFragmentCount(), minCapacity) + myAudioQueueExtraFragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 EmulationTiming::prebufferFragmentCount() const
|
uInt32 EmulationTiming::prebufferFragmentCount() const
|
||||||
{
|
{
|
||||||
return discreteDivCeil(myPlaybackPeriod * audioSampleRate(), audioFragmentSize() * myPlaybackRate) + PREBUFFER_EXTRA_FRAGMENT_COUNT;
|
return discreteDivCeil(myPlaybackPeriod * audioSampleRate(), audioFragmentSize() * myPlaybackRate) + myAudioQueueHeadroom;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,15 @@ class EmulationTiming {
|
||||||
|
|
||||||
EmulationTiming(FrameLayout frameLayout = FrameLayout::ntsc);
|
EmulationTiming(FrameLayout frameLayout = FrameLayout::ntsc);
|
||||||
|
|
||||||
void updateFrameLayout(FrameLayout frameLayout);
|
EmulationTiming& updateFrameLayout(FrameLayout frameLayout);
|
||||||
|
|
||||||
void updatePlaybackRate(uInt32 playbackRate);
|
EmulationTiming& updatePlaybackRate(uInt32 playbackRate);
|
||||||
|
|
||||||
void updatePlaybackPeriod(uInt32 period);
|
EmulationTiming& updatePlaybackPeriod(uInt32 period);
|
||||||
|
|
||||||
|
EmulationTiming& updateAudioQueueExtraFragments(uInt32 audioQueueExtraFragments);
|
||||||
|
|
||||||
|
EmulationTiming& updateAudioQueueHeadroom(uInt32 audioQueueHeadroom);
|
||||||
|
|
||||||
uInt32 maxCyclesPerTimeslice() const;
|
uInt32 maxCyclesPerTimeslice() const;
|
||||||
|
|
||||||
|
@ -60,6 +64,9 @@ class EmulationTiming {
|
||||||
|
|
||||||
uInt32 myPlaybackPeriod;
|
uInt32 myPlaybackPeriod;
|
||||||
|
|
||||||
|
uInt32 myAudioQueueExtraFragments;
|
||||||
|
uInt32 myAudioQueueHeadroom;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
EmulationTiming(const EmulationTiming&) = delete;
|
EmulationTiming(const EmulationTiming&) = delete;
|
||||||
|
|
|
@ -90,6 +90,7 @@ OSystem::OSystem()
|
||||||
myBuildInfo = info.str();
|
myBuildInfo = info.str();
|
||||||
|
|
||||||
mySettings = MediaFactory::createSettings(*this);
|
mySettings = MediaFactory::createSettings(*this);
|
||||||
|
myAudioSettings = AudioSettings(mySettings.get());
|
||||||
myRandom = make_unique<Random>(*this);
|
myRandom = make_unique<Random>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,9 +322,9 @@ FBInitStatus OSystem::createFrameBuffer()
|
||||||
void OSystem::createSound()
|
void OSystem::createSound()
|
||||||
{
|
{
|
||||||
if(!mySound)
|
if(!mySound)
|
||||||
mySound = MediaFactory::createAudio(*this);
|
mySound = MediaFactory::createAudio(*this, myAudioSettings);
|
||||||
#ifndef SOUND_SUPPORT
|
#ifndef SOUND_SUPPORT
|
||||||
mySettings->setValue("sound", false);
|
myAudioSettings.setEnabled(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +550,7 @@ unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile, string&
|
||||||
|
|
||||||
// Finally, create the cart with the correct properties
|
// Finally, create the cart with the correct properties
|
||||||
if(cart)
|
if(cart)
|
||||||
console = make_unique<Console>(*this, cart, props);
|
console = make_unique<Console>(*this, cart, props, myAudioSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return console;
|
return console;
|
||||||
|
|
|
@ -44,6 +44,7 @@ class EmulationWorker;
|
||||||
#include "FrameBufferConstants.hxx"
|
#include "FrameBufferConstants.hxx"
|
||||||
#include "EventHandlerConstants.hxx"
|
#include "EventHandlerConstants.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
#include "AudioSettings.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class provides an interface for accessing operating system specific
|
This class provides an interface for accessing operating system specific
|
||||||
|
@ -481,6 +482,9 @@ class OSystem
|
||||||
// Indicates whether to stop the main loop
|
// Indicates whether to stop the main loop
|
||||||
bool myQuitLoop;
|
bool myQuitLoop;
|
||||||
|
|
||||||
|
// Audio settings
|
||||||
|
AudioSettings myAudioSettings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string myBaseDir;
|
string myBaseDir;
|
||||||
string myStateDir;
|
string myStateDir;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "OSystem.hxx"
|
#include "OSystem.hxx"
|
||||||
#include "Version.hxx"
|
#include "Version.hxx"
|
||||||
|
#include "AudioSettings.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "DebuggerDialog.hxx"
|
#include "DebuggerDialog.hxx"
|
||||||
|
@ -69,12 +70,14 @@ Settings::Settings(OSystem& osystem)
|
||||||
setInternal("tv.bleed", "0.0");
|
setInternal("tv.bleed", "0.0");
|
||||||
|
|
||||||
// Sound options
|
// Sound options
|
||||||
setInternal("sound", "true");
|
setInternal(AudioSettings::SETTING_ENABLED, AudioSettings::DEFAULT_ENABLED);
|
||||||
setInternal("aud.mode", "balanced");
|
setInternal(AudioSettings::SETTING_PRESET, static_cast<int>(AudioSettings::DEFAULT_PRESET));
|
||||||
setInternal("fragsize", "512");
|
setInternal(AudioSettings::SETTING_SAMPLE_RATE, AudioSettings::DEFAULT_SAMPLE_RATE);
|
||||||
setInternal("freq", "44100");
|
setInternal(AudioSettings::SETTING_FRAGMENT_SIZE, AudioSettings::DEFAULT_FRAGMENT_SIZE);
|
||||||
setInternal("volume", "100");
|
setInternal(AudioSettings::SETTING_BUFFER_SIZE, AudioSettings::DEFAULT_BUFFER_SIZE);
|
||||||
setInternal("resampling.quality", "2");
|
setInternal(AudioSettings::SETTING_HEADROOM, AudioSettings::DEFAULT_HEADROOM);
|
||||||
|
setInternal(AudioSettings::SETTING_RESAMPLING_QUALITY, static_cast<int>(AudioSettings::DEFAULT_RESAMPLING_QUALITY));
|
||||||
|
setInternal(AudioSettings::SETTING_VOLUME, AudioSettings::DEFAULT_VOLUME);
|
||||||
|
|
||||||
// Input event options
|
// Input event options
|
||||||
setInternal("keymap", "");
|
setInternal("keymap", "");
|
||||||
|
@ -361,13 +364,7 @@ void Settings::validate()
|
||||||
if(i < 0 || i > 6) setInternal("plr.tm.horizon", 5);*/
|
if(i < 0 || i > 6) setInternal("plr.tm.horizon", 5);*/
|
||||||
|
|
||||||
#ifdef SOUND_SUPPORT
|
#ifdef SOUND_SUPPORT
|
||||||
i = getInt("volume");
|
AudioSettings::normalize(*this);
|
||||||
if(i < 0 || i > 100) setInternal("volume", "100");
|
|
||||||
i = getInt("freq");
|
|
||||||
if(!(i == 44100 || i == 48000 || i == 96000))
|
|
||||||
setInternal("freq", "44100");
|
|
||||||
i = getInt("resampling.quality");
|
|
||||||
if (i < 1 || i > 3) setInternal("resampling.quality", 2);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
i = getInt("joydeadzone");
|
i = getInt("joydeadzone");
|
||||||
|
@ -447,11 +444,14 @@ void Settings::usage() const
|
||||||
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
|
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
|
||||||
<< endl
|
<< endl
|
||||||
#ifdef SOUND_SUPPORT
|
#ifdef SOUND_SUPPORT
|
||||||
<< " -sound <1|0> Enable sound generation\n"
|
<< " -audio.enabled <1|0> Enable audio\n"
|
||||||
<< " -fragsize <number> The size of sound fragments (must be a power of two)\n"
|
<< " -audio.preset <1-5> Audio preset (or 1 for custom)\n"
|
||||||
<< " -freq <number> Set sound sample output frequency (44100|48000|96000)\n"
|
<< " -audio.sample_rate <number> Output sample rate (44100|48000|96000)\n"
|
||||||
<< " -resampling.quality <number> Resampling quality (1 -3), default: 2\n"
|
<< " -audio.fragment_size <number> Fragment size (128|256|512|1024|2048|4096)\n"
|
||||||
<< " -volume <number> Set the volume (0 - 100)\n"
|
<< " -audio.buffer_size <number> Max. number of additional half-frames to buffer (0 -- 20)\n"
|
||||||
|
<< " -audio.headroom <number> Additional half-frames to prebuffer (0 -- 20)\n"
|
||||||
|
<< " -audio.resampling_quality <1-3> Resampling quality\n"
|
||||||
|
<< " -audio.volume <number> Vokume (0 -- 100)\n"
|
||||||
<< endl
|
<< endl
|
||||||
#endif
|
#endif
|
||||||
<< " -tia.zoom <zoom> Use the specified zoom level (windowed mode) for TIA image\n"
|
<< " -tia.zoom <zoom> Use the specified zoom level (windowed mode) for TIA image\n"
|
||||||
|
|
|
@ -89,7 +89,7 @@ class Sound
|
||||||
|
|
||||||
@param percent The new volume percentage level for the sound device
|
@param percent The new volume percentage level for the sound device
|
||||||
*/
|
*/
|
||||||
virtual void setVolume(Int32 percent) = 0;
|
virtual void setVolume(uInt32 percent) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adjusts the volume of the sound device based on the given direction.
|
Adjusts the volume of the sound device based on the given direction.
|
||||||
|
|
|
@ -20,6 +20,4 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SettingsWINDOWS::SettingsWINDOWS(OSystem& osystem)
|
SettingsWINDOWS::SettingsWINDOWS(OSystem& osystem)
|
||||||
: Settings(osystem)
|
: Settings(osystem)
|
||||||
{
|
{}
|
||||||
setInternal("fragsize", "1024");
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue