Updated the SoundSDL class to use the new TIA sound emulation library. The

class supports stereo sound output; however, to switch to stereo mode you
currently have to change desired.channels to 2 instead of 1 in the code.
Eventually, we need a setting to enable this and it might be nice to have
a "stella.pro" value for defaults.  Games like Skeleton+ and Synthcart
support stereo output so setting their values to "STEREO" would be good
and having the default be "MONO".

I'm also checking in an updated VC++ project file; however, the other
makefiles will need to be updated to remove TIASound.c and add TIASnd.cxx
to the build


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@765 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
bwmott 2005-09-04 23:59:30 +00:00
parent 28946ba589
commit df183c6e35
3 changed files with 81 additions and 49 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SoundSDL.cxx,v 1.21 2005-08-25 16:29:52 stephena Exp $
// $Id: SoundSDL.cxx,v 1.22 2005-09-04 23:59:30 bwmott Exp $
//============================================================================
#ifdef SOUND_SUPPORT
@ -30,6 +30,7 @@
#include "Settings.hxx"
#include "System.hxx"
#include "OSystem.hxx"
#include "TIASnd.hxx"
#include "SoundSDL.hxx"
@ -38,8 +39,11 @@ SoundSDL::SoundSDL(OSystem* osystem)
: Sound(osystem),
myIsEnabled(osystem->settings().getBool("sound")),
myIsInitializedFlag(false),
myLastRegisterSetCycle(0),
myDisplayFrameRate(60),
myFragmentSizeLogBase2(0),
myIsMuted(false)
myIsMuted(false),
myVolume(100)
{
initialize(true);
}
@ -52,10 +56,10 @@ SoundSDL::~SoundSDL()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::setEnabled(bool enable)
void SoundSDL::setEnabled(bool state)
{
myIsEnabled = enable;
myOSystem->settings().setBool("sound", enable);
myIsEnabled = state;
myOSystem->settings().setBool("sound", state);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -72,16 +76,13 @@ void SoundSDL::initialize(bool forcerestart)
// Clear the sound queue FIXME - still an annoying partial sound playing?
SDL_PauseAudio(1);
Tia_clear_registers();
myRegWriteQueue.clear();
SDL_PauseAudio(0);
myTIASound.reset();
if(forcerestart && myIsInitializedFlag)
closeAudio();
bool isAlreadyInitialized = (SDL_WasInit(SDL_INIT_AUDIO) & SDL_INIT_AUDIO) > 0;
if(!isAlreadyInitialized)
if(!((SDL_WasInit(SDL_INIT_AUDIO) & SDL_INIT_AUDIO) > 0))
{
myIsInitializedFlag = false;
myIsMuted = false;
@ -105,8 +106,7 @@ void SoundSDL::initialize(bool forcerestart)
desired.freq = 44100;
desired.format = AUDIO_U16;
#endif
desired.channels = 1;
desired.channels = 1; // Set to 2 for stereo TIA sound support
desired.samples = fragsize;
desired.callback = callback;
desired.userdata = (void*)this;
@ -134,20 +134,18 @@ void SoundSDL::initialize(bool forcerestart)
myIsMuted = false;
myFragmentSizeLogBase2 = log((double)myHardwareSpec.samples) / log(2.0);
/*
/*
cerr << "Freq: " << (int)myHardwareSpec.freq << endl;
cerr << "Format: " << (int)myHardwareSpec.format << endl;
cerr << "Channels: " << (int)myHardwareSpec.channels << endl;
cerr << "Silence: " << (int)myHardwareSpec.silence << endl;
cerr << "Samples: " << (int)myHardwareSpec.samples << endl;
cerr << "Size: " << (int)myHardwareSpec.size << endl;
*/
*/
// Now initialize the TIASound object which will actually generate sound
Tia_sound_init(desired.freq, myHardwareSpec.freq);
// And start the SDL sound subsystem ...
SDL_PauseAudio(0);
myTIASound.outputFrequency(myHardwareSpec.freq);
myTIASound.channels(myHardwareSpec.channels);
// Adjust volume to that defined in settings
myVolume = myOSystem->settings().getInt("volume");
@ -160,6 +158,12 @@ void SoundSDL::initialize(bool forcerestart)
<< " Frag size: " << fragsize << endl << endl;
}
}
// And start the SDL sound subsystem ...
if(myIsInitializedFlag)
{
SDL_PauseAudio(0);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -209,7 +213,7 @@ void SoundSDL::setVolume(Int32 percent)
myOSystem->settings().setInt("volume", percent);
SDL_LockAudio();
myVolume = percent;
Tia_volume(percent);
myTIASound.volume(percent);
SDL_UnlockAudio();
}
}
@ -250,6 +254,7 @@ void SoundSDL::adjustCycleCounter(Int32 amount)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::setFrameRate(uInt32 framerate)
{
// FIXME, we should clear out the queue or adjust the values in it
myDisplayFrameRate = framerate;
myLastRegisterSetCycle = 0;
}
@ -264,11 +269,11 @@ void SoundSDL::set(uInt16 addr, uInt8 value, Int32 cycle)
double delta = (((double)(cycle - myLastRegisterSetCycle)) /
(1193191.66666667));
// Now, adjust the time based on the frame rate the user has selected
// FIXME - not sure this is needed anymore, since the display framerate
// and sound framerate are always locked in sync; hence 1:1
delta = delta * (myDisplayFrameRate / 60.0);//FIXME (double)myOSystem->console().frameRate());
// Now, adjust the time based on the frame rate the user has selected. For
// the sound to "scale" correctly, we have to know the games real frame
// rate (e.g., 50 or 60) and the currently emulated frame rate. We use these
// values to "scale" the time before the register change occurs.
delta = delta * (myDisplayFrameRate / (double)myOSystem->frameRate());
RegWrite info;
info.addr = addr;
info.value = value;
@ -287,15 +292,19 @@ void SoundSDL::processFragment(uInt8* stream, Int32 length)
if(!myIsInitializedFlag)
return;
uInt32 channels = myHardwareSpec.channels;
length = length / channels;
// If there are excessive items on the queue then we'll remove some
if(myRegWriteQueue.duration() > (myFragmentSizeLogBase2 / myDisplayFrameRate))
if(myRegWriteQueue.duration() >
(myFragmentSizeLogBase2 / myDisplayFrameRate))
{
double removed = 0.0;
while(removed < ((myFragmentSizeLogBase2 - 1) / myDisplayFrameRate))
{
RegWrite& info = myRegWriteQueue.front();
removed += info.delta;
Update_tia_sound(info.addr, info.value);
myTIASound.set(info.addr, info.value);
myRegWriteQueue.dequeue();
}
// cout << "Removed Items from RegWriteQueue!" << endl;
@ -310,7 +319,9 @@ void SoundSDL::processFragment(uInt8* stream, Int32 length)
{
// There are no more pending TIA sound register updates so we'll
// use the current settings to finish filling the sound fragment
Tia_process(stream + (uInt32)position, length - (uInt32)position);
// myTIASound.process(stream + (uInt32)position, length - (uInt32)position);
myTIASound.process(stream + ((uInt32)position * channels),
length - (uInt32)position);
// Since we had to fill the fragment we'll reset the cycle counter
// to zero. NOTE: This isn't 100% correct, however, it'll do for
@ -325,7 +336,7 @@ void SoundSDL::processFragment(uInt8* stream, Int32 length)
// update the sound buffer to the point of the next register update
RegWrite& info = myRegWriteQueue.front();
// How long will the remaing samples in the fragment take to play
// How long will the remaining samples in the fragment take to play
double duration = remaining / (double)myHardwareSpec.freq;
// Does the register update occur before the end of the fragment?
@ -336,15 +347,19 @@ void SoundSDL::processFragment(uInt8* stream, Int32 length)
if(info.delta > 0.0)
{
// Process the fragment upto the next TIA register write. We
// round the count passed to Tia_process up if needed.
// round the count passed to process up if needed.
double samples = (myHardwareSpec.freq * info.delta);
Tia_process(stream + (uInt32)position, (uInt32)samples +
(uInt32)(position + samples) -
// myTIASound.process(stream + (uInt32)position, (uInt32)samples +
// (uInt32)(position + samples) -
// ((uInt32)position + (uInt32)samples));
myTIASound.process(stream + ((uInt32)position * channels),
(uInt32)samples + (uInt32)(position + samples) -
((uInt32)position + (uInt32)samples));
position += samples;
remaining -= samples;
}
Update_tia_sound(info.addr, info.value);
myTIASound.set(info.addr, info.value);
myRegWriteQueue.dequeue();
}
else
@ -352,7 +367,9 @@ void SoundSDL::processFragment(uInt8* stream, Int32 length)
// The next register update occurs in the next fragment so finish
// this fragment with the current TIA settings and reduce the register
// update delay by the corresponding amount of time
Tia_process(stream + (uInt32)position, length - (uInt32)position);
// myTIASound.process(stream + (uInt32)position, length - (uInt32)position);
myTIASound.process(stream + ((uInt32)position * channels),
length - (uInt32)position);
info.delta -= duration;
break;
}
@ -404,7 +421,12 @@ bool SoundSDL::load(Deserializer& in)
{
SDL_PauseAudio(1);
myRegWriteQueue.clear();
Tia_set_registers(reg1, reg2, reg3, reg4, reg5, reg6);
myTIASound.set(0x15, reg1);
myTIASound.set(0x16, reg2);
myTIASound.set(0x17, reg3);
myTIASound.set(0x18, reg4);
myTIASound.set(0x19, reg5);
myTIASound.set(0x1a, reg6);
SDL_PauseAudio(0);
}
}
@ -435,7 +457,14 @@ bool SoundSDL::save(Serializer& out)
// Only get the TIA sound registers if sound is enabled
if(myIsInitializedFlag)
Tia_get_registers(&reg1, &reg2, &reg3, &reg4, &reg5, &reg6);
{
reg1 = myTIASound.get(0x15);
reg2 = myTIASound.get(0x16);
reg3 = myTIASound.get(0x17);
reg4 = myTIASound.get(0x18);
reg5 = myTIASound.get(0x19);
reg6 = myTIASound.get(0x1a);
}
out.putLong(reg1);
out.putLong(reg2);
@ -547,4 +576,4 @@ void SoundSDL::RegWriteQueue::grow()
myBuffer = buffer;
}
#endif // SOUND_SUPPORT
#endif // SOUND_SUPPORT

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SoundSDL.hxx,v 1.13 2005-06-28 23:18:15 stephena Exp $
// $Id: SoundSDL.hxx,v 1.14 2005-09-04 23:59:30 bwmott Exp $
//============================================================================
#ifndef SOUND_SDL_HXX
@ -28,12 +28,13 @@ class OSystem;
#include "Sound.hxx"
#include "bspf.hxx"
#include "MediaSrc.hxx"
#include "TIASnd.hxx"
/**
This class implements the sound API for SDL.
@author Stephen Anthony and Bradford W. Mott
@version $Id: SoundSDL.hxx,v 1.13 2005-06-28 23:18:15 stephena Exp $
@version $Id: SoundSDL.hxx,v 1.14 2005-09-04 23:59:30 bwmott Exp $
*/
class SoundSDL : public Sound
{
@ -53,12 +54,12 @@ class SoundSDL : public Sound
/**
Enables/disables the sound subsystem.
@param enable Either true or false, to enable or disable the sound system
@param state True or false, to enable or disable the sound system
*/
void setEnabled(bool enable);
void setEnabled(bool state);
/**
The system cycle counter is being adjusting by the specified amount. Any
The system cycle counter is being adjusting by the specified amount. Any
members using the system cycle counter should be adjusted as needed.
@param amount The amount the cycle counter is being adjusted by
@ -121,8 +122,8 @@ class SoundSDL : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 =decrease)
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 = decrease)
*/
void adjustVolume(Int8 direction);
@ -228,6 +229,9 @@ class SoundSDL : public Sound
};
private:
// TIASound emulation object
TIASound myTIASound;
// Indicates if the sound subsystem is to be initialized
bool myIsEnabled;
@ -237,7 +241,7 @@ class SoundSDL : public Sound
// Indicates the cycle when a sound register was last set
Int32 myLastRegisterSetCycle;
// Indicates the base framerate depending on whether the ROM is NTSC or PAL
// Indicates the base framerate depending on if the ROM is NTSC or PAL
uInt32 myDisplayFrameRate;
// Log base 2 of the selected fragment size
@ -264,5 +268,4 @@ class SoundSDL : public Sound
};
#endif // SOUND_SUPPORT
#endif

View File

@ -21,7 +21,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\yacc;..\debugger;..\gui;..\emucore\m6502\src\bspf\src;..\emucore\m6502\src;..\emucore;..\common;..\win32;..\debugger\gui"
PreprocessorDefinitions="BSPF_WIN32;WIN32;_DEBUG;JOYSTICK_SUPPORT;DEVELOPER_SUPPORT;SNAPSHOT_SUPPORT;DISPLAY_OPENGL;TEXTURES_ARE_LOST;SOUND_SUPPORT"
PreprocessorDefinitions="BSPF_WIN32;WIN32;_DEBUG;JOYSTICK_SUPPORT;DEVELOPER_SUPPORT;DISPLAY_OPENGL;TEXTURES_ARE_LOST;SNAPSHOT_SUPPORT;SOUND_SUPPORT"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
@ -37,7 +37,7 @@
SDLmain.lib
libpng.lib
opengl32.lib"
AdditionalDependencies="sdl.lib sdlmain.lib libpng.lib opengl32.lib"
AdditionalDependencies="sdl.lib sdlmain.lib libpng.lib opengl32.lib zdll.lib"
OutputFile="$(OutDir)/Stella.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
@ -536,7 +536,7 @@ opengl32.lib"
RelativePath="..\debugger\gui\TiaOutputWidget.cxx">
</File>
<File
RelativePath="..\emucore\TIASound.c">
RelativePath="..\emucore\TIASnd.cxx">
</File>
<File
RelativePath="..\debugger\gui\TiaWidget.cxx">
@ -1021,7 +1021,7 @@ opengl32.lib"
RelativePath="..\debugger\gui\TiaOutputWidget.hxx">
</File>
<File
RelativePath="..\emucore\TIASound.h">
RelativePath="..\emucore\TIASnd.hxx">
</File>
<File
RelativePath="..\debugger\TiaWidget.hxx">