Encapsulate SDL-sound code into separate file

This commit is contained in:
Vladimir Serbinenko 2019-11-01 17:06:08 +01:00
parent f2b872c46f
commit bef7ae60a5
3 changed files with 127 additions and 103 deletions

View File

@ -49,11 +49,11 @@ UTILS = maketape readtape
SRCS = access.c boot.c branch.c conf.c covox.c double.c ea.c itab.c \
main.c service.c ui.c scr-sdl.c scr.c timer.c tape.c disk.c mouse.c printer.c \
single.c weird.c tty.c io.c timing.c sound.c disas.c serial.c bkplip.c \
terakdisk.c synth.c emu2149.c sdltty.c
terakdisk.c synth.c emu2149.c sdlsound.c sdltty.c
OBJS = access.o boot.o branch.o conf.o covox.o double.o ea.o itab.o icon.o \
main.o service.o ui.o scr-sdl.o scr.o timer.o tape.o disk.o mouse.o printer.o \
single.o weird.o tty.o io.o timing.o sound.o disas.o serial.o bkplip.o \
terakdisk.o synth.o emu2149.o sdltty.o
terakdisk.o synth.o emu2149.o sdlsound.o sdltty.o
INCS = defines.h scr.h conf.h emu2149.h emutypes.h
USRCS = readtape.c maketape.c pngtorgba.c
TEXTS = README.html configure.in icon.c

109
sdlsound.c Normal file
View File

@ -0,0 +1,109 @@
#include "defines.h"
#include "conf.h"
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_mutex.h>
#include <libintl.h>
#define _(String) gettext (String)
//#define SOUND_EXPONENT (8+io_sound_freq/20000)
//#define SOUND_BUFSIZE (1<<SOUND_EXPONENT) /* about 1/43 sec */
#define SOUND_BUFSIZE 512
#define NUMBUF 2
typedef struct {
short * buf;
unsigned int ptr;
} sound_buf_t;
sound_buf_t sound_buf[NUMBUF];
unsigned io_sound_bufsize;
int cur_buf;
static SDL_sem * sem;
static void callback(void * dummy, Uint8 * outbuf, int len)
{
int i;
static int cur_out_buf;
if (SDL_SemValue(sem) == NUMBUF) {
// Underflow: TODO fill the buffer with silence
// fprintf(stderr, "!");
return;
}
memcpy(outbuf, sound_buf[cur_out_buf].buf, len);
cur_out_buf = (cur_out_buf + 1) % NUMBUF;
SDL_SemPost(sem);
}
static void sound_finish() {
/* release the write thread so it can terminate */
SDL_PauseAudio(1);
SDL_DestroySemaphore(sem);
}
static SDL_AudioSpec desired;
void platform_sound_flush() {
if (sound_buf[cur_buf].ptr != 0) {
SDL_SemWait(sem);
sound_buf[cur_buf].ptr = 0;
cur_buf = (cur_buf + 1) % NUMBUF;
}
}
void sound_write_sample(short val) {
short * p = &sound_buf[cur_buf].buf[sound_buf[cur_buf].ptr++];
if (sound_buf[cur_buf].buf == NULL)
return;
*p = val;
if (io_sound_bufsize == sound_buf[cur_buf].ptr) {
platform_sound_flush();
}
}
void sound_discard() {
sound_buf[cur_buf].ptr = 0;
}
void platform_sound_init() {
int iarg, i;
if (fullspeed) {
io_max_sound_age = 2 * SOUND_BUFSIZE;
/* otherwise UINT_MAX */
}
fprintf(stderr, _("sound_init called\n"));
if (-1 == SDL_InitSubSystem(SDL_INIT_AUDIO)) {
fprintf(stderr, _("Failed to initialize audio subsystem\n"));
}
desired.format = 16;
desired.channels = 1;
desired.freq = io_sound_freq;
desired.samples = io_sound_bufsize = SOUND_BUFSIZE;
desired.callback = callback;
if (-1 == SDL_OpenAudio(&desired, 0)) {
fprintf(stderr, _("Failed to initialize sound, freq %d, %d samples\n"), io_sound_freq, SOUND_BUFSIZE);
nflag = 0;
return;
}
sem = SDL_CreateSemaphore(NUMBUF);
for (i = 0; i < NUMBUF; i++) {
sound_buf[i].ptr = 0;
sound_buf[i].buf = malloc(io_sound_bufsize * sizeof(short));
}
if (!sound_buf[NUMBUF-1].buf) {
fprintf(stderr, _("Failed to allocate sound buffers\n"));
exit(1);
}
atexit(sound_finish);
SDL_PauseAudio(0);
}

117
sound.c
View File

@ -1,131 +1,46 @@
#include "defines.h"
#include "conf.h"
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_mutex.h>
#include <libintl.h>
#define _(String) gettext (String)
#include "intl.h"
#define SOUND_EXPONENT (8+io_sound_freq/20000)
//#define SOUND_BUFSIZE (1<<SOUND_EXPONENT) /* about 1/43 sec */
#define SOUND_BUFSIZE 512
#define MAX_SOUND_AGE ~0 /* always play */
unsigned io_sound_bufsize,
io_sound_freq = 11025;
typedef struct {
short * buf;
unsigned int ptr;
} sound_buf_t;
#define NUMBUF 2
sound_buf_t sound_buf[NUMBUF];
SDL_sem * sem;
int cur_buf;
void callback(void * dummy, Uint8 * outbuf, int len)
{
int i;
static int cur_out_buf;
if (SDL_SemValue(sem) == NUMBUF) {
// Underflow: TODO fill the buffer with silence
// fprintf(stderr, "!");
return;
}
memcpy(outbuf, sound_buf[cur_out_buf].buf, len);
cur_out_buf = (cur_out_buf + 1) % NUMBUF;
SDL_SemPost(sem);
}
unsigned io_sound_freq = 44100;
/* Called after every instruction */
void sound_flush() {
int i;
if (fullspeed && io_sound_age >= io_max_sound_age && covox_age >= io_max_sound_age) {
if (sound_buf[cur_buf].ptr != 0)
{
SDL_SemWait(sem);
sound_buf[cur_buf].ptr = 0;
cur_buf = (cur_buf + 1) % NUMBUF;
}
platform_sound_flush();
return;
}
while (ticks >= io_sound_count) {
short * p = &sound_buf[cur_buf].buf[sound_buf[cur_buf].ptr++];
if (io_sound_age < 1000)
*p = io_sound_val + covox_val << 4;
sound_write_sample (io_sound_val + covox_val << 4);
else
*p = (covox_val << 4) + synth_next();
io_sound_count += io_sound_pace;
sound_write_sample ((covox_val << 4) + synth_next());
io_sound_age++;
if (io_sound_age == io_max_sound_age) {
platform_sound_flush();
}
covox_age++;
if (io_sound_bufsize == sound_buf[cur_buf].ptr ||
io_sound_age == io_max_sound_age) {
SDL_SemWait(sem);
sound_buf[cur_buf].ptr = 0;
cur_buf = (cur_buf + 1) % NUMBUF;
io_sound_count += io_sound_pace;
}
}
}
void sound_finish() {
/* release the write thread so it can terminate */
SDL_PauseAudio(1);
SDL_DestroySemaphore(sem);
}
SDL_AudioSpec desired;
void sound_init() {
static init_done = 0;
int iarg, i;
io_max_sound_age = MAX_SOUND_AGE;
io_sound_age = MAX_SOUND_AGE;
static int init_done = 0;
if (!nflag)
return;
if (fullspeed) {
io_max_sound_age = 2 * SOUND_BUFSIZE;
/* otherwise UINT_MAX */
}
if (init_done) {
sound_buf[cur_buf].ptr = 0;
io_sound_age = io_max_sound_age;
return;
}
fprintf(stderr, _("sound_init called\n"));
if (-1 == SDL_InitSubSystem(SDL_INIT_AUDIO)) {
fprintf(stderr, _("Failed to initialize audio subsystem\n"));
}
desired.format = 16;
desired.channels = 1;
desired.freq = io_sound_freq;
desired.samples = io_sound_bufsize = SOUND_BUFSIZE;
desired.callback = callback;
if (-1 == SDL_OpenAudio(&desired, 0)) {
fprintf(stderr, _("Failed to initialize sound, freq %d, %d samples\n"), io_sound_freq, SOUND_BUFSIZE);
nflag = 0;
sound_discard();
return;
}
io_sound_pace = TICK_RATE/io_sound_freq;
sem = SDL_CreateSemaphore(NUMBUF);
platform_sound_init();
for (i = 0; i < NUMBUF; i++) {
sound_buf[i].ptr = 0;
sound_buf[i].buf = malloc(io_sound_bufsize * sizeof(short));
}
if (!sound_buf[NUMBUF-1].buf) {
fprintf(stderr, _("Failed to allocate sound buffers\n"));
exit(1);
}
atexit(sound_finish);
SDL_PauseAudio(0);
io_sound_pace = TICK_RATE/(io_sound_freq + 0.0);
io_max_sound_age = MAX_SOUND_AGE;
io_sound_age = MAX_SOUND_AGE; /* in io_sound_pace's since last change */
init_done = 1;
}