commit 87d67985930fc55f457454e8b0927c69b41ba333
parent c4ec4a6340ef2552eb38b14a103a5ff9c552e434
Author: neauoire <aliceffekt@gmail.com>
Date: Fri, 20 Oct 2023 11:54:25 -0400
Formatting
Diffstat:
3 files changed, 249 insertions(+), 236 deletions(-)
diff --git a/src/devices/audio.c b/src/devices/audio.c
@@ -19,42 +19,44 @@ WITH REGARD TO THIS SOFTWARE.
#define INTERPOL_METHOD 1
typedef enum EnvStage {
- ENV_ATTACK = (1 << 0),
- ENV_DECAY = (1 << 1),
- ENV_SUSTAIN = (1 << 2),
- ENV_RELEASE = (1 << 3),
+ ENV_ATTACK = (1 << 0),
+ ENV_DECAY = (1 << 1),
+ ENV_SUSTAIN = (1 << 2),
+ ENV_RELEASE = (1 << 3),
} EnvStage;
typedef struct Envelope {
- float a;
- float d;
- float s;
- float r;
- float vol;
- EnvStage stage;
+ float a;
+ float d;
+ float s;
+ float r;
+ float vol;
+ EnvStage stage;
} Envelope;
typedef struct Sample {
- Uint8 *data;
- float len;
- float pos;
- float inc;
- float loop;
- Uint8 pitch;
- Envelope env;
+ Uint8 *data;
+ float len;
+ float pos;
+ float inc;
+ float loop;
+ Uint8 pitch;
+ Envelope env;
} Sample;
typedef struct AudioChannel {
- Sample sample;
- Sample next_sample;
- bool xfade;
- float duration;
- float vol_l;
- float vol_r;
+ Sample sample;
+ Sample next_sample;
+ bool xfade;
+ float duration;
+ float vol_l;
+ float vol_r;
} AudioChannel;
AudioChannel channel[POLYPHONY];
+/* clang-format off */
+
const float tuning[109] = {
0.00058853f, 0.00062352f, 0.00066060f, 0.00069988f, 0.00074150f,
0.00078559f, 0.00083230f, 0.00088179f, 0.00093423f, 0.00098978f,
@@ -80,236 +82,247 @@ const float tuning[109] = {
0.25338348f, 0.26845044f, 0.28441334f, 0.30132544f,
};
+/* clang-format on */
+
void
-env_on(Envelope *env) {
- env->stage = ENV_ATTACK;
- env->vol = 0.0f;
- if (env->a > 0) {
- env->a = (SOUND_TIMER / AUDIO_BUFSIZE) / env->a;
- } else if (env->stage == ENV_ATTACK) {
- env->stage = ENV_DECAY;
- env->vol = 1.0f;
- }
- if (env->d < 10.0f) {
- env->d = 10.0f;
- }
- env->d = (SOUND_TIMER / AUDIO_BUFSIZE) / env->d;
- if (env->r < 10.0f) {
- env->r = 10.0f;
- }
- env->r = (SOUND_TIMER / AUDIO_BUFSIZE) / env->r;
+env_on(Envelope *env)
+{
+ env->stage = ENV_ATTACK;
+ env->vol = 0.0f;
+ if(env->a > 0) {
+ env->a = (SOUND_TIMER / AUDIO_BUFSIZE) / env->a;
+ } else if(env->stage == ENV_ATTACK) {
+ env->stage = ENV_DECAY;
+ env->vol = 1.0f;
+ }
+ if(env->d < 10.0f) {
+ env->d = 10.0f;
+ }
+ env->d = (SOUND_TIMER / AUDIO_BUFSIZE) / env->d;
+ if(env->r < 10.0f) {
+ env->r = 10.0f;
+ }
+ env->r = (SOUND_TIMER / AUDIO_BUFSIZE) / env->r;
}
void
-env_off(Envelope *env) {
- env->stage = ENV_RELEASE;
+env_off(Envelope *env)
+{
+ env->stage = ENV_RELEASE;
}
void
-note_on(AudioChannel *channel, Uint16 duration, Uint8 *data, Uint16 len, Uint8 vol,
- Uint8 attack, Uint8 decay, Uint8 sustain, Uint8 release, Uint8 pitch, bool loop) {
- channel->duration = duration > 0 ? duration : len / 44.1f;
- channel->vol_l = (vol >> 4) / 15.0f;
- channel->vol_r = (vol & 0xf) / 15.0f;
-
- Sample sample = {0};
- sample.data = data;
- sample.len = len;
- sample.pos = 0;
- sample.env.a = attack * 64.0f;
- sample.env.d = decay * 64.0f;
- sample.env.s = sustain / 16.0f;
- sample.env.r = release * 64.0f;
- if (loop) {
- sample.loop = len;
- } else {
- sample.loop = 0;
- }
- env_on(&sample.env);
- if (pitch < 20) {
- pitch = 20;
- }
- float sample_rate = 44100 / 261.60;
- if (len <= 256) {
- sample_rate = len;
- }
- const float *inc = &tuning[pitch - 20];
- sample.inc = *(inc) * sample_rate;
-
- channel->next_sample = sample;
- channel->xfade = true;
+note_on(AudioChannel *channel, Uint16 duration, Uint8 *data, Uint16 len, Uint8 vol, Uint8 attack, Uint8 decay, Uint8 sustain, Uint8 release, Uint8 pitch, bool loop)
+{
+ channel->duration = duration > 0 ? duration : len / 44.1f;
+ channel->vol_l = (vol >> 4) / 15.0f;
+ channel->vol_r = (vol & 0xf) / 15.0f;
+
+ Sample sample = {0};
+ sample.data = data;
+ sample.len = len;
+ sample.pos = 0;
+ sample.env.a = attack * 64.0f;
+ sample.env.d = decay * 64.0f;
+ sample.env.s = sustain / 16.0f;
+ sample.env.r = release * 64.0f;
+ if(loop) {
+ sample.loop = len;
+ } else {
+ sample.loop = 0;
+ }
+ env_on(&sample.env);
+ if(pitch < 20) {
+ pitch = 20;
+ }
+ float sample_rate = 44100 / 261.60;
+ if(len <= 256) {
+ sample_rate = len;
+ }
+ const float *inc = &tuning[pitch - 20];
+ sample.inc = *(inc)*sample_rate;
+
+ channel->next_sample = sample;
+ channel->xfade = true;
}
void
-note_off(AudioChannel *channel, Uint16 duration) {
- channel->duration = duration;
- env_off(&channel->sample.env);
+note_off(AudioChannel *channel, Uint16 duration)
+{
+ channel->duration = duration;
+ env_off(&channel->sample.env);
}
void
-env_advance(Envelope *env) {
- switch (env->stage) {
- case ENV_ATTACK: {
- env->vol += env->a;
- if (env->vol >= 1.0f) {
- env->stage = ENV_DECAY;
- env->vol = 1.0f;
- }
- } break;
- case ENV_DECAY: {
- env->vol -= env->d;
- if (env->vol <= env->s || env->d <= 0) {
- env->stage = ENV_SUSTAIN;
- env->vol = env->s;
- }
- } break;
- case ENV_SUSTAIN: {
- env->vol = env->s;
- } break;
- case ENV_RELEASE: {
- if (env->vol <= 0 || env->r <= 0) {
- env->vol = 0;
- } else {
- env->vol -= env->r;
- }
- } break;
- }
+env_advance(Envelope *env)
+{
+ switch(env->stage) {
+ case ENV_ATTACK: {
+ env->vol += env->a;
+ if(env->vol >= 1.0f) {
+ env->stage = ENV_DECAY;
+ env->vol = 1.0f;
+ }
+ } break;
+ case ENV_DECAY: {
+ env->vol -= env->d;
+ if(env->vol <= env->s || env->d <= 0) {
+ env->stage = ENV_SUSTAIN;
+ env->vol = env->s;
+ }
+ } break;
+ case ENV_SUSTAIN: {
+ env->vol = env->s;
+ } break;
+ case ENV_RELEASE: {
+ if(env->vol <= 0 || env->r <= 0) {
+ env->vol = 0;
+ } else {
+ env->vol -= env->r;
+ }
+ } break;
+ }
}
float
-interpolate_sample(Uint8 *data, Uint16 len, float pos) {
+interpolate_sample(Uint8 *data, Uint16 len, float pos)
+{
#if INTERPOL_METHOD == 0
- return data[(int)pos];
+ return data[(int)pos];
#elif INTERPOL_METHOD == 1
- float x = pos;
- int x0 = (int)x;
- int x1 = (x0 + 1);
- float y0 = data[x0];
- float y1 = data[x1 % len];
- x = x - x0;
- float y = y0 + x * (y1 - y0);
- return y;
+ float x = pos;
+ int x0 = (int)x;
+ int x1 = (x0 + 1);
+ float y0 = data[x0];
+ float y1 = data[x1 % len];
+ x = x - x0;
+ float y = y0 + x * (y1 - y0);
+ return y;
#elif INTERPOL_METHOD == 2
- float x = pos;
- int x0 = x - 1;
- int x1 = x;
- int x2 = x + 1;
- int x3 = x + 2;
- float y0 = data[x0 % len];
- float y1 = data[x1];
- float y2 = data[x2 % len];
- float y3 = data[x3 % len];
- x = x - x1;
- float c0 = y1;
- float c1 = 0.5f * (y2 - y0);
- float c2 = y0 - 2.5f * y1 + 2.f * y2 - 0.5f * y3;
- float c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0);
- return ((c3 * x + c2) * x + c1) * x + c0;
+ float x = pos;
+ int x0 = x - 1;
+ int x1 = x;
+ int x2 = x + 1;
+ int x3 = x + 2;
+ float y0 = data[x0 % len];
+ float y1 = data[x1];
+ float y2 = data[x2 % len];
+ float y3 = data[x3 % len];
+ x = x - x1;
+ float c0 = y1;
+ float c1 = 0.5f * (y2 - y0);
+ float c2 = y0 - 2.5f * y1 + 2.f * y2 - 0.5f * y3;
+ float c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0);
+ return ((c3 * x + c2) * x + c1) * x + c0;
#endif
}
Sint16
-next_sample(Sample *sample) {
- if (sample->pos >= sample->len) {
- if (sample->loop == 0) {
- sample->data = 0;
- return 0;
- }
- while (sample->pos >= sample->len) {
- sample->pos -= sample->loop;
- }
- }
-
- float val = interpolate_sample(sample->data, sample->len, sample->pos);
- val *= sample->env.vol;
- Sint8 next = (Sint8)0x80 ^ (Uint8)val;
-
- sample->pos += sample->inc;
- env_advance(&sample->env);
- return next;
+next_sample(Sample *sample)
+{
+ if(sample->pos >= sample->len) {
+ if(sample->loop == 0) {
+ sample->data = 0;
+ return 0;
+ }
+ while(sample->pos >= sample->len) {
+ sample->pos -= sample->loop;
+ }
+ }
+
+ float val = interpolate_sample(sample->data, sample->len, sample->pos);
+ val *= sample->env.vol;
+ Sint8 next = (Sint8)0x80 ^ (Uint8)val;
+
+ sample->pos += sample->inc;
+ env_advance(&sample->env);
+ return next;
}
void
-audio_handler(void *ctx, Uint8 *out_stream, int len) {
- Sint16 *stream = (Sint16 *)out_stream;
- memset(stream, 0x00, len);
-
- int n;
- for (n = 0; n < POLYPHONY; n++) {
- Uint8 device = (3 + n) << 4;
- Uxn *u = (Uxn *)ctx;
- Uint8 *addr = &u->dev[device];
- if (channel[n].duration <= 0 && PEEK2(addr)) {
+audio_handler(void *ctx, Uint8 *out_stream, int len)
+{
+ Sint16 *stream = (Sint16 *)out_stream;
+ memset(stream, 0x00, len);
+
+ int n;
+ for(n = 0; n < POLYPHONY; n++) {
+ Uint8 device = (3 + n) << 4;
+ Uxn *u = (Uxn *)ctx;
+ Uint8 *addr = &u->dev[device];
+ if(channel[n].duration <= 0 && PEEK2(addr)) {
uxn_eval(u, PEEK2(addr));
- }
- channel[n].duration -= SOUND_TIMER;
-
- int x = 0;
- if (channel[n].xfade) {
- float delta = 1.0f / (XFADE_SAMPLES * 2);
- while (x < XFADE_SAMPLES * 2) {
- float alpha = x * delta;
- float beta = 1.0f - alpha;
- Sint16 next_a = next_sample(&channel[n].next_sample);
- Sint16 next_b = 0;
- if (channel[n].sample.data != 0) {
- next_b = next_sample(&channel[n].sample);
- }
- Sint16 next = alpha * next_a + beta * next_b;
- stream[x++] += next * channel[n].vol_l;
- stream[x++] += next * channel[n].vol_r;
- }
- channel[n].sample = channel[n].next_sample;
- channel[n].xfade = false;
- }
- Sample *sample = &channel[n].sample;
- while (x < len / 2) {
- if (sample->data == 0) {
- break;
- }
- Sint16 next = next_sample(sample);
- stream[x++] += next * channel[n].vol_l;
- stream[x++] += next * channel[n].vol_r;
- }
- }
- int i;
- for (i = 0; i < len / 2; i++) {
- stream[i] <<= 6;
- }
+ }
+ channel[n].duration -= SOUND_TIMER;
+
+ int x = 0;
+ if(channel[n].xfade) {
+ float delta = 1.0f / (XFADE_SAMPLES * 2);
+ while(x < XFADE_SAMPLES * 2) {
+ float alpha = x * delta;
+ float beta = 1.0f - alpha;
+ Sint16 next_a = next_sample(&channel[n].next_sample);
+ Sint16 next_b = 0;
+ if(channel[n].sample.data != 0) {
+ next_b = next_sample(&channel[n].sample);
+ }
+ Sint16 next = alpha * next_a + beta * next_b;
+ stream[x++] += next * channel[n].vol_l;
+ stream[x++] += next * channel[n].vol_r;
+ }
+ channel[n].sample = channel[n].next_sample;
+ channel[n].xfade = false;
+ }
+ Sample *sample = &channel[n].sample;
+ while(x < len / 2) {
+ if(sample->data == 0) {
+ break;
+ }
+ Sint16 next = next_sample(sample);
+ stream[x++] += next * channel[n].vol_l;
+ stream[x++] += next * channel[n].vol_r;
+ }
+ }
+ int i;
+ for(i = 0; i < len / 2; i++) {
+ stream[i] <<= 6;
+ }
}
void
audio_start(int idx, Uint8 *d, Uxn *u)
{
- Uint16 duration = PEEK2(d + 0x5);
- Uint8 off = d[0xf] == 0x00;
-
- if (!off) {
- Uint16 addr = PEEK2(d + 0xc);
- Uint8 *data = &u->ram[addr];
- Uint16 len = PEEK2(d + 0xa);
- Uint8 volume = d[0xe];
- bool loop = !(d[0xf] & 0x80);
- Uint8 pitch = d[0xf] & 0x7f;
- Uint16 adsr = PEEK2(d + 0x8);
- Uint8 attack = (adsr >> 12) & 0xF;
- Uint8 decay = (adsr >> 8) & 0xF;
- Uint8 sustain = (adsr >> 4) & 0xF;
- Uint8 release = (adsr >> 0) & 0xF;
- note_on(&channel[idx], duration, data, len, volume, attack, decay, sustain, release, pitch, loop);
- } else {
- note_off(&channel[idx], duration);
- }
+ Uint16 duration = PEEK2(d + 0x5);
+ Uint8 off = d[0xf] == 0x00;
+
+ if(!off) {
+ Uint16 addr = PEEK2(d + 0xc);
+ Uint8 *data = &u->ram[addr];
+ Uint16 len = PEEK2(d + 0xa);
+ Uint8 volume = d[0xe];
+ bool loop = !(d[0xf] & 0x80);
+ Uint8 pitch = d[0xf] & 0x7f;
+ Uint16 adsr = PEEK2(d + 0x8);
+ Uint8 attack = (adsr >> 12) & 0xF;
+ Uint8 decay = (adsr >> 8) & 0xF;
+ Uint8 sustain = (adsr >> 4) & 0xF;
+ Uint8 release = (adsr >> 0) & 0xF;
+ note_on(&channel[idx], duration, data, len, volume, attack, decay, sustain, release, pitch, loop);
+ } else {
+ note_off(&channel[idx], duration);
+ }
}
Uint8
-audio_get_vu(int instance) {
- return channel[instance].sample.env.vol * 255.0f;
+audio_get_vu(int instance)
+{
+ return channel[instance].sample.env.vol * 255.0f;
}
Uint16
-audio_get_position(int instance) {
- return channel[instance].sample.pos;
+audio_get_position(int instance)
+{
+ return channel[instance].sample.pos;
}
diff --git a/src/uxncli.c b/src/uxncli.c
@@ -64,7 +64,7 @@ emu_end(Uxn *u)
int
main(int argc, char **argv)
{
- Uint8 dev[0x100] = {0};
+ Uint8 dev[0x100] = {0};
Uxn u;
u.dev = (Uint8 *)&dev;
int i = 1;
diff --git a/src/uxnemu.c b/src/uxnemu.c
@@ -70,20 +70,20 @@ clamp(int v, int min, int max)
static Uint8
audio_dei(int instance, Uint8 *d, Uint8 port)
{
- switch(port) {
- case 0x2:
- return audio_get_position(instance) >> 8;
- case 0x3:
- return audio_get_position(instance);
- case 0x4:
- return audio_get_vu(instance);
- case 0x0:
- case 0x8:
- case 0xa:
- case 0xc: return PEEK2(d + port);
- default: return d[port];
- }
- return d[port];
+ switch(port) {
+ case 0x2:
+ return audio_get_position(instance) >> 8;
+ case 0x3:
+ return audio_get_position(instance);
+ case 0x4:
+ return audio_get_vu(instance);
+ case 0x0:
+ case 0x8:
+ case 0xa:
+ case 0xc: return PEEK2(d + port);
+ default: return d[port];
+ }
+ return d[port];
}
static void
@@ -94,7 +94,7 @@ audio_deo(int instance, Uint8 *d, Uint8 port, Uxn *u)
SDL_LockAudioDevice(audio_id);
audio_start(instance, d, u);
SDL_UnlockAudioDevice(audio_id);
- SDL_PauseAudioDevice(audio_id, 0);
+ SDL_PauseAudioDevice(audio_id, 0);
}
}
@@ -271,7 +271,7 @@ emu_init(Uxn *u)
deadline_interval = ms_interval * TIMEOUT_MS;
exec_deadline = SDL_GetPerformanceCounter() + deadline_interval;
screen_resize(WIDTH, HEIGHT);
- SDL_PauseAudioDevice(audio_id, 1);
+ SDL_PauseAudioDevice(audio_id, 1);
return 1;
}
@@ -514,7 +514,7 @@ emu_run(Uxn *u, char *rom)
static int
emu_end(Uxn *u)
{
- SDL_CloseAudioDevice(audio_id);
+ SDL_CloseAudioDevice(audio_id);
#ifdef _WIN32
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
TerminateThread((HANDLE)SDL_GetThreadID(stdin_thread), 0);
@@ -529,7 +529,7 @@ emu_end(Uxn *u)
int
main(int argc, char **argv)
{
- Uint8 dev[0x100] = {0};
+ Uint8 dev[0x100] = {0};
Uxn u = {0};
Uxn u_audio = {0};
u.dev = (Uint8 *)&dev;
@@ -555,10 +555,10 @@ main(int argc, char **argv)
char *rom = argv[i++];
if(!system_init(&u, ram, rom)) {
return system_error("Init", "Failed to initialize uxn.");
- }
+ }
if(!system_init(&u_audio, ram, rom)) {
return system_error("Init", "Failed to initialize uxn.");
- }
+ }
if(!emu_init(&u_audio))
return system_error("Init", "Failed to initialize varvara.");
/* Game Loop */