Added preliminary sound support for OSX. As far as I know, it should work on any system with SDL. However, I have no way of checking anything other than OSX.

This commit is contained in:
Steve Checkoway
2003-06-14 04:18:58 +00:00
parent 602ed81f48
commit 6abd605ce8
5 changed files with 216 additions and 4 deletions
@@ -0,0 +1,146 @@
/*
* RageSoundDriver_SDL.cpp
* stepmania
*
* Created by Steve Checkoway on Fri Jun 13 2003.
* Copyright (c) 2003 Steve Checkoway. All rights reserved.
*
*/
#include "global.h"
#include "RageSoundDriver_SDL.h"
#include "RageTimer.h"
#include "RageLog.h"
#include "RageSound.h"
#include "RageUtil.h"
const unsigned channels = 2;
const unsigned samplerate = 441000;
const unsigned samplesize = channels*2;
const unsigned buffersize_frames = 1024; /* in samples */
const unsigned buffersize = buffersize_frames * samplesize;
RageSound_SDL::RageSound_SDL() {
last_cursor_pos = 0;
/* Do we need to init SDL_Audio? */
initedSDL_Audio = SDL_WasInit(SDL_INIT_AUDIO) != SDL_INIT_AUDIO;
if (initedSDL_Audio)
if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {
LOG->Trace("Initializing SDL_Audio subsytem.");
RageException::ThrowNonfatal(SDL_GetError());
}
SDL_AudioSpec *specs = static_cast<SDL_AudioSpec *>(calloc(1, sizeof(SDL_AudioSpec)));
specs->freq = samplerate;
specs->format = AUDIO_S16MSB; /* Signed 16-bit big-endian samples */
specs->channels = channels;
specs->samples = buffersize_frames;
specs->callback = GetData;
specs->userdata = this;
if (SDL_OpenAudio(specs, NULL))
RageException::ThrowNonfatal(SDL_GetError());
ASSERT(specs->size == buffersize);
SDL_PauseAudio(0);
}
RageSound_SDL::~RageSound_SDL() {
SDL_CloseAudio();
LOG->Trace("Mixing thread shut down.");
/* Did we init SDL_Audio? */
if (initedSDL_Audio) {
SDL_QuitSubSystem(SDL_INIT_AUDIO);
LOG->Trace("SDL_Audio subsystem quit.");
}
}
/* This function is called by the SDL_Audio subsytem to get the data
* to output.
* Params: userdata: A pointer to the creating RageSound_SDL.
* stream: The audio buffer to fill.
* len: The length of the buffer.
*/
void RageSound_SDL::GetData(void *userdata, Uint8 *stream, int len) {
LockMutex L(SOUNDMAN->lock);
static Sint16 *buf = NULL;
static int bufsize = buffersize_frames * channels;
static SoundMixBuffer mix;
if (!buf)
buf = new Sint16[bufsize];
RageSound_SDL *P = static_cast<RageSound_SDL *>(userdata);
memset(buf, 0, bufsize*sizeof(Uint16));
/* I don't like this but I can't think of another place to put it. */
while (!SOUNDMAN)
sleep(10);
for (unsigned i = 0; i < P->sounds.size(); ++i) {
if (P->sounds[i]->stopping)
continue;
int got = P->sounds[i]->snd->GetPCM(reinterpret_cast<char *>(buf), len, P->last_cursor_pos);
mix.write(buf, got/2);
if (got < len) {
P->sounds[i]->stopping = true;
P->sounds[i]->flush_pos = P->last_cursor_pos + (got / samplesize);
}
}
memcpy(stream, buf, len);
P->last_cursor_pos += buffersize_frames;
}
void RageSound_SDL::StartMixing(RageSound *snd) {
sound *s = new sound;
s->snd = snd;
LockMutex L(SOUNDMAN->lock);
sounds.push_back(s);
}
void RageSound_SDL::StopMixing(RageSound *snd) {
LockMutex L(SOUNDMAN->lock);
/* Find the sound. */
unsigned i;
for(i = 0; i < sounds.size(); ++i)
if(sounds[i]->snd == snd) break;
if(i == sounds.size())
{
LOG->Trace("not stopping a sound because it's not playing");
return;
}
delete sounds[i];
sounds.erase(sounds.begin()+i, sounds.begin()+i+1);
}
void RageSound_SDL::Update(float delta) {
LockMutex L(SOUNDMAN->lock);
vector<sound *>snds = sounds;
for (unsigned i = 0; i < snds.size(); ++i) {
if (!sounds[i]->stopping)
continue;
if (GetPosition(snds[i]->snd) < sounds[i]->flush_pos)
continue;
snds[i]->snd->StopPlaying();
}
}
/* What is this parameter for?
* This returns the same as is passed to RageSound::GetPCM
* as required by RageSoundDriver. I suppose I don't really
* understand the purpose of this method.
* --Steve
*/
int RageSound_SDL::GetPosition(const RageSound *snd) const {
return last_cursor_pos;
}
float RageSound_SDL::GetPlayLatency() const {
return (1.0f / samplerate) * (7/8);
}
@@ -0,0 +1,45 @@
#ifndef RAGE_SOUND_SDL
#define RAGE_SOUND_SDL
/*
* RageSoundDriver_SDL.h
* stepmania
*
* Created by Steve Checkoway on Fri Jun 13 2003.
* Judicially copying from RageSoundDriver_Null.*
* Copyright (c) 2003 Steve Checkoway. All rights reserved.
*
*/
#include "RageSound.h"
#include <time.h>
#include "RageSoundDriver.h"
#include <SDL.h>
class RageSound_SDL: public RageSoundDriver {
private:
struct sound {
RageSound *snd;
bool stopping;
int flush_pos;
sound() { snd=NULL; stopping=false; flush_pos=0; }
};
vector<sound *> sounds;
SDL_AudioSpec *specs;
bool initedSDL_Audio;
int last_cursor_pos;
protected:
virtual void StartMixing(RageSound *snd);
virtual void StopMixing(RageSound *snd);
virtual int GetPosition(const RageSound *snd) const;
virtual void Update(float delta);
virtual float GetPlayLatency() const;
public:
RageSound_SDL();
virtual ~RageSound_SDL();
static void GetData(void *userdata, Uint8 *stream, int len);
};
#endif /*RAGE_SOUND_SDL*/
+7 -2
View File
@@ -16,12 +16,11 @@
#if defined(LINUX) #if defined(LINUX)
#include "arch_linux.h" #include "arch_linux.h"
#elif defined(DARWIN) #elif defined(DARWIN)
// #include "arch_darwin.h" #include "arch_darwin.h"
#elif defined(WIN32) #elif defined(WIN32)
#include "arch_Win32.h" #include "arch_Win32.h"
#endif #endif
LoadingWindow *MakeLoadingWindow() { return new ARCH_LOADING_WINDOW; } LoadingWindow *MakeLoadingWindow() { return new ARCH_LOADING_WINDOW; }
ErrorDialog *MakeErrorDialog() { return new ARCH_ERROR_DIALOG; } ErrorDialog *MakeErrorDialog() { return new ARCH_ERROR_DIALOG; }
ArchHooks *MakeArchHooks() { return new ARCH_HOOKS; } ArchHooks *MakeArchHooks() { return new ARCH_HOOKS; }
@@ -70,6 +69,12 @@ RageSoundDriver *MakeRageSoundDriver(CString drivers)
#ifdef HAVE_OSS #ifdef HAVE_OSS
if(!DriversToTry[i].CompareNoCase("OSS")) ret = new RageSound_OSS; if(!DriversToTry[i].CompareNoCase("OSS")) ret = new RageSound_OSS;
#endif #endif
if(!DriversToTry[i].CompareNoCase("SDL"))
try {
ret = new RageSound_SDL;
} catch (RageException e) {
ret = NULL;
}
if(!DriversToTry[i].CompareNoCase("Null")) ret = new RageSound_Null; if(!DriversToTry[i].CompareNoCase("Null")) ret = new RageSound_Null;
if( !ret ) if( !ret )
LOG->Warn("Unknown sound driver name: %s", DriversToTry[i].c_str()); LOG->Warn("Unknown sound driver name: %s", DriversToTry[i].c_str());
+1 -1
View File
@@ -22,7 +22,7 @@ RageSoundDriver *MakeRageSoundDriver(CString drivers);
#if defined(LINUX) #if defined(LINUX)
#define DEFAULT_SOUND_DRIVER_LIST "ALSA9,OSS,Null" #define DEFAULT_SOUND_DRIVER_LIST "ALSA9,OSS,Null"
#elif defined(DARWIN) #elif defined(DARWIN)
#define DEFAULT_SOUND_DRIVER_LIST "Null" /* XXX */ #define DEFAULT_SOUND_DRIVER_LIST "SDL,Null"
#elif defined(WIN32) #elif defined(WIN32)
#define DEFAULT_SOUND_DRIVER_LIST "DirectSound,DirectSound-sw,WaveOut" #define DEFAULT_SOUND_DRIVER_LIST "DirectSound,DirectSound-sw,WaveOut"
#else #else
+16
View File
@@ -0,0 +1,16 @@
#ifndef ARCH_DARWIN_H
#define ARCH_DARWIN_H
/*
* arch_darwin.h
* stepmania
*
* Created by Steve Checkoway on Fri Jun 13 2003.
* Copyright (c) 2003 Steve Checkoway. All rights reserved.
*
*/
#include <SDL.h>
#include "RageSoundDriver_SDL.h"
#endif