Add portaudio as an SDL audio driver
This commit is contained in:
parent
936a39f624
commit
a17d971fc0
10
Makefile
10
Makefile
@ -121,6 +121,16 @@ else
|
|||||||
LDFLAGS += -lc -lm -ldl
|
LDFLAGS += -lc -lm -ldl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SDL_AUDIO_DRIVER),portaudio)
|
||||||
|
ifeq (,$(PKG_CONFIG))
|
||||||
|
SDL_CFLAGS += -I/usr/local/include
|
||||||
|
SDL_LDFLAGS += -lportaudio
|
||||||
|
else
|
||||||
|
SDL_CFLAGS += $(shell $(PKG_CONFIG) --cflags portaudio)
|
||||||
|
SDL_LDFLAGS += $(shell $(PKG_CONFIG) --libs portaudio)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(PLATFORM),Darwin)
|
ifeq ($(PLATFORM),Darwin)
|
||||||
SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> $(NULL))
|
SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> $(NULL))
|
||||||
CFLAGS += -F/Library/Frameworks -mmacosx-version-min=10.9
|
CFLAGS += -F/Library/Frameworks -mmacosx-version-min=10.9
|
||||||
|
133
SDL/audio/portaudio.c
Normal file
133
SDL/audio/portaudio.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "audio.h"
|
||||||
|
#include <portaudio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define AUDIO_FREQUENCY 96000
|
||||||
|
static PaStream *stream;
|
||||||
|
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
static size_t buffer_position = 0, buffer_size = 0, buffer_needed = 0;
|
||||||
|
static GB_sample_t *buffer = NULL;
|
||||||
|
static bool playing = false;
|
||||||
|
|
||||||
|
|
||||||
|
bool GB_audio_is_playing(void)
|
||||||
|
{
|
||||||
|
return playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_set_paused(bool paused)
|
||||||
|
{
|
||||||
|
if (!stream) return;
|
||||||
|
|
||||||
|
if (paused) {
|
||||||
|
Pa_Sleep(1000);
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
playing = false;
|
||||||
|
GB_audio_clear_queue();
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
Pa_StopStream(stream);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Pa_StartStream(stream);
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_clear_queue(void)
|
||||||
|
{
|
||||||
|
buffer_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GB_audio_get_frequency(void)
|
||||||
|
{
|
||||||
|
return stream? Pa_GetStreamInfo(stream)->sampleRate : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GB_audio_get_queue_length(void)
|
||||||
|
{
|
||||||
|
return buffer_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_queue_sample(GB_sample_t *sample)
|
||||||
|
{
|
||||||
|
if (!stream) return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
if (!GB_audio_is_playing()) {
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_position == buffer_size) {
|
||||||
|
if (buffer_size >= 0x4000) {
|
||||||
|
buffer_position = 0;
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_size == 0) {
|
||||||
|
buffer_size = 512;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer_size += buffer_size >> 2;
|
||||||
|
}
|
||||||
|
buffer = realloc(buffer, sizeof(*sample) * buffer_size);
|
||||||
|
}
|
||||||
|
buffer[buffer_position++] = *sample;
|
||||||
|
if (buffer_position == buffer_needed) {
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
buffer_needed = 0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int callback(const void *in, void *_out,
|
||||||
|
unsigned long frames,
|
||||||
|
const PaStreamCallbackTimeInfo *time_info,
|
||||||
|
PaStreamCallbackFlags status_flags,
|
||||||
|
void *unused)
|
||||||
|
{
|
||||||
|
GB_sample_t *out = (GB_sample_t *)_out;
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
|
if (buffer_position < frames) {
|
||||||
|
buffer_needed = frames;
|
||||||
|
pthread_cond_wait(&cond, &lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playing) {
|
||||||
|
memset(out, 0, frames * sizeof(*out));
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_position >= frames && buffer_position < frames + 4800) {
|
||||||
|
memcpy(out, buffer, frames * sizeof(*buffer));
|
||||||
|
memmove(buffer, buffer + frames, (buffer_position - frames) * sizeof(*buffer));
|
||||||
|
buffer_position -= frames;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(out, buffer + (buffer_position - frames), frames * sizeof(*buffer));
|
||||||
|
buffer_position = 0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_init(void)
|
||||||
|
{
|
||||||
|
Pa_Initialize();
|
||||||
|
Pa_OpenDefaultStream(&stream,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
paInt16,
|
||||||
|
AUDIO_FREQUENCY,
|
||||||
|
paFramesPerBufferUnspecified,
|
||||||
|
callback,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user