Make the UxnAudio struct private to audio.c.

This commit is contained in:
Andrew Alderwick 2022-03-17 16:59:36 +00:00
parent 084a0f5ab4
commit 5dcf0a2b35
3 changed files with 49 additions and 38 deletions

View File

@ -16,6 +16,14 @@ WITH REGARD TO THIS SOFTWARE.
#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) #define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025)
#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) #define ADSR_STEP (SAMPLE_FREQUENCY / 0xf)
typedef struct {
Uint8 *addr;
Uint32 count, advance, period, age, a, d, s, r;
Uint16 i, len;
Sint8 volume[2];
Uint8 pitch, repeat;
} UxnAudio;
/* clang-format off */ /* clang-format off */
static Uint32 advances[12] = { static Uint32 advances[12] = {
@ -40,8 +48,9 @@ envelope(UxnAudio *c, Uint32 age)
} }
int int
audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end) audio_render(int instance, Sint16 *sample, Sint16 *end)
{ {
UxnAudio *c = &uxn_audio[instance];
Sint32 s; Sint32 s;
if(!c->advance || !c->period) return 0; if(!c->advance || !c->period) return 0;
while(sample < end) { while(sample < end) {
@ -59,13 +68,26 @@ audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end)
*sample++ += s * c->volume[0] / 0x180; *sample++ += s * c->volume[0] / 0x180;
*sample++ += s * c->volume[1] / 0x180; *sample++ += s * c->volume[1] / 0x180;
} }
if(!c->advance) audio_finished_handler(c); if(!c->advance) audio_finished_handler(instance);
return 1; return 1;
} }
void void
audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch) audio_start(int instance, Device *d)
{ {
UxnAudio *c = &uxn_audio[instance];
Uint16 addr, adsr;
Uint8 pitch;
DEVPEEK16(adsr, 0x8);
DEVPEEK16(c->len, 0xa);
DEVPEEK16(addr, 0xc);
if(c->len > 0x10000 - addr)
c->len = 0x10000 - addr;
c->addr = &d->u->ram[addr];
c->volume[0] = d->dat[0xe] >> 4;
c->volume[1] = d->dat[0xe] & 0xf;
c->repeat = !(d->dat[0xf] & 0x80);
pitch = d->dat[0xf] & 0x7f;
if(pitch < 108 && c->len) if(pitch < 108 && c->len)
c->advance = advances[pitch % 12] >> (8 - pitch / 12); c->advance = advances[pitch % 12] >> (8 - pitch / 12);
else { else {
@ -85,8 +107,9 @@ audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch)
} }
Uint8 Uint8
audio_get_vu(UxnAudio *c) audio_get_vu(int instance)
{ {
UxnAudio *c = &uxn_audio[instance];
int i; int i;
Sint32 sum[2] = {0, 0}; Sint32 sum[2] = {0, 0};
if(!c->advance || !c->period) return 0; if(!c->advance || !c->period) return 0;
@ -97,3 +120,10 @@ audio_get_vu(UxnAudio *c)
} }
return (sum[0] << 4) | sum[1]; return (sum[0] << 4) | sum[1];
} }
Uint16
audio_get_position(int instance)
{
UxnAudio *c = &uxn_audio[instance];
return c->i;
}

View File

@ -15,17 +15,8 @@ typedef signed int Sint32;
#define SAMPLE_FREQUENCY 44100 #define SAMPLE_FREQUENCY 44100
#define POLYPHONY 4 #define POLYPHONY 4
typedef struct { Uint8 audio_get_vu(int instance);
Uint8 *addr; Uint16 audio_get_position(int instance);
Uint32 count, advance, period, age, a, d, s, r; int audio_render(int instance, Sint16 *sample, Sint16 *end);
Uint16 i, len; void audio_start(int instance, Device *d);
Sint8 volume[2]; void audio_finished_handler(int instance);
Uint8 pitch, repeat;
} UxnAudio;
extern UxnAudio uxn_audio[POLYPHONY];
Uint8 audio_get_vu(UxnAudio *c);
int audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end);
void audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch);
void audio_finished_handler(UxnAudio *c);

View File

@ -58,21 +58,21 @@ error(char *msg, const char *err)
static void static void
audio_callback(void *u, Uint8 *stream, int len) audio_callback(void *u, Uint8 *stream, int len)
{ {
int i, running = 0; int instance, running = 0;
Sint16 *samples = (Sint16 *)stream; Sint16 *samples = (Sint16 *)stream;
SDL_memset(stream, 0, len); SDL_memset(stream, 0, len);
for(i = 0; i < POLYPHONY; i++) for(instance = 0; instance < POLYPHONY; instance++)
running += audio_render(&uxn_audio[i], samples, samples + len / 2); running += audio_render(instance, samples, samples + len / 2);
if(!running) if(!running)
SDL_PauseAudioDevice(audio_id, 1); SDL_PauseAudioDevice(audio_id, 1);
(void)u; (void)u;
} }
void void
audio_finished_handler(UxnAudio *c) audio_finished_handler(int instance)
{ {
SDL_Event event; SDL_Event event;
event.type = audio0_event + (c - uxn_audio); event.type = audio0_event + instance;
SDL_PushEvent(&event); SDL_PushEvent(&event);
} }
@ -185,11 +185,11 @@ console_deo(Device *d, Uint8 port)
static Uint8 static Uint8
audio_dei(Device *d, Uint8 port) audio_dei(Device *d, Uint8 port)
{ {
UxnAudio *c = &uxn_audio[d - devaudio0]; int instance = d - devaudio0;
if(!audio_id) return d->dat[port]; if(!audio_id) return d->dat[port];
switch(port) { switch(port) {
case 0x4: return audio_get_vu(c); case 0x4: return audio_get_vu(instance);
case 0x2: DEVPOKE16(0x2, c->i); /* fall through */ case 0x2: DEVPOKE16(0x2, audio_get_position(instance)); /* fall through */
default: return d->dat[port]; default: return d->dat[port];
} }
} }
@ -197,21 +197,11 @@ audio_dei(Device *d, Uint8 port)
static void static void
audio_deo(Device *d, Uint8 port) audio_deo(Device *d, Uint8 port)
{ {
UxnAudio *c = &uxn_audio[d - devaudio0]; int instance = d - devaudio0;
if(!audio_id) return; if(!audio_id) return;
if(port == 0xf) { if(port == 0xf) {
Uint16 addr, adsr;
SDL_LockAudioDevice(audio_id); SDL_LockAudioDevice(audio_id);
DEVPEEK16(adsr, 0x8); audio_start(instance, d);
DEVPEEK16(c->len, 0xa);
DEVPEEK16(addr, 0xc);
if(c->len > 0x10000 - addr)
c->len = 0x10000 - addr;
c->addr = &d->u->ram[addr];
c->volume[0] = d->dat[0xe] >> 4;
c->volume[1] = d->dat[0xe] & 0xf;
c->repeat = !(d->dat[0xf] & 0x80);
audio_start(c, adsr, d->dat[0xf] & 0x7f);
SDL_UnlockAudioDevice(audio_id); SDL_UnlockAudioDevice(audio_id);
SDL_PauseAudioDevice(audio_id, 0); SDL_PauseAudioDevice(audio_id, 0);
} }