Switch to F32 samples, make volume scale more linear in sound..

This commit is contained in:
Christian Speckner 2018-05-10 23:53:30 +02:00
parent cea1c011be
commit b329c7ff5f
5 changed files with 24 additions and 33 deletions

View File

@ -32,13 +32,6 @@
#include "EmulationTiming.hxx"
#include "audio/SimpleResampler.hxx"
namespace {
inline Int16 applyVolume(Int16 sample, Int32 volumeFactor)
{
return static_cast<Int16>(static_cast<Int32>(sample) * volumeFactor / 0xffff);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL2::SoundSDL2(OSystem& osystem)
: Sound(osystem),
@ -50,20 +43,13 @@ SoundSDL2::SoundSDL2(OSystem& osystem)
{
myOSystem.logMessage("SoundSDL2::SoundSDL2 started ...", 2);
#ifdef BSPF_WINDOWS
// TODO - remove the following code once we convert to the new sound
// core, and use 32-bit floating point samples and do
// our own resampling
SDL_setenv("SDL_AUDIODRIVER", "directsound", true);
#endif
// 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 = myOSystem.settings().getInt("freq");
desired.format = AUDIO_S16SYS;
desired.format = AUDIO_F32SYS;
desired.channels = 2;
desired.samples = myOSystem.settings().getInt("fragsize");
desired.callback = callback;
@ -191,7 +177,7 @@ void SoundSDL2::setVolume(Int32 percent)
myVolume = percent;
SDL_LockAudio();
myVolumeFactor = static_cast<Int32>(floor(static_cast<double>(0xffff) * static_cast<double>(myVolume) / 100.));
myVolumeFactor = std::pow(static_cast<float>(percent) / 100.f, 2.f);
SDL_UnlockAudio();
}
}
@ -235,11 +221,11 @@ uInt32 SoundSDL2::getSampleRate() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL2::processFragment(Int16* stream, uInt32 length)
void SoundSDL2::processFragment(float* stream, uInt32 length)
{
myResampler->fillFragment(stream, length);
for (uInt32 i = 0; i < length; i++) stream[i] = applyVolume(stream[i], myVolumeFactor);
for (uInt32 i = 0; i < length; i++) stream[i] = stream[i] * myVolumeFactor;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -272,7 +258,7 @@ void SoundSDL2::callback(void* udata, uInt8* stream, int len)
SoundSDL2* self = static_cast<SoundSDL2*>(udata);
if (self->myAudioQueue)
self->processFragment(reinterpret_cast<Int16*>(stream), len >> 1);
self->processFragment(reinterpret_cast<float*>(stream), len >> 2);
else
SDL_memset(stream, 0, len);
}

View File

@ -111,7 +111,7 @@ class SoundSDL2 : public Sound
@param stream Pointer to the start of the fragment
@param length Length of the fragment
*/
void processFragment(Int16* stream, uInt32 length);
void processFragment(float* stream, uInt32 length);
private:
@ -123,7 +123,7 @@ class SoundSDL2 : public Sound
// Current volume as a percentage (0 - 100)
uInt32 myVolume;
Int32 myVolumeFactor;
float myVolumeFactor;
// Audio specification structure
SDL_AudioSpec myHardwareSpec;

View File

@ -55,7 +55,7 @@ class Resampler {
myNextFragmentCallback(nextFragmentCallback)
{}
virtual void fillFragment(Int16* fragment, uInt32 length) = 0;
virtual void fillFragment(float* fragment, uInt32 length) = 0;
virtual ~Resampler() {}

View File

@ -31,7 +31,7 @@ SimpleResampler::SimpleResampler(
{}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SimpleResampler::fillFragment(Int16* fragment, uInt32 length)
void SimpleResampler::fillFragment(float* fragment, uInt32 length)
{
if (myIsUnderrun) {
Int16* nextFragment = myNextFragmentCallback();
@ -44,7 +44,7 @@ void SimpleResampler::fillFragment(Int16* fragment, uInt32 length)
}
if (!myCurrentFragment) {
memset(fragment, 0, 2 * length);
memset(fragment, 0, sizeof(float) * length);
return;
}
@ -74,18 +74,23 @@ void SimpleResampler::fillFragment(Int16* fragment, uInt32 length)
}
}
if (myFormatTo.stereo) {
if (myFormatFrom.stereo) {
fragment[2*i] = myCurrentFragment[2*myFragmentIndex];
fragment[2*i + 1] = myCurrentFragment[2*myFragmentIndex + 1];
if (myFormatFrom.stereo) {
float sampleL = static_cast<float>(myCurrentFragment[2*myFragmentIndex]) / static_cast<float>(0x7fff);
float sampleR = static_cast<float>(myCurrentFragment[2*myFragmentIndex + 1]) / static_cast<float>(0x7fff);
if (myFormatTo.stereo) {
fragment[2*i] = sampleL;
fragment[2*i + 1] = sampleR;
}
else
fragment[2*i] = fragment[2*i + 1] = myCurrentFragment[myFragmentIndex];
fragment[i] = (sampleL + sampleR) / 2.f;
} else {
if (myFormatFrom.stereo)
fragment[i] = (myCurrentFragment[2*myFragmentIndex] / 2) + (myCurrentFragment[2*myFragmentIndex + 1] / 2);
float sample = static_cast<float>(myCurrentFragment[myFragmentIndex] / static_cast<float>(0x7fff));
if (myFormatTo.stereo)
fragment[2*i] = fragment[2*i + 1] = sample;
else
fragment[i] = myCurrentFragment[myFragmentIndex];
fragment[i] = sample;
}
}
}

View File

@ -28,7 +28,7 @@ class SimpleResampler : public Resampler {
Resampler::NextFragmentCallback NextFragmentCallback
);
virtual void fillFragment(Int16* fragment, uInt32 length);
virtual void fillFragment(float* fragment, uInt32 length);
private: