gsplus/src/sdlsnd_driver.c

202 lines
4.7 KiB
C

/*
GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2)
*/
#include <assert.h>
#include "defc.h"
#include "sound.h"
#include "SDL.h"
extern int Verbose;
extern int g_audio_rate;
unsigned int __stdcall child_sound_loop_win32(void *param);
void check_wave_error(int res, char *str);
#define NUM_WAVE_HEADERS 8
//HWAVEOUT g_wave_handle = NULL; // OG Default value must be set
//WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
extern int g_audio_enable;
extern word32 *g_sound_shm_addr;
extern int g_preferred_rate;
int g_sdlsnd_buflen = 0x1000;
word32 *bptr = NULL;
int g_sdlsnd_write_idx;
int g_sdlsnd_read_idx;
// just to makeit stand out
#ifdef HAVE_SDL
static Uint8 *audio_chunk;
static Uint8 *audio_pos;
static Uint32 audio_len;
static byte *sdlsnd_buf = 0;
SDL_AudioSpec want, have;
SDL_AudioDeviceID dev;
static byte *playbuf = 0;
static int g_playbuf_buffered = 0;
static SDL_AudioSpec spec;
static int snd_buf;
static int snd_write; /* write position into playbuf */
static /* volatile */ int snd_read = 0;
static void _snd_callback(void*, Uint8 *stream, int len);
static void sound_write_sdl(int real_samps, int size);
#endif
void sdlsnd_init(word32 *shmaddr)
{
printf("sdlsnd_init\n");
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
printf("Cannot initialize SDL audio\n");
g_audio_enable = 0;
}
child_sound_loop(-1, -1, shmaddr);
return;
}
void
win32snd_init(word32 *shmaddr)
{
printf("win32snd_init\n");
child_sound_loop(-1, -1, shmaddr);
return;
}
void sdl_send_audio(word32 *ptr, int size, int real_samps) {
/* code */
//printf(" sdl_s_a %d\t 0x%08x ",size, &ptr);
int i;
for (i=0; i<size; i++) {
if (real_samps) {
bptr[g_sdlsnd_write_idx++] = ptr[i];
} else {
bptr[g_sdlsnd_write_idx++] = 0;
}
if (g_sdlsnd_write_idx>g_sdlsnd_buflen) {
g_sdlsnd_write_idx=0;
}
}
g_playbuf_buffered += size;
}
void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
/* Only play if we have data left */
/* if ( g_playbuf_buffered == 0) {
return;
}
*/
for(int i = 0; i < len; ++i) {
if(g_playbuf_buffered <= 0) {
stream[i] = 0;
} else {
stream[i] = bptr[g_sdlsnd_read_idx++];
if(g_sdlsnd_read_idx == g_sdlsnd_buflen)
g_sdlsnd_read_idx = 0;
g_playbuf_buffered--;
}
}
return;
/* Mix as much data as possible */
len = ( len > g_playbuf_buffered ? g_playbuf_buffered : len );
//len = ( g_sdlsnd_read_idx+len < g_sdlsnd_buflen ? len : g_sdlsnd_read_idx+len);
SDL_memset(stream, 0, len);
if (g_sdlsnd_read_idx+len < g_sdlsnd_buflen) {
SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], len);
g_sdlsnd_read_idx += len;
g_playbuf_buffered -= len;
} else {
/*
int top_len = 0;
top_len = g_sdlsnd_buflen - g_sdlsnd_read_idx;
SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], top_len);
g_sdlsnd_read_idx = 0;
g_playbuf_buffered -= top_len;
// SDL_memcpy (stream+top_len, bptr[g_sdlsnd_read_idx], len-top_len);
g_sdlsnd_read_idx += len-top_len;
g_playbuf_buffered -= len-top_len;
*/
}
//SDL_MixAudio(stream, pointer, len, SDL_MIX_MAXVOLUME);
}
void
child_sound_init_sdl()
{
printf("child_sound_init_sdl");
SDL_memset(&want, 0, sizeof(want)); // or SDL_zero(want)
want.freq = g_preferred_rate; // 48000 ?
want.format = AUDIO_S16SYS; // AUDIO_F32
want.channels = NUM_CHANNELS; //2
want.samples = 512; //4096
want.callback = handle_sdl_snd; // you wrote this function elsewhere.
dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (dev == 0) {
printf("Failed to open audio: %s\n", SDL_GetError());
} else {
if (have.format != want.format) { // we let this one thing change.
printf("We didn't get Float32 audio format.\n");
}
}
// super experimental unknown
g_playbuf_buffered = 0; // init buffered state
int blen;
blen = (SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE * 2); // *2 unnecessary?
g_sdlsnd_buflen = blen;
bptr = (byte*)malloc(blen);
if(bptr == NULL) {
printf("Unabled to allocate sound buffer\n");
exit(1);
}
memset(bptr, 0, SOUND_SHM_SAMP_SIZE*SAMPLE_CHAN_SIZE *2); // zero out the buffer
g_sdlsnd_write_idx = 0; // initialize
g_sdlsnd_read_idx = 0;
SDL_PauseAudioDevice(dev, 0); // start audio playing.
g_audio_rate = have.freq;
printf("g_audio_rate: %d\n", g_audio_rate);
set_audio_rate(g_audio_rate); // let kegs simulator know the rate
}
void
sdlsnd_shutdown() {
//SDL_Delay(5000); // let the audio callback play some sound for 5 seconds.
SDL_CloseAudioDevice(dev);
printf("sdlsnd_shutdown");
}