uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

commit c3506869b50287f6e21c1c8f4ce4479a501f5e06
parent 7b33cf3d9554bbca8bd8fb4f5a1b0976a5b8a6dd
Author: neauoire <aliceffekt@gmail.com>
Date:   Tue, 28 Dec 2021 13:47:35 -0800

Renamed Apu to Audio

Diffstat:
Mbuild.sh | 6+++---
Mmkfile | 6+++---
Dsrc/devices/apu.c | 97-------------------------------------------------------------------------------
Dsrc/devices/apu.h | 28----------------------------
Asrc/devices/audio.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/devices/audio.h | 32++++++++++++++++++++++++++++++++
Msrc/devices/screen.c | 3+--
Msrc/uxnemu.c | 18++++++++----------
8 files changed, 146 insertions(+), 143 deletions(-)

diff --git a/build.sh b/build.sh @@ -16,8 +16,8 @@ then clang-format -i src/uxn.c clang-format -i src/devices/screen.h clang-format -i src/devices/screen.c - clang-format -i src/devices/apu.h - clang-format -i src/devices/apu.c + clang-format -i src/devices/audio.h + clang-format -i src/devices/audio.c clang-format -i src/devices/file.h clang-format -i src/devices/file.c clang-format -i src/devices/mouse.h @@ -62,7 +62,7 @@ fi echo "Building.." ${CC} ${CFLAGS} src/uxnasm.c -o bin/uxnasm -${CC} ${CFLAGS} ${CORE} src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/screen.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu +${CC} ${CFLAGS} ${CORE} src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/screen.c src/devices/audio.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu ${CC} ${CFLAGS} ${CORE} src/devices/file.c src/uxncli.c -o bin/uxncli if [ -d "$HOME/bin" ] diff --git a/mkfile b/mkfile @@ -6,7 +6,7 @@ ROM=${USM:%.tal=%.rom} CFLAGS=$CFLAGS -D__plan9__ -I/sys/include/npe -I/sys/include/npe/SDL2 HFILES=\ /sys/include/npe/stdio.h\ - src/devices/apu.h\ + src/devices/audio.h\ src/devices/file.h\ src/devices/screen.h\ src/uxn.h\ @@ -35,13 +35,13 @@ bin/uxncli: file.$O uxncli.$O uxn.$O bin/uxnasm: uxnasm.$O $LD $LDFLAGS -o $target $prereq -bin/uxnemu: uxnemu.$O apu.$O file.$O screen.$O uxn.$O +bin/uxnemu: uxnemu.$O audio.$O file.$O screen.$O uxn.$O $LD $LDFLAGS -o $target $prereq (uxnasm|uxncli|uxnemu|uxn)\.$O:R: src/\1.c $CC $CFLAGS -Isrc -o $target src/$stem1.c -(apu|file|screen)\.$O:R: src/devices/\1.c +(audio|file|screen)\.$O:R: src/devices/\1.c $CC $CFLAGS -Isrc -o $target src/devices/$stem1.c nuke:V: clean diff --git a/src/devices/apu.c b/src/devices/apu.c @@ -1,97 +0,0 @@ -#include "../uxn.h" -#include "apu.h" - -/* -Copyright (c) 2021 Devine Lu Linvega -Copyright (c) 2021 Andrew Alderwick - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) -#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) - -/* clang-format off */ - -static Uint32 advances[12] = { - 0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1, - 0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c -}; - -/* clang-format on */ - -static Sint32 -envelope(Apu *c, Uint32 age) -{ - if(!c->r) return 0x0888; - if(age < c->a) return 0x0888 * age / c->a; - if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a); - if(age < c->s) return 0x0444; - if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s); - c->advance = 0; - return 0x0000; -} - -int -apu_render(Apu *c, Sint16 *sample, Sint16 *end) -{ - Sint32 s; - if(!c->advance || !c->period) return 0; - while(sample < end) { - c->count += c->advance; - c->i += c->count / c->period; - c->count %= c->period; - if(c->i >= c->len) { - if(!c->repeat) { - c->advance = 0; - break; - } - c->i %= c->len; - } - s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++); - *sample++ += s * c->volume[0] / 0x180; - *sample++ += s * c->volume[1] / 0x180; - } - if(!c->advance) apu_finished_handler(c); - return 1; -} - -void -apu_start(Apu *c, Uint16 adsr, Uint8 pitch) -{ - if(pitch < 108 && c->len) - c->advance = advances[pitch % 12] >> (8 - pitch / 12); - else { - c->advance = 0; - return; - } - c->a = ADSR_STEP * (adsr >> 12); - c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a; - c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d; - c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s; - c->age = 0; - c->i = 0; - if(c->len <= 0x100) /* single cycle mode */ - c->period = NOTE_PERIOD * 337 / 2 / c->len; - else /* sample repeat mode */ - c->period = NOTE_PERIOD; -} - -Uint8 -apu_get_vu(Apu *c) -{ - int i; - Sint32 sum[2] = {0, 0}; - if(!c->advance || !c->period) return 0; - for(i = 0; i < 2; ++i) { - if(!c->volume[i]) continue; - sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800; - if(sum[i] > 0xf) sum[i] = 0xf; - } - return (sum[0] << 4) | sum[1]; -} diff --git a/src/devices/apu.h b/src/devices/apu.h @@ -1,28 +0,0 @@ -/* -Copyright (c) 2021 Devine Lu Linvega -Copyright (c) 2021 Andrew Alderwick - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -typedef signed int Sint32; - -#define SAMPLE_FREQUENCY 44100 - -typedef struct { - Uint8 *addr; - Uint32 count, advance, period, age, a, d, s, r; - Uint16 i, len; - Sint8 volume[2]; - Uint8 pitch, repeat; -} Apu; - -int apu_render(Apu *c, Sint16 *sample, Sint16 *end); -void apu_start(Apu *c, Uint16 adsr, Uint8 pitch); -Uint8 apu_get_vu(Apu *c); -void apu_finished_handler(Apu *c); diff --git a/src/devices/audio.c b/src/devices/audio.c @@ -0,0 +1,99 @@ +#include "../uxn.h" +#include "audio.h" + +/* +Copyright (c) 2021 Devine Lu Linvega +Copyright (c) 2021 Andrew Alderwick + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE. +*/ + +#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) +#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) + +/* clang-format off */ + +static Uint32 advances[12] = { + 0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1, + 0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c +}; + +Audio audio[POLYPHONY]; + +/* clang-format on */ + +static Sint32 +envelope(Audio *c, Uint32 age) +{ + if(!c->r) return 0x0888; + if(age < c->a) return 0x0888 * age / c->a; + if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a); + if(age < c->s) return 0x0444; + if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s); + c->advance = 0; + return 0x0000; +} + +int +audio_render(Audio *c, Sint16 *sample, Sint16 *end) +{ + Sint32 s; + if(!c->advance || !c->period) return 0; + while(sample < end) { + c->count += c->advance; + c->i += c->count / c->period; + c->count %= c->period; + if(c->i >= c->len) { + if(!c->repeat) { + c->advance = 0; + break; + } + c->i %= c->len; + } + s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++); + *sample++ += s * c->volume[0] / 0x180; + *sample++ += s * c->volume[1] / 0x180; + } + if(!c->advance) audio_finished_handler(c); + return 1; +} + +void +audio_start(Audio *c, Uint16 adsr, Uint8 pitch) +{ + if(pitch < 108 && c->len) + c->advance = advances[pitch % 12] >> (8 - pitch / 12); + else { + c->advance = 0; + return; + } + c->a = ADSR_STEP * (adsr >> 12); + c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a; + c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d; + c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s; + c->age = 0; + c->i = 0; + if(c->len <= 0x100) /* single cycle mode */ + c->period = NOTE_PERIOD * 337 / 2 / c->len; + else /* sample repeat mode */ + c->period = NOTE_PERIOD; +} + +Uint8 +audio_get_vu(Audio *c) +{ + int i; + Sint32 sum[2] = {0, 0}; + if(!c->advance || !c->period) return 0; + for(i = 0; i < 2; ++i) { + if(!c->volume[i]) continue; + sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800; + if(sum[i] > 0xf) sum[i] = 0xf; + } + return (sum[0] << 4) | sum[1]; +} diff --git a/src/devices/audio.h b/src/devices/audio.h @@ -0,0 +1,31 @@ +/* +Copyright (c) 2021 Devine Lu Linvega +Copyright (c) 2021 Andrew Alderwick + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE. +*/ + +typedef signed int Sint32; + +#define SAMPLE_FREQUENCY 44100 +#define POLYPHONY 4 + +typedef struct { + Uint8 *addr; + Uint32 count, advance, period, age, a, d, s, r; + Uint16 i, len; + Sint8 volume[2]; + Uint8 pitch, repeat; +} Audio; + +extern Audio audio[POLYPHONY]; + +int audio_render(Audio *c, Sint16 *sample, Sint16 *end); +void audio_start(Audio *c, Uint16 adsr, Uint8 pitch); +Uint8 audio_get_vu(Audio *c); +void audio_finished_handler(Audio *c); +\ No newline at end of file diff --git a/src/devices/screen.c b/src/devices/screen.c @@ -45,8 +45,7 @@ screen_write(Screen *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color) { if(x < p->width && y < p->height) { Uint32 i = x + y * p->width; - Uint8 prev = layer->pixels[i]; - if(color != prev) { + if(color != layer->pixels[i]) { layer->pixels[i] = color; layer->changed = 1; } diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -9,7 +9,7 @@ #pragma clang diagnostic ignored "-Wtypedef-redefinition" #include <SDL.h> #include "devices/screen.h" -#include "devices/apu.h" +#include "devices/audio.h" #include "devices/file.h" #include "devices/controller.h" #include "devices/mouse.h" @@ -30,7 +30,6 @@ WITH REGARD TO THIS SOFTWARE. #define WIDTH 64 * 8 #define HEIGHT 40 * 8 #define PAD 4 -#define POLYPHONY 4 #define BENCH 0 static SDL_Window *gWindow; @@ -41,7 +40,6 @@ static SDL_Rect gRect; /* devices */ -static Apu apu[POLYPHONY]; static Device *devsystem, *devscreen, *devmouse, *devctrl, *devaudio0, *devconsole; static Uint8 zoom = 1; static Uint32 stdin_event, audio0_event; @@ -68,17 +66,17 @@ audio_callback(void *u, Uint8 *stream, int len) Sint16 *samples = (Sint16 *)stream; SDL_memset(stream, 0, len); for(i = 0; i < POLYPHONY; ++i) - running += apu_render(&apu[i], samples, samples + len / 2); + running += audio_render(&audio[i], samples, samples + len / 2); if(!running) SDL_PauseAudioDevice(audio_id, 1); (void)u; } void -apu_finished_handler(Apu *c) +audio_finished_handler(Audio *c) { SDL_Event event; - event.type = audio0_event + (c - apu); + event.type = audio0_event + (c - audio); SDL_PushEvent(&event); } @@ -212,10 +210,10 @@ console_deo(Device *d, Uint8 port) static Uint8 audio_dei(Device *d, Uint8 port) { - Apu *c = &apu[d - devaudio0]; + Audio *c = &audio[d - devaudio0]; if(!audio_id) return d->dat[port]; switch(port) { - case 0x4: return apu_get_vu(c); + case 0x4: return audio_get_vu(c); case 0x2: poke16(d->dat, 0x2, c->i); /* fall through */ default: return d->dat[port]; } @@ -224,7 +222,7 @@ audio_dei(Device *d, Uint8 port) static void audio_deo(Device *d, Uint8 port) { - Apu *c = &apu[d - devaudio0]; + Audio *c = &audio[d - devaudio0]; if(!audio_id) return; if(port == 0xf) { SDL_LockAudioDevice(audio_id); @@ -233,7 +231,7 @@ audio_deo(Device *d, Uint8 port) c->volume[0] = d->dat[0xe] >> 4; c->volume[1] = d->dat[0xe] & 0xf; c->repeat = !(d->dat[0xf] & 0x80); - apu_start(c, peek16(d->dat, 0x8), d->dat[0xf] & 0x7f); + audio_start(c, peek16(d->dat, 0x8), d->dat[0xf] & 0x7f); SDL_UnlockAudioDevice(audio_id); SDL_PauseAudioDevice(audio_id, 0); }