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:
@@ -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*/
|
||||||
@@ -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; }
|
||||||
@@ -69,7 +68,13 @@ RageSoundDriver *MakeRageSoundDriver(CString drivers)
|
|||||||
#endif
|
#endif
|
||||||
#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());
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
Reference in New Issue
Block a user