The sound system is now opened once per program invocation, and paused

when it isn't needed.  According to SDL this shouldn't be necessary, but
some combinations of video modes and audio hardware cause sound to stop
working if it's repeatedly opened and closed.  So we have to keep it open.

Always attempt to use 2 channels (aka stereo) when opening the SDL audio
device.  This is now required, since ROMs can request mono or stereo mode,
and the sound system can no longer be closed and re-opened with the
desired settings.  So we need to always use 2 channels to accommodate
when it might be needed.  This actually more closely emulates the 2600,
which does have two audio channels.  The 'mono' vs 'stereo' ROM property
basically controls whether these channels are exposed (ie, does the
virtual console have two-channel audio hardware installed).  In that sense,
these settings control how the channels are mixed.

Updated some settings to have more reasonable defaults.

Added acknowledgement for people that have donated hardware to help with
development.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2291 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2011-12-21 17:18:53 +00:00
parent 9d93318450
commit 56694b5934
18 changed files with 257 additions and 213 deletions

View File

@ -14,27 +14,30 @@
3.4.1 to 3.5: (December xx, 2011)
FIXME (will I have time for this?)
* Replaced NTSC TV filtering with Blargg NTSC filters. These filters
work in OpenGL mode only, but in contrast to the old filters, they
now work with OpenGL 1.x / OpenGL ES.
* Added several improvements to the joystick management code. Joystick
event mapping is now saved per device, meaning that if you map events
to a certain joystick device, remove the device and then later insert
it again, Stella will remember the original mapping.
* The total number of joysticks present and their associated properties
(number of axes, buttons, hats, etc) is now dynamic. That is, there's
no longer a hard-coded limit on number of joysticks that Stella can
use, or the number of buttons, etc that it contains. This fixes a
serious bug with PS3 controllers with 27 buttons, whereby adding a
(number of axes, buttons and hats) is now dynamic. That is, there's
no longer a hard-coded limit on the number of joysticks that Stella
can use, or the number of buttons, etc that it contains. This fixes
a serious bug with PS3 controllers with 27 buttons, whereby adding a
mapping for joystick 0 would inadvertantly change settings for
joystick 1, and could potentially lead to a segfault.
joystick 1, and could potentially lead to a program crash.
* Huge restructuring of the OpenGL code, making it compatible with
OpenGL 2.x+ features (such as vertex buffer objects), while at the
same time keeping compatibility with OpenGL 1.5 / OpenGL ES.
Because of the required changes, TV effects were removed (they will
be added again for the next release).
* Improvements to audio handling, particularly for certain cases of
Windows, ATI video cards, and OpenGL mode. The sound device is now
opened only once when Stella starts, and is paused between loading
different ROMs. This fixes a problem whereby sound could possibly
not be functional after loading the first ROM.
* Added logging facility, whereby the output of the application is
available within Stella itself. This can still be printed to the
@ -56,7 +59,7 @@
can be disabled by developers for testing reasons.
* Updated default snapshot directory to be much saner and easier to
find. For most systems, it now defaults to the users 'Desktop.
find. For most systems, it now defaults to the users 'Desktop'.
Note that the commandline argument has changed to 'snapdir'.
* The debugger 'print' command now indicates "special" addresses if
@ -72,6 +75,9 @@
* Updated include PNG library to latest stable version.
* Updated the credits list in the documentation, listing people that
have donated hardware to the Stella team.
-Have fun!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -267,7 +267,7 @@
<li>Supports EEPROM emulation for <a href="http://www.richard.hutchinson.dsl.pipex.com/new_page_5.htm">
AtariVox</a> and <a href="http://www.vectrex.biz/MemCard.htm">SaveKey</a> controllers</li>
<li>Supports all known bankswitching schemes (let us know if there's one we missed)</li>
<li>Supports DPC+ bankswitching scheme from the Harmony cart, including emulation of the ARM processor</li>
<li>Supports DPC+ bankswitching scheme from the Harmony cart, including partial emulation of the ARM processor</li>
<li>Supports cartridge autodetection for almost all bankswitching schemes</li>
<li>Supports Supercharger single-load and multi-load games</li>
<li>Supports ROMs stored in ZIP and GZIP format, as well as the usual A26/BIN/ROM formats</li>
@ -2232,8 +2232,8 @@
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Volume</td><td>self-explanatory</td><td>-volume</td></tr>
<tr><td>Fragment size</td><td>set size of audio buffers</td><td>-fragsize</td></tr>
<tr><td>Output freq</td><td>change sound output frequency (advanced)</td><td>-freq</td></tr>
<tr><td>Sample size (*)</td><td>set size of audio buffers</td><td>-fragsize</td></tr>
<tr><td>Output freq (*)</td><td>change sound output frequency (advanced)</td><td>-freq</td></tr>
<tr><td>TIA freq</td><td>change TIA output frequency (advanced)</td><td>-tiafreq</td></tr>
<tr><td>Clip volume</td><td>Eliminate popping in sound generation (advanced)</td><td>-clipvol</td></tr>
<tr><td>Enable sound</td><td>self-explanatory</td><td>-sound</td></tr>
@ -3263,6 +3263,12 @@ Ms Pac-Man (Stella extended codes):
<td>Provided technical information on the Supercharger</td>
</tr>
<tr>
<td VALIGN="TOP">"Uncle"&nbsp;Carmine<br>
(<a href="http://www.carmine.com">http://www.carmine.com</a>)</td>
<td>Generously donated several 2600 games and manuals to help with development</td>
</tr>
<tr>
<td VALIGN="TOP">Piero&nbsp;Cavina</td>
<td>Allowed "Oystron" to be included in the Stella distribution</td>
@ -3344,6 +3350,12 @@ Ms Pac-Man (Stella extended codes):
in testing ROMs on a real system</td>
</tr>
<tr>
<td VALIGN="TOP">Nick&nbsp;Montfort and Ian&nbsp;Bogost<br>
(<a href="http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=11696">Racing the Beam</a>)</td>
<td>Specifically mentioned Stella in their book</td>
</tr>
<tr>
<td VALIGN="TOP">Kostas&nbsp;Nakos</td>
<td>Author/maintainer of the WinCE version of Stella from releases 2.0
@ -3413,6 +3425,12 @@ Ms Pac-Man (Stella extended codes):
<td>Author of the "Game Menu" emulator game shell</td>
</tr>
<tr>
<td VALIGN="TOP">James&nbsp;Randall aka&nbsp;'toymailman'</td>
<td>Generously donated a 7800 console and several games and manuals to help
with development</td>
</tr>
<tr>
<td VALIGN="TOP">RomHunter<br>(<a href="http://www.atarimania.com/roms-MENU-2.html">RomHunter ROMs</a>)</td>
<td>Provides an updated database of ROM information on a regular basis</td>
@ -3536,7 +3554,7 @@ Ms Pac-Man (Stella extended codes):
<tr>
<td VALIGN="TOP">Albert&nbsp;Yarusso<br>
<a href="http://atariage.com">http://atariage.com</a></td>
(<a href="http://atariage.com">http://atariage.com</a>)</td>
<td>Provided helpful feedback for the MacOSX port, and generously
donated an AtariVox device to help with development</td>
</tr>

View File

@ -69,15 +69,15 @@ string FrameBufferSoft::about() const
{
ostringstream buf;
buf << "Video rendering: Software mode" << endl
buf << "Video rendering: Software mode" << endl << setfill('0')
<< " Color: " << (int)myFormat->BitsPerPixel << " bit" << endl
<< " Rmask = " << hex << setw(4) << (int)myFormat->Rmask
<< " Rmask = " << hex << setw(8) << (int)myFormat->Rmask
<< ", Rshift = "<< dec << setw(2) << (int)myFormat->Rshift
<< ", Rloss = " << dec << setw(2) << (int)myFormat->Rloss << endl
<< " Gmask = " << hex << setw(4) << (int)myFormat->Gmask
<< " Gmask = " << hex << setw(8) << (int)myFormat->Gmask
<< ", Gshift = "<< dec << setw(2) << (int)myFormat->Gshift
<< ", Gloss = " << dec << setw(2) << (int)myFormat->Gloss << endl
<< " Bmask = " << hex << setw(4) << (int)myFormat->Bmask
<< " Bmask = " << hex << setw(8) << (int)myFormat->Bmask
<< ", Bshift = "<< dec << setw(2) << (int)myFormat->Bshift
<< ", Bloss = " << dec << setw(2) << (int)myFormat->Bloss << endl;

View File

@ -90,13 +90,6 @@ class SoundNull : public Sound
*/
void close() { }
/**
Return true iff the sound device was successfully initialized.
@return true iff the sound device was successfully initialized.
*/
bool isSuccessfullyInitialized() const { return false; }
/**
Set the mute state of the sound object. While muted no sound is played.

View File

@ -35,39 +35,88 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL::SoundSDL(OSystem* osystem)
: Sound(osystem),
myIsEnabled(osystem->settings().getBool("sound")),
myIsEnabled(false),
myIsInitializedFlag(false),
myLastRegisterSetCycle(0),
myDisplayFrameRate(60.0),
myNumChannels(1),
myNumChannels(0),
myFragmentSizeLogBase2(0),
myIsMuted(false),
myIsMuted(true),
myVolume(100)
{
myOSystem->logMessage("SoundSDL::SoundSDL started ...\n", 2);
// 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_U8;
desired.channels = 2;
desired.samples = myOSystem->settings().getInt("fragsize");
desired.callback = callback;
desired.userdata = (void*)this;
ostringstream buf;
if(SDL_OpenAudio(&desired, &myHardwareSpec) < 0)
{
buf << "WARNING: Couldn't open SDL audio system! " << endl
<< " " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
return;
}
// Make sure the sample buffer isn't to big (if it is the sound code
// will not work so we'll need to disable the audio support)
if(((float)myHardwareSpec.samples / (float)myHardwareSpec.freq) >= 0.25)
{
buf << "WARNING: Sound device doesn't support realtime audio! Make "
<< "sure a sound" << endl
<< " server isn't running. Audio is disabled." << endl;
myOSystem->logMessage(buf.str(), 0);
SDL_CloseAudio();
return;
}
myIsInitializedFlag = true;
SDL_PauseAudio(1);
myOSystem->logMessage("SoundSDL::SoundSDL initialized\n", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL::~SoundSDL()
{
// Close the SDL audio system if it's initialized
close();
if(myIsInitializedFlag)
{
SDL_CloseAudio();
myIsEnabled = myIsInitializedFlag = false;
}
myOSystem->logMessage("SoundSDL destroyed\n", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::setEnabled(bool state)
{
myIsEnabled = state;
myOSystem->settings().setBool("sound", state);
myOSystem->logMessage(state ? "SoundSDL::setEnabled(true)\n" :
"SoundSDL::setEnabled(false)\n", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::open()
{
// Check whether to start the sound subsystem
if(!myIsEnabled)
myOSystem->logMessage("SoundSDL::open started ...\n", 2);
myIsEnabled = false;
mute(true);
if(!myIsInitializedFlag || !myOSystem->settings().getBool("sound"))
{
close();
myOSystem->logMessage("Sound disabled.\n\n", 1);
myOSystem->logMessage("Sound disabled\n\n", 1);
return;
}
@ -75,98 +124,48 @@ void SoundSDL::open()
myRegWriteQueue.clear();
myTIASound.reset();
if(SDL_WasInit(SDL_INIT_AUDIO) == 0)
{
myIsInitializedFlag = false;
myIsMuted = false;
myLastRegisterSetCycle = 0;
myFragmentSizeLogBase2 = log((double)myHardwareSpec.samples) / log(2.0);
uInt32 fragsize = myOSystem->settings().getInt("fragsize");
Int32 frequency = myOSystem->settings().getInt("freq");
Int32 tiafreq = myOSystem->settings().getInt("tiafreq");
// Now initialize the TIASound object which will actually generate sound
int tiafreq = myOSystem->settings().getInt("tiafreq");
myTIASound.outputFrequency(myHardwareSpec.freq);
myTIASound.tiaFrequency(tiafreq);
const string& chanResult =
myTIASound.channels(myHardwareSpec.channels, myNumChannels == 2);
SDL_AudioSpec desired;
desired.freq = frequency;
#ifndef GP2X
desired.format = AUDIO_U8;
#else
desired.format = AUDIO_U16;
#endif
desired.channels = myNumChannels;
desired.samples = fragsize;
desired.callback = callback;
desired.userdata = (void*)this;
bool clipvol = myOSystem->settings().getBool("clipvol");
myTIASound.clipVolume(clipvol);
ostringstream buf;
if(SDL_OpenAudio(&desired, &myHardwareSpec) < 0)
{
buf << "WARNING: Couldn't open SDL audio system! " << endl
<< " " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
return;
}
// Adjust volume to that defined in settings
myVolume = myOSystem->settings().getInt("volume");
setVolume(myVolume);
// Make sure the sample buffer isn't to big (if it is the sound code
// will not work so we'll need to disable the audio support)
if(((float)myHardwareSpec.samples / (float)myHardwareSpec.freq) >= 0.25)
{
buf << "WARNING: Sound device doesn't support realtime audio! Make "
<< "sure a sound" << endl
<< " server isn't running. Audio is disabled." << endl;
myOSystem->logMessage(buf.str(), 0);
SDL_CloseAudio();
return;
}
myIsInitializedFlag = true;
myIsMuted = false;
myFragmentSizeLogBase2 = log((double)myHardwareSpec.samples) / log(2.0);
// Now initialize the TIASound object which will actually generate sound
myTIASound.outputFrequency(myHardwareSpec.freq);
myTIASound.tiaFrequency(tiafreq);
myTIASound.channels(myHardwareSpec.channels);
bool clipvol = myOSystem->settings().getBool("clipvol");
myTIASound.clipVolume(clipvol);
// Adjust volume to that defined in settings
myVolume = myOSystem->settings().getInt("volume");
setVolume(myVolume);
// Show some info
buf << "Sound enabled:" << endl
<< " Volume: " << myVolume << endl
<< " Frag size: " << fragsize << endl
<< " Frequency: " << myHardwareSpec.freq << endl
<< " Format: " << myHardwareSpec.format << endl
<< " TIA Freq: " << tiafreq << endl
<< " Channels: " << myNumChannels << endl
<< " Clip volume: " << (int)clipvol << endl
<< endl;
myOSystem->logMessage(buf.str(), 1);
}
// Show some info
ostringstream buf;
buf << "Sound enabled:" << endl
<< " Volume: " << (int)myVolume << endl
<< " Frag size: " << (int)myHardwareSpec.samples << endl
<< " Frequency: " << (int)myHardwareSpec.freq << endl
<< " Format: " << (int)myHardwareSpec.format << endl
<< " TIA Freq: " << (int)tiafreq << endl
<< " Channels: " << (int)myHardwareSpec.channels
<< " (" << chanResult << ")" << endl
<< " Clip volume: " << (clipvol ? "on" : "off") << endl
<< endl;
myOSystem->logMessage(buf.str(), 1);
// And start the SDL sound subsystem ...
if(myIsInitializedFlag)
SDL_PauseAudio(0);
myIsEnabled = true;
mute(false);
myOSystem->logMessage("SoundSDL::open finished\n", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::close()
{
if(myIsInitializedFlag)
{
SDL_CloseAudio();
myIsInitializedFlag = false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SoundSDL::isSuccessfullyInitialized() const
{
return myIsInitializedFlag;
mute(true);
myOSystem->logMessage("SoundSDL::close\n", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -175,9 +174,7 @@ void SoundSDL::mute(bool state)
if(myIsInitializedFlag)
{
myIsMuted = state;
SDL_PauseAudio(myIsMuted ? 1 : 0);
myRegWriteQueue.clear();
}
}
@ -283,7 +280,7 @@ void SoundSDL::set(uInt16 addr, uInt8 value, Int32 cycle)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::processFragment(uInt8* stream, Int32 length)
{
if(!myIsInitializedFlag)
if(!myIsEnabled)
return;
uInt32 channels = myHardwareSpec.channels;
@ -425,13 +422,12 @@ bool SoundSDL::load(Serializer& in)
if(in.getString() != name())
return false;
uInt8 reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg5 = 0, reg6 = 0;
reg1 = (uInt8) in.getByte();
reg2 = (uInt8) in.getByte();
reg3 = (uInt8) in.getByte();
reg4 = (uInt8) in.getByte();
reg5 = (uInt8) in.getByte();
reg6 = (uInt8) in.getByte();
uInt8 reg1 = (uInt8) in.getByte(),
reg2 = (uInt8) in.getByte(),
reg3 = (uInt8) in.getByte(),
reg4 = (uInt8) in.getByte(),
reg5 = (uInt8) in.getByte(),
reg6 = (uInt8) in.getByte();
myLastRegisterSetCycle = (Int32) in.getInt();

View File

@ -54,7 +54,7 @@ class SoundSDL : public Sound
/**
Enables/disables the sound subsystem.
@param state 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 state);
@ -62,14 +62,18 @@ class SoundSDL : public Sound
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
@param amount The amount the cycle counter is being adjusted by
*/
void adjustCycleCounter(Int32 amount);
/**
Sets the number of channels (mono or stereo sound).
Sets the number of channels (mono or stereo sound). Note that this
determines how the emulation should 'mix' the channels of the TIA sound
system (of which there are always two). It does not specify the actual
number of hardware channels that SDL should use; it will always attempt
to use two channels in hardware.
@param channels The number of channels
@param channels The number of channels
*/
void setChannels(uInt32 channels);
@ -93,17 +97,10 @@ class SoundSDL : public Sound
*/
void close();
/**
Return true iff the sound device was successfully initialized.
@return true iff the sound device was successfully initialized.
*/
bool isSuccessfullyInitialized() const;
/**
Set the mute state of the sound object. While muted no sound is played.
@param state Mutes sound if true, unmute if false
@param state Mutes sound if true, unmute if false
*/
void mute(bool state);
@ -115,9 +112,9 @@ class SoundSDL : public Sound
/**
Sets the sound register to a given value.
@param addr The register address
@param value The value to save into the register
@param cycle The system cycle at which the register is being updated
@param addr The register address
@param value The value to save into the register
@param cycle The system cycle at which the register is being updated
*/
void set(uInt16 addr, uInt8 value, Int32 cycle);
@ -126,15 +123,15 @@ class SoundSDL : public Sound
volume is given as a percentage from 0 to 100. Values outside
this range indicate that the volume shouldn't be changed at all.
@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);
/**
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);
@ -142,23 +139,23 @@ class SoundSDL : public Sound
/**
Saves the current state of this device to the given Serializer.
@param out The serializer device to save to.
@return The result of the save. True on success, false on failure.
@param out The serializer device to save to.
@return The result of the save. True on success, false on failure.
*/
bool save(Serializer& out) const;
/**
Loads the current state of this device from the given Serializer.
@param in The Serializer device to load from.
@return The result of the load. True on success, false on failure.
@param in The Serializer device to load from.
@return The result of the load. True on success, false on failure.
*/
bool load(Serializer& in);
/**
Get a descriptor for this console class (used in error checking).
@return The name of the object
@return The name of the object
*/
string name() const { return "TIASound"; }
@ -166,8 +163,8 @@ class SoundSDL : public Sound
/**
Invoked by the sound callback to process the next sound fragment.
@param stream Pointer to the start of the fragment
@param length Length of the fragment
@param stream Pointer to the start of the fragment
@param length Length of the fragment
*/
void processFragment(uInt8* stream, Int32 length);
@ -223,14 +220,14 @@ class SoundSDL : public Sound
/**
Return the item at the front on the queue.
@return The item at the front of the queue.
@return The item at the front of the queue.
*/
RegWrite& front();
/**
Answers the number of items currently in the queue.
@return The number of items in the queue.
@return The number of items in the queue.
*/
uInt32 size() const;

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "3.5_svn_test3"
#define STELLA_VERSION "3.5_svn_test4"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -487,10 +487,9 @@ void Console::initializeAudio()
int framerate = myOSystem->settings().getInt("framerate");
if(framerate > 0) myFramerate = float(framerate);
const string& sound = myProperties.get(Cartridge_Sound);
uInt32 channels = (sound == "STEREO" ? 2 : 1);
myOSystem->sound().close();
myOSystem->sound().setChannels(channels);
myOSystem->sound().setChannels(sound == "STEREO" ? 2 : 1);
myOSystem->sound().setFrameRate(myFramerate);
myOSystem->sound().open();

View File

@ -2649,9 +2649,9 @@ string EventHandler::StellaJoystick::about() const
buf << name;
if(type == JT_REGULAR)
buf << " with:" << endl << " "
<< SDL_JoystickNumAxes(stick) << " axes, "
<< SDL_JoystickNumButtons(stick) << " buttons, "
<< SDL_JoystickNumHats(stick) << " hats";
<< numAxes << " axes, "
<< numButtons << " buttons, "
<< numHats << " hats";
return buf.str();
}

View File

@ -464,8 +464,8 @@ fallback:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::createSound()
{
delete mySound; mySound = NULL;
mySound = MediaFactory::createAudio(this);
if(!mySound)
mySound = MediaFactory::createAudio(this);
#ifndef SOUND_SUPPORT
mySettings->setBool("sound", false);
#endif

View File

@ -41,11 +41,11 @@ Settings::Settings(OSystem* osystem)
// OpenGL specific options
setInternal("gl_filter", "nearest");
setInternal("gl_aspectn", "100");
setInternal("gl_aspectn", "90");
setInternal("gl_aspectp", "100");
setInternal("gl_fsmax", "false");
setInternal("gl_fsmax", "true");
setInternal("gl_lib", "libGL.so");
setInternal("gl_vsync", "false");
setInternal("gl_vsync", "true");
setInternal("gl_vbo", "true");
// Framebuffer-related options
@ -99,7 +99,7 @@ Settings::Settings(OSystem* osystem)
setInternal("uselauncher", "true");
setInternal("launcherres", "640x480");
setInternal("launcherfont", "medium");
setInternal("launcherexts", "allfiles");
setInternal("launcherexts", "allroms");
setInternal("romviewer", "0");
setInternal("lastrom", "");

View File

@ -89,13 +89,6 @@ class Sound : public Serializable
*/
virtual void close() = 0;
/**
Return true iff the sound device was successfully initialized.
@return true iff the sound device was successfully initialized.
*/
virtual bool isSuccessfullyInitialized() const = 0;
/**
Set the mute state of the sound object. While muted no sound is played.

View File

@ -21,10 +21,10 @@
#include "TIASnd.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TIASound::TIASound(Int32 outputFrequency, Int32 tiaFrequency, uInt32 channels)
: myOutputFrequency(outputFrequency),
TIASound::TIASound(Int32 outputFrequency, Int32 tiaFrequency)
: myChannelMode(Hardware2Stereo),
myOutputFrequency(outputFrequency),
myTIAFrequency(tiaFrequency),
myChannels(channels),
myOutputCounter(0),
myVolumePercentage(100),
myVolumeClip(128)
@ -60,9 +60,20 @@ void TIASound::tiaFrequency(Int32 freq)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASound::channels(uInt32 number)
string TIASound::channels(uInt32 hardware, bool stereo)
{
myChannels = number == 2 ? 2 : 1;
if(hardware == 1)
myChannelMode = Hardware1;
else
myChannelMode = stereo ? Hardware2Stereo : Hardware2Mono;
switch(myChannelMode)
{
case Hardware1: return "Hardware1";
case Hardware2Mono: return "Hardware2Mono";
case Hardware2Stereo: return "Hardware2Stereo";
default: return EmptyString;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -357,27 +368,39 @@ void TIASound::process(uInt8* buffer, uInt32 samples)
myOutputCounter += myOutputFrequency;
if(myChannels == 1)
switch(myChannelMode)
{
// Handle mono sample generation
while((samples > 0) && (myOutputCounter >= myTIAFrequency))
{
*(buffer++) = (((myP4[0] & 8) ? v0 : 0) +
((myP4[1] & 8) ? v1 : 0)) + myVolumeClip;
myOutputCounter -= myTIAFrequency;
samples--;
}
}
else
{
// Handle stereo sample generation
while((samples > 0) && (myOutputCounter >= myTIAFrequency))
{
*(buffer++) = ((myP4[0] & 8) ? v0 : 0) + myVolumeClip;
*(buffer++) = ((myP4[1] & 8) ? v1 : 0) + myVolumeClip;
myOutputCounter -= myTIAFrequency;
samples--;
}
case Hardware2Mono: // mono sampling with 2 hardware channels
while((samples > 0) && (myOutputCounter >= myTIAFrequency))
{
uInt8 byte = (((myP4[0] & 8) ? v0 : 0) +
((myP4[1] & 8) ? v1 : 0)) + myVolumeClip;
*(buffer++) = byte;
*(buffer++) = byte;
myOutputCounter -= myTIAFrequency;
samples--;
}
break;
case Hardware2Stereo: // stereo sampling with 2 hardware channels
while((samples > 0) && (myOutputCounter >= myTIAFrequency))
{
*(buffer++) = ((myP4[0] & 8) ? v0 : 0) + myVolumeClip;
*(buffer++) = ((myP4[1] & 8) ? v1 : 0) + myVolumeClip;
myOutputCounter -= myTIAFrequency;
samples--;
}
break;
case Hardware1: // mono/stereo sampling with only 1 hardware channel
while((samples > 0) && (myOutputCounter >= myTIAFrequency))
{
*(buffer++) = (((myP4[0] & 8) ? v0 : 0) +
((myP4[1] & 8) ? v1 : 0)) + myVolumeClip;
myOutputCounter -= myTIAFrequency;
samples--;
}
break;
}
}
}

View File

@ -35,8 +35,7 @@ class TIASound
/**
Create a new TIA Sound object using the specified output frequency
*/
TIASound(Int32 outputFrequency = 31400, Int32 tiaFrequency = 31400,
uInt32 channels = 1);
TIASound(Int32 outputFrequency = 31400, Int32 tiaFrequency = 31400);
/**
Destructor
@ -60,9 +59,16 @@ class TIASound
void tiaFrequency(Int32 freq);
/**
Selects the number of audio channels per sample (1 = mono, 2 = stereo)
Selects the number of audio channels per sample. There are two factors
to consider: hardware capability and desired mixing.
@param hardware The number of channels supported by the sound system
@param stereo Whether to output the internal sound signals into 1
or 2 channels
@return Status of the channel configuration used
*/
void channels(uInt32 number);
string channels(uInt32 hardware, bool stereo);
/**
Set volume clipping (decrease volume range by half to eliminate popping)
@ -133,6 +139,12 @@ class TIASound
uInt32 myCounter;
};
enum ChannelMode {
Hardware1,
Hardware2Mono,
Hardware2Stereo
};
private:
uInt8 myAUDC[2];
uInt8 myAUDF[2];
@ -142,9 +154,9 @@ class TIASound
uInt8 myP4[2]; // 4-bit register LFSR (lower 4 bits used)
uInt8 myP5[2]; // 5-bit register LFSR (lower 5 bits used)
ChannelMode myChannelMode;
Int32 myOutputFrequency;
Int32 myTIAFrequency;
uInt32 myChannels;
Int32 myOutputCounter;
uInt32 myVolumePercentage;
uInt8 myVolumeClip;

View File

@ -48,7 +48,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent,
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
int xpos, ypos;
int lwidth = font.getStringWidth("Fragment Size: "),
int lwidth = font.getStringWidth("Sample Size (*): "),
pwidth = font.getStringWidth("512 bytes");
WidgetArray wid;
StringMap items;
@ -82,7 +82,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent,
items.push_back("4 KB", "4096");
myFragsizePopup = new PopUpWidget(this, font, xpos, ypos,
pwidth + myVolumeLabel->getWidth() - 4, lineHeight,
items, "Fragment size: ", lwidth);
items, "Sample size (*): ", lwidth);
wid.push_back(myFragsizePopup);
ypos += lineHeight + 4;
@ -95,7 +95,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent,
items.push_back("48000 Hz", "48000");
myFreqPopup = new PopUpWidget(this, font, xpos, ypos,
pwidth + myVolumeLabel->getWidth() - 4, lineHeight,
items, "Output freq: ", lwidth);
items, "Output freq (*): ", lwidth);
wid.push_back(myFreqPopup);
ypos += lineHeight + 4;
@ -108,16 +108,22 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent,
ypos += lineHeight + 4;
// Clip volume
myClipVolumeCheckbox = new CheckboxWidget(this, font, xpos+50, ypos,
myClipVolumeCheckbox = new CheckboxWidget(this, font, xpos+10, ypos,
"Clip volume", 0);
wid.push_back(myClipVolumeCheckbox);
ypos += lineHeight + 4;
xpos += myClipVolumeCheckbox->getWidth() + 20;
// Enable sound
mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos+50, ypos,
mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos,
"Enable sound", kSoundEnableChanged);
wid.push_back(mySoundEnableCheckbox);
// Add message concerning usage
ypos += lineHeight + 12;
const GUI::Font& infofont = instance().infoFont();
new StaticTextWidget(this, infofont, 10, ypos,
font.getStringWidth("(*) Requires application restart"), fontHeight,
"(*) Requires application restart", kTextAlignLeft);
// Add Defaults, OK and Cancel buttons
ButtonWidget* b;

View File

@ -32,7 +32,8 @@ class StringListWidget;
class LoggerDialog : public Dialog
{
public:
LoggerDialog(OSystem* osystem, DialogContainer* parent, const GUI::Font& font, int max_w, int max_h);
LoggerDialog(OSystem* osystem, DialogContainer* parent,
const GUI::Font& font, int max_w, int max_h);
virtual ~LoggerDialog();
protected:

View File

@ -449,16 +449,16 @@ void VideoDialog::setDefaults()
myFSResPopup->setSelected("auto", "");
myFrameTimingPopup->setSelected("sleep", "");
myGLFilterPopup->setSelected("nearest", "");
myNAspectRatioSlider->setValue(100);
myNAspectRatioLabel->setLabel("100");
myNAspectRatioSlider->setValue(90);
myNAspectRatioLabel->setLabel("90");
myPAspectRatioSlider->setValue(100);
myPAspectRatioLabel->setLabel("100");
myFrameRateSlider->setValue(0);
myFrameRateLabel->setLabel("Auto");
myFullscreenPopup->setSelected("0", "");
myColorLossCheckbox->setState(false);
myGLStretchCheckbox->setState(false);
myColorLossCheckbox->setState(true);
myGLStretchCheckbox->setState(true);
myUseVBOCheckbox->setState(true);
myUseVSyncCheckbox->setState(true);
myUIMessagesCheckbox->setState(true);