mirror of https://github.com/stella-emu/stella.git
Allow sound sample rate/fragment size to change dynamically.
- Move sound debugging output to logging facilities - This should fix issue #348, but more testing is required Bumped version # for beta release.
This commit is contained in:
parent
13b9bbe5a4
commit
e5fb010631
|
@ -84,11 +84,6 @@ class SoundNull : public Sound
|
|||
*/
|
||||
uInt32 getSampleRate() const override { return 31400; }
|
||||
|
||||
/**
|
||||
Reset the sound device.
|
||||
*/
|
||||
void reset() override { }
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
volume is given as a percentage from 0 to 100. Values outside
|
||||
|
|
|
@ -54,32 +54,9 @@ SoundSDL2::SoundSDL2(OSystem& osystem, AudioSettings& audioSettings)
|
|||
return;
|
||||
}
|
||||
|
||||
// The sound system is opened only once per program run, to eliminate
|
||||
// issues with opening and closing it multiple times
|
||||
// This fixes a bug most prevalent with ATI video cards in Windows,
|
||||
// whereby sound stopped working after the first video change
|
||||
SDL_AudioSpec desired;
|
||||
desired.freq = myAudioSettings.sampleRate();
|
||||
desired.format = AUDIO_F32SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize());
|
||||
desired.callback = callback;
|
||||
desired.userdata = static_cast<void*>(this);
|
||||
|
||||
myDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &myHardwareSpec,
|
||||
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
|
||||
if(myDevice == 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
buf << "WARNING: Couldn't open SDL audio device! " << endl
|
||||
<< " " << SDL_GetError() << endl;
|
||||
myOSystem.logMessage(buf.str(), 0);
|
||||
SDL_zero(myHardwareSpec);
|
||||
if(!openDevice())
|
||||
return;
|
||||
}
|
||||
|
||||
myIsInitializedFlag = true;
|
||||
|
||||
mute(true);
|
||||
|
||||
|
@ -95,6 +72,35 @@ SoundSDL2::~SoundSDL2()
|
|||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL2::openDevice()
|
||||
{
|
||||
SDL_AudioSpec desired;
|
||||
desired.freq = myAudioSettings.sampleRate();
|
||||
desired.format = AUDIO_F32SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize());
|
||||
desired.callback = callback;
|
||||
desired.userdata = static_cast<void*>(this);
|
||||
|
||||
if(myIsInitializedFlag)
|
||||
SDL_CloseAudioDevice(myDevice);
|
||||
myDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &myHardwareSpec,
|
||||
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
|
||||
if(myDevice == 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
buf << "WARNING: Couldn't open SDL audio device! " << endl
|
||||
<< " " << SDL_GetError() << endl;
|
||||
myOSystem.logMessage(buf.str(), 0);
|
||||
|
||||
return myIsInitializedFlag = false;
|
||||
}
|
||||
return myIsInitializedFlag = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::setEnabled(bool state)
|
||||
{
|
||||
|
@ -109,6 +115,12 @@ void SoundSDL2::setEnabled(bool state)
|
|||
void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
|
||||
EmulationTiming* emulationTiming)
|
||||
{
|
||||
// Do we need to re-open the sound device?
|
||||
// Only do this when absolutely necessary
|
||||
if(myAudioSettings.sampleRate() != uInt32(myHardwareSpec.freq) ||
|
||||
myAudioSettings.fragmentSize() != uInt32(myHardwareSpec.samples))
|
||||
openDevice();
|
||||
|
||||
myEmulationTiming = emulationTiming;
|
||||
|
||||
myOSystem.logMessage("SoundSDL2::open started ...", 2);
|
||||
|
@ -128,18 +140,32 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
|
|||
// Adjust volume to that defined in settings
|
||||
setVolume(myAudioSettings.volume());
|
||||
|
||||
initResampler();
|
||||
|
||||
// Show some info
|
||||
ostringstream buf;
|
||||
buf << "Sound enabled:" << endl
|
||||
<< " Volume: " << myVolume << endl
|
||||
<< " Frag size: " << uInt32(myHardwareSpec.samples) << endl
|
||||
<< " Frequency: " << uInt32(myHardwareSpec.freq) << endl
|
||||
<< " Channels: " << uInt32(myHardwareSpec.channels)
|
||||
<< endl;
|
||||
<< " Channels: " << uInt32(myHardwareSpec.channels) << endl
|
||||
<< " Resampling: ";
|
||||
switch (myAudioSettings.resamplingQuality()) {
|
||||
case AudioSettings::ResamplingQuality::nearestNeightbour:
|
||||
buf << "quality 1, nearest neighbor" << endl;
|
||||
break;
|
||||
case AudioSettings::ResamplingQuality::lanczos_2:
|
||||
buf << "quality 2, nearest Lanczos (a = 2)" << endl;
|
||||
break;
|
||||
case AudioSettings::ResamplingQuality::lanczos_3:
|
||||
buf << "quality 3, nearest Lanczos (a = 3)" << endl;
|
||||
break;
|
||||
default:
|
||||
buf << "unknown resampler" << endl;
|
||||
break;
|
||||
}
|
||||
myOSystem.logMessage(buf.str(), 1);
|
||||
|
||||
initResampler();
|
||||
|
||||
// And start the SDL sound subsystem ...
|
||||
mute(false);
|
||||
|
||||
|
@ -158,7 +184,6 @@ void SoundSDL2::close()
|
|||
myCurrentFragment = nullptr;
|
||||
|
||||
myOSystem.logMessage("SoundSDL2::close", 2);
|
||||
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -170,11 +195,6 @@ void SoundSDL2::mute(bool state)
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::reset()
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::setVolume(uInt32 percent)
|
||||
{
|
||||
|
@ -262,16 +282,13 @@ void SoundSDL2::initResampler()
|
|||
switch (myAudioSettings.resamplingQuality()) {
|
||||
case AudioSettings::ResamplingQuality::nearestNeightbour:
|
||||
myResampler = make_unique<SimpleResampler>(formatFrom, formatTo, nextFragmentCallback);
|
||||
(cerr << "resampling quality 1: using nearest neighbor resampling\n").flush();
|
||||
break;
|
||||
|
||||
case AudioSettings::ResamplingQuality::lanczos_2:
|
||||
(cerr << "resampling quality 2: using nearest Lanczos resampling, a = 2\n").flush();
|
||||
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 2);
|
||||
break;
|
||||
|
||||
case AudioSettings::ResamplingQuality::lanczos_3:
|
||||
(cerr << "resampling quality 3: using nearest Lanczos resampling, a = 3\n").flush();
|
||||
myResampler = make_unique<LanczosResampler>(formatFrom, formatTo, nextFragmentCallback, 3);
|
||||
break;
|
||||
|
||||
|
|
|
@ -77,11 +77,6 @@ class SoundSDL2 : public Sound
|
|||
*/
|
||||
void mute(bool state) override;
|
||||
|
||||
/**
|
||||
Reset the sound device.
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
volume is given as a percentage from 0 to 100. Values outside
|
||||
|
@ -115,6 +110,12 @@ class SoundSDL2 : public Sound
|
|||
void processFragment(float* stream, uInt32 length);
|
||||
|
||||
private:
|
||||
/**
|
||||
The actual sound device is opened only when absolutely necessary.
|
||||
Typically this will only happen once per program run, but it can also
|
||||
happen dynamically when changing sample rate and/or fragment size.
|
||||
*/
|
||||
bool openDevice();
|
||||
|
||||
void initResampler();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "StateManager.hxx"
|
||||
|
||||
#define STATE_HEADER "05099000state"
|
||||
#define STATE_HEADER "05099100state"
|
||||
// #define MOVIE_HEADER "03030000movie"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef VERSION_HXX
|
||||
#define VERSION_HXX
|
||||
|
||||
#define STELLA_VERSION "6.0_pre1"
|
||||
#define STELLA_BUILD "4434"
|
||||
#define STELLA_VERSION "6.0_beta1"
|
||||
#define STELLA_BUILD "4514"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -589,16 +589,12 @@ void Console::initializeAudio()
|
|||
myOSystem.sound().close();
|
||||
|
||||
myEmulationTiming
|
||||
.updatePlaybackRate(myOSystem.sound().getSampleRate())
|
||||
.updatePlaybackPeriod(myOSystem.sound().getFragmentSize())
|
||||
.updatePlaybackRate(myAudioSettings.sampleRate())
|
||||
.updatePlaybackPeriod(myAudioSettings.fragmentSize())
|
||||
.updateAudioQueueExtraFragments(myAudioSettings.bufferSize())
|
||||
.updateAudioQueueHeadroom(myAudioSettings.headroom())
|
||||
.updateSpeedFactor(myOSystem.settings().getFloat("speed"));
|
||||
|
||||
(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();
|
||||
myTIA->setAudioQueue(myAudioQueue);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class Sound
|
|||
{
|
||||
public:
|
||||
/**
|
||||
Create a new sound object. The init method must be invoked before
|
||||
Create a new sound object. The open method must be invoked before
|
||||
using the object.
|
||||
*/
|
||||
Sound(OSystem& osystem) : myOSystem(osystem) { }
|
||||
|
@ -77,11 +77,6 @@ class Sound
|
|||
*/
|
||||
virtual uInt32 getSampleRate() const = 0;
|
||||
|
||||
/**
|
||||
Reset the sound device.
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
volume is given as a percentage from 0 to 100. Values outside
|
||||
|
|
Loading…
Reference in New Issue