Changes for the SDL port to use the new sound API. This is still beta

code, and there are still some audio/video sync'ing problems.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@115 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2002-10-11 13:07:01 +00:00
parent 36a5c1575d
commit 1810444904
5 changed files with 198 additions and 160 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of ## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES. ## this file, and for a DISCLAIMER OF ALL WARRANTIES.
## ##
## $Id: makefile,v 1.22 2002-10-09 04:38:11 bwmott Exp $ ## $Id: makefile,v 1.23 2002-10-11 13:06:59 stephena Exp $
##============================================================================ ##============================================================================
##============================================================================ ##============================================================================
@ -179,7 +179,7 @@ linux-x:
linux-sdl: linux-sdl:
make stella.sdl \ make stella.sdl \
INCLUDES="$(INCLUDES) -I$(UI)/sdl -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/sdl" \
SYS_INCLUDES="" \ SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1" \
OPTIONS+="$(OPTS.SDL)" \ OPTIONS+="$(OPTS.SDL)" \
@ -187,7 +187,7 @@ linux-sdl:
LDFLAGS+="$(CFLAGS.SDL)" \ LDFLAGS+="$(CFLAGS.SDL)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.SDL)" \ LDLIBS+="$(LIBS.SDL)" \
OBJS="mainSDL.o SndSDL.o RectList.o" \ OBJS="mainSDL.o SoundSDL.o RectList.o" \
OBJS+="$(OBJS.SDL)" OBJS+="$(OBJS.SDL)"
bsdi-x: bsdi-x:
@ -408,8 +408,8 @@ SoundX11.o: $(UI)/x11/SoundX11.cxx
mainSDL.o: $(UI)/sdl/mainSDL.cxx mainSDL.o: $(UI)/sdl/mainSDL.cxx
$(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/mainSDL.cxx $(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/mainSDL.cxx
SndSDL.o: $(UI)/sdl/SndSDL.cxx $(UI)/sdl/SndSDL.hxx SoundSDL.o: $(UI)/sdl/SoundSDL.cxx $(UI)/sdl/SoundSDL.hxx
$(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/SndSDL.cxx $(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/SoundSDL.cxx
RectList.o: $(UI)/sdl/RectList.cxx $(UI)/sdl/RectList.hxx RectList.o: $(UI)/sdl/RectList.cxx $(UI)/sdl/RectList.hxx
$(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/RectList.cxx $(CXX) -c $(CXXFLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/sdl/RectList.cxx

View File

@ -1,77 +0,0 @@
//============================================================================
//
// 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-1998 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SndSDL.hxx,v 1.1 2002-08-15 00:29:40 stephena Exp $
//============================================================================
#ifndef SOUNDSDL_HXX
#define SOUNDSDL_HXX
#include <SDL.h>
#include "bspf.hxx"
#include "Sound.hxx"
/**
This class implements the sound API for SDL.
@author Stephen Anthony
@version $Id: SndSDL.hxx,v 1.1 2002-08-15 00:29:40 stephena Exp $
*/
class SoundSDL : public Sound
{
public:
/**
Create a new sound object
*/
SoundSDL(int volume, bool activate = true);
/**
Destructor
*/
virtual ~SoundSDL();
public:
/**
Set the value of the specified sound register
@param reg The sound register to set
@param val The new value for the sound registers
*/
virtual void set(Sound::Register reg, uInt8 val);
/**
Set the mute state of the sound object
@param state Mutes sound iff true
*/
virtual void mute(bool state);
/**
Set the current volume according to the given percentage
@param percent Scaled value (0-100) indicating the desired volume
*/
void setVolume(int percent);
private:
// Indicates if the sound system was initialized
bool myEnabled;
// Indicates if the sound is currently muted
bool isMuted;
};
#endif

View File

@ -13,66 +13,59 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: SndSDL.cxx,v 1.1 2002-08-15 00:29:40 stephena Exp $ // $Id: SoundSDL.cxx,v 1.1 2002-10-11 13:07:00 stephena Exp $
//============================================================================ //============================================================================
#include <SDL.h> #include <SDL.h>
#include "TIASound.h" #include "SoundSDL.hxx"
#include "SndSDL.hxx"
#define FRAGSIZE 1 << 10 static uInt8 currentVolume;
static MediaSource* _mediaSource;
static int currentVolume = 0;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void fill_audio(void* udata, Uint8* stream, int len) SoundSDL::SoundSDL(bool activate)
{ : myIsInitializedFlag(false),
Uint8 buffer[FRAGSIZE]; mySampleRate(31400),
myFragSize(512),
if(len > FRAGSIZE) myIsMuted(true)
len = FRAGSIZE;
Tia_process(buffer, len);
SDL_MixAudio(stream, buffer, len, currentVolume);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL::SoundSDL(int volume, bool activate)
{ {
myEnabled = activate; myIsInitializedFlag = activate;
if(!myEnabled) if(!myIsInitializedFlag)
return; return;
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{ {
cerr << "Couldn't init SDL audio system: " << SDL_GetError() << endl; cerr << "Couldn't init SDL audio system: " << SDL_GetError() << endl;
myEnabled = false; myIsInitializedFlag = false;
mySampleRate = 0;
return; return;
} }
SDL_AudioSpec desired, obtained; SDL_AudioSpec desired, obtained;
desired.freq = 31400; desired.freq = mySampleRate;
desired.samples = FRAGSIZE; desired.samples = myFragSize;
desired.format = AUDIO_U8; desired.format = AUDIO_U8;
desired.callback = fill_audio; desired.callback = fillAudio;
desired.userdata = NULL; desired.userdata = NULL;
desired.channels = 1; desired.channels = 1;
if(SDL_OpenAudio(&desired, &obtained) < 0) if(SDL_OpenAudio(&desired, &obtained) < 0)
{ {
cerr << "Couldn't open SDL audio: " << SDL_GetError() << endl; cerr << "Couldn't open SDL audio: " << SDL_GetError() << endl;
myEnabled = false; myIsInitializedFlag = false;
mySampleRate = 0;
return; return;
} }
/* Initialize the TIA Sound Library */
Tia_sound_init(31400, obtained.freq);
isMuted = false; myIsMuted = false;
setVolume(volume); mySampleRate = obtained.freq;
// Take care of the static stuff ...
currentVolume = 0;
_mediaSource = (MediaSource*) NULL;
SDL_PauseAudio(0); SDL_PauseAudio(0);
} }
@ -80,69 +73,75 @@ SoundSDL::SoundSDL(int volume, bool activate)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL::~SoundSDL() SoundSDL::~SoundSDL()
{ {
if(myEnabled)
SDL_CloseAudio();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::set(Sound::Register reg, uInt8 value) uInt32 SoundSDL::getSampleRate() const
{ {
if(!myEnabled) return myIsInitializedFlag ? mySampleRate : 0;
return; }
switch(reg) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{ bool SoundSDL::isSuccessfullyInitialized() const
case AUDC0: {
Update_tia_sound(0x15, value); return myIsInitializedFlag;
break;
case AUDC1:
Update_tia_sound(0x16, value);
break;
case AUDF0:
Update_tia_sound(0x17, value);
break;
case AUDF1:
Update_tia_sound(0x18, value);
break;
case AUDV0:
Update_tia_sound(0x19, value);
break;
case AUDV1:
Update_tia_sound(0x1A, value);
break;
default:
return;
break;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::mute(bool state) void SoundSDL::mute(bool state)
{ {
if(!myEnabled) if(!myIsInitializedFlag)
return; return;
// Ignore multiple calls to do the same thing // Ignore multiple calls to do the same thing
if(isMuted == state) if(myIsMuted == state)
return; return;
isMuted = state; myIsMuted = state;
SDL_PauseAudio(isMuted ? 1 : 0); SDL_PauseAudio(myIsMuted ? 1 : 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::setVolume(int percent) void SoundSDL::close()
{ {
if(!myEnabled) SDL_PauseAudio(0);
if(myIsInitializedFlag)
SDL_CloseAudio();
myIsInitializedFlag = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::setSoundVolume(uInt32 percent)
{
if(!myIsInitializedFlag)
return; return;
if((percent >= 0) && (percent <= 100)) if((percent >= 0) && (percent <= 100))
currentVolume = (int) (((float) percent / 100.0) * (float) SDL_MIX_MAXVOLUME); currentVolume = (int) (((float) percent / 100.0) * (float) SDL_MIX_MAXVOLUME);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::updateSound(MediaSource& mediaSource)
{
// this is a HUGE HACK and will disappear soon
_mediaSource = &mediaSource;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL::fillAudio(void* udata, uInt8* stream, Int32 len)
{
if(!_mediaSource)
return;
uInt32 samples = _mediaSource->numberOfAudioSamples();
if(samples == 0)
return;
uInt8 buffer[len];
_mediaSource->dequeueAudioSamples(buffer, len);
SDL_MixAudio(stream, buffer, len, currentVolume);
}

View File

@ -0,0 +1,111 @@
//============================================================================
//
// 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-1998 by Bradford W. Mott
//
// 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.1 2002-10-11 13:07:01 stephena Exp $
//============================================================================
#ifndef SOUNDSDL_HXX
#define SOUNDSDL_HXX
#include <SDL.h>
#include "bspf.hxx"
#include "MediaSrc.hxx"
/**
This class implements the sound API for SDL.
@author Stephen Anthony
@version $Id: SoundSDL.hxx,v 1.1 2002-10-11 13:07:01 stephena Exp $
*/
class SoundSDL
{
public:
/**
Create a new sound object
*/
SoundSDL(bool activate = true);
/**
Destructor
*/
virtual ~SoundSDL();
public:
/**
Return the playback sample rate for the sound device.
@return The playback sample rate
*/
uInt32 getSampleRate() const;
/**
Return true iff the sound device was successfully initlaized.
@return true iff the sound device was successfully initlaized.
*/
bool isSuccessfullyInitialized() const;
/**
Sets the volume of the sound device to the specified level. The
volume is given as a precentage from 0 to 100.
@param volume The new volume for the sound device
*/
void setSoundVolume(uInt32 volume);
/**
Update the sound device using the audio sample from the specified
media source.
@param mediaSource The media source to get audio samples from.
*/
void updateSound(MediaSource& mediaSource);
/**
Closes the soudn device
*/
void close();
/**
Set the mute state of the sound object
@param state Mutes sound iff true
*/
void mute(bool state);
private:
// Indicates if the sound device was successfully initialized
bool myIsInitializedFlag;
// DSP sample rate
uInt32 mySampleRate;
// SDL fragment size
uInt32 myFragSize;
// Indicates if the sound is currently muted
bool myIsMuted;
/**
Some stuff which is required to be static since the SDL audio
callback is a C-style function.
*/
private:
static void fillAudio(void* udata, uInt8* stream, Int32 len);
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: mainSDL.cxx,v 1.29 2002-10-05 12:49:49 stephena Exp $ // $Id: mainSDL.cxx,v 1.30 2002-10-11 13:07:01 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include <fstream>
@ -36,10 +36,9 @@
#include "MediaSrc.hxx" #include "MediaSrc.hxx"
#include "PropsSet.hxx" #include "PropsSet.hxx"
#include "System.hxx" #include "System.hxx"
#include "SndUnix.hxx"
#include "RectList.hxx" #include "RectList.hxx"
#include "Settings.hxx" #include "Settings.hxx"
#include "SndSDL.hxx" #include "SoundSDL.hxx"
#ifdef HAVE_PNG #ifdef HAVE_PNG
#include "Snapshot.hxx" #include "Snapshot.hxx"
@ -1563,15 +1562,16 @@ int main(int argc, char* argv[])
return 0; return 0;
} }
// Create a sound object for use with the console // Create a sound object for playing audio
SoundSDL sound(settings->theDesiredVolume); SoundSDL sound;
sound.setSoundVolume(settings->theDesiredVolume);
// Get just the filename of the file containing the ROM image // Get just the filename of the file containing the ROM image
const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1; const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1;
// Create the 2600 game console // Create the 2600 game console
theConsole = new Console(image, size, filename, theConsole = new Console(image, size, filename,
theEvent, propertiesSet, sound); theEvent, propertiesSet, sound.getSampleRate());
// Free the image since we don't need it any longer // Free the image since we don't need it any longer
delete[] image; delete[] image;
@ -1580,12 +1580,14 @@ int main(int argc, char* argv[])
if(!setupDisplay()) if(!setupDisplay())
{ {
cerr << "ERROR: Couldn't set up display.\n"; cerr << "ERROR: Couldn't set up display.\n";
sound.close();
cleanup(); cleanup();
return 0; return 0;
} }
if(!setupJoystick()) if(!setupJoystick())
{ {
cerr << "ERROR: Couldn't set up joysticks.\n"; cerr << "ERROR: Couldn't set up joysticks.\n";
sound.close();
cleanup(); cleanup();
return 0; return 0;
} }
@ -1623,6 +1625,7 @@ int main(int argc, char* argv[])
startTime = getTicks(); startTime = getTicks();
theConsole->mediaSource().update(); theConsole->mediaSource().update();
sound.updateSound(theConsole->mediaSource());
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
handleEvents(); handleEvents();
@ -1662,6 +1665,7 @@ int main(int argc, char* argv[])
if(!thePauseIndicator) if(!thePauseIndicator)
{ {
theConsole->mediaSource().update(); theConsole->mediaSource().update();
sound.updateSound(theConsole->mediaSource());
} }
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
handleEvents(); handleEvents();
@ -1695,6 +1699,7 @@ int main(int argc, char* argv[])
} }
// Cleanup time ... // Cleanup time ...
sound.close();
cleanup(); cleanup();
return 0; return 0;
} }