Last active
November 5, 2024 18:26
-
-
Save paniq/942b4aa2b89b2e312037d06ad44a4115 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printf = dlimport 'printf | |
printf-type = fntype auto s32 ptr | |
printf_ = vatype printf-type | |
printf_ptr = vatype printf-type ptr | |
printf_s32 = vatype printf-type s32 | |
printf_u32 = vatype printf-type u32 | |
printf_u64 = vatype printf-type u64 | |
printf_s32_s32 = vatype printf-type s32 s32 | |
printf_s32_s32_s32 = vatype printf-type s32 s32 s32 | |
printf_u64_s32 = vatype printf-type u64 s32 | |
printf_s32_u64 = vatype printf-type s32 u64 | |
printf_s32_u16_u8_u16 = vatype printf-type s32 u16 u8 u16 | |
export = proc symbol function-type source : | |
__replace = SYMINFO | |
FUNC function-type source 'return | |
symbol | |
int = s32 | |
void* = ptr | |
char* = ptr | |
float* = ptr | |
size_t = u64 | |
SDL_AudioDeviceID = u32 | |
#void * memset ( void * ptr, int value, size_t num ); | |
T_memset = fntype auto void* void* int size_t | |
memset = dlimport 'memset | |
#void *malloc( size_t size ); | |
T_malloc = fntype auto void* size_t | |
malloc = dlimport 'malloc | |
pi = 3.1415927 | |
tau = fmul pi 2.0 | |
smod = proc a b : | |
__replace = srem (iadd b (srem a b)) b | |
fmod = proc a b : | |
__replace = frem (fadd b (frem a b)) b | |
range = proc N : | |
i = (case (ine N 0:usize) true) ? loop 0:usize | |
i1 = iadd i 1:usize | |
i_last = case (ult i1 N) false | |
i_repeat = i_last ! repeat i i1 | |
i_last ? repeat i (UNDEF 4) | |
# sndfile.h | |
# | |
struct SF_INFO | |
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ | |
int samplerate ; | |
int channels ; | |
int format ; | |
int sections ; | |
int seekable ; | |
} ; | |
SF_INFO = 32:usize | |
SF_INFO.frames = 0:usize # 8 | |
SF_INFO.samplerate = 8:usize # 4 | |
SF_INFO.channels = 12:usize # 4 | |
SF_INFO.format = 16:usize # 4 | |
SF_INFO.sections = 20:usize # 4 | |
SF_INFO.seekable = 24:usize # 4 | |
SNDFILE* = ptr | |
SF_INFO* = ptr | |
sf_count_t = s64 | |
SFM_WRITE = 0x20 | |
SF_FORMAT_WAV = 0x010000 | |
SF_FORMAT_PCM_16 = 0x0002 | |
SF_FORMAT_FLOAT = 0x0006 | |
#SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; | |
T_sf_open = fntype auto SNDFILE* char* int SF_INFO* | |
sf_open = dlimport 'sf_open | |
#int sf_close (SNDFILE *sndfile) ; | |
T_sf_close = fntype auto int SNDFILE* | |
sf_close = dlimport 'sf_close | |
#sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; | |
T_sf_write_float = fntype auto sf_count_t SNDFILE* float* sf_count_t | |
sf_write_float = dlimport 'sf_write_float | |
#void sf_write_sync (SNDFILE *sndfile) ; | |
T_sf_write_sync = fntype auto void SNDFILE* | |
sf_write_sync = dlimport 'sf_write_sync | |
#const char* sf_strerror (SNDFILE *sndfile) ; | |
T_sf_strerror = fntype auto char* SNDFILE* | |
sf_strerror = dlimport 'sf_strerror | |
hash = proc x : | |
x = ixor x (ushr x 16) | |
x = imul x 0x7feb352d:u32 | |
x = ixor x (ushr x 15) | |
x = imul x 0x846ca68b:u32 | |
x = ixor x (ushr x 16) | |
__replace = x | |
echo = proc s D : | |
N = imul D 2:usize | |
SZ = imul N 8:usize | |
buf = alloc SZ | |
pcall T_memset memset buf 0 SZ | |
ppos = alloc 8:usize | |
store ppos 0:usize | |
pos = s.l s.r ? load 8 ppos | |
sofs = imul pos 8:usize | |
dofs = imul (urem (iadd pos D) N) 8:usize | |
ldofs = iadd buf dofs | |
rdofs = iadd ldofs 4:usize | |
lsofs = iadd buf sofs | |
rsofs = iadd lsofs 4:usize | |
l = fmul (load 4 lsofs) 0.9 | |
r = fmul (load 4 rsofs) 0.9 | |
dl = fadd s.l l | |
dr = fadd s.r r | |
store ldofs dl | |
store rdofs dr | |
store ppos (urem (iadd pos 1:usize) N) | |
dspmain = proc t : | |
* = fmul | |
- = fsub | |
+ = fadd | |
% = fmod | |
/ = fdiv | |
ntoc = proc x : # 0..1 -> -1..1 | |
__replace = - (* 2.0 x) 1.0 | |
cton = proc x : # -1..1 -> 0..1 | |
__replace = / (+ x 1.0) 2.0 | |
sinosc = proc phase : # -1..1 | |
__replace = sin (* phase tau) | |
saw = proc phase : # 0..1 | |
__replace = % phase 1.0 | |
sawosc = proc phase : # -1..1 | |
__replace = - (* (% phase 1.0) 2.0) 1.0 | |
octave = proc x : | |
__replace = exp2 x | |
bpm = 120.0 | |
beat = / (* t bpm) 60.0 | |
beat = * 4.0 beat | |
voice = proc idx : | |
A-4 = 440.0 | |
bar = ftou 4 beat | |
fidx = utof 4 idx | |
#beatofs = * fidx (/ 1.0 16.0) | |
beatofs = * fidx 0.01 | |
beat = + beat beatofs | |
flip = ntoc (utof 4 (iand idx 1)) | |
freq = fidx | |
freq = + freq 1.0 | |
bit = ishl 1 idx | |
#on = case (ieq (iand (hash bar) bit) bit) true | |
on = case (ieq (iand bar bit) bit) true | |
nidx = / fidx 7.0 | |
pan = ntoc nidx | |
pan = * pan flip | |
pan = * pan nidx | |
lpan = cton pan | |
rpan = cton (- 0.0 pan) | |
vib = + (* (sinosc (* t (+ 7.0 beatofs))) 0.5) 0.5 | |
vib = exp2 (* vib 0.001) | |
hz = * (+ t vib) | |
* A-4 | |
freq | |
s = 0.0 | |
s = + s | |
sawosc | |
* hz | |
octave -2.0 | |
s = + s | |
sinosc | |
* hz | |
octave -1.0 | |
s = * (/ 1.0 16.0) | |
* s | |
- 1.0 | |
saw beat | |
s1 = on ? pass s | |
s2 = on ! pass 0.0 | |
s = or s1 s2 | |
l = * s lpan | |
r = * s rpan | |
silent = proc : | |
l = 0.0 | |
r = 0.0 | |
mix = proc a b : | |
l = + a.l b.l | |
r = + a.r b.r | |
vmix = proc a b v : | |
l = + a.l (* b.l v) | |
r = + a.r (* b.r v) | |
s = (silent) | |
s = mix | |
mix | |
mix | |
mix s (voice 0) | |
mix s (voice 1) | |
mix | |
mix s (voice 2) | |
mix s (voice 3) | |
mix | |
mix | |
mix s (voice 4) | |
mix s (voice 5) | |
mix | |
mix s (voice 6) | |
mix s (voice 7) | |
s = vmix s (echo s 400:usize) 0.5 | |
s = vmix s (echo s 6400:usize) 0.5 | |
#old_s = s | |
#s = echo s | |
l = s.l | |
r = s.r | |
export 'main | |
fntype auto s32 s32 ptr | |
proc argc argv : | |
info = pcall T_malloc malloc SF_INFO | |
_ = pcall T_memset memset info 0 SF_INFO | |
info = _ ? pass info | |
_ = any | |
store (iadd info SF_INFO.channels) 2 | |
store (iadd info SF_INFO.samplerate) 44100 | |
store (iadd info SF_INFO.format) | |
ior SF_FORMAT_WAV SF_FORMAT_FLOAT | |
info = _ ? pass info | |
handle = pcall T_sf_open sf_open "test.wav" SFM_WRITE info | |
handle = (case handle 0:u64) ! pass handle | |
handle ! pcall printf_ptr printf "sf_open() failed: %s\n" | |
pcall T_sf_strerror sf_strerror null | |
_ = pcall printf_ptr printf "writing to handle %p\n" handle | |
# fill buffer | |
#SAMPLESIZE = 100:usize | |
SAMPLESIZE = (imul 44100:usize 64:usize) | |
NUM_SAMPLES = imul SAMPLESIZE 2:usize | |
SIZEOF_SAMPLES = imul NUM_SAMPLES 4:usize | |
samples = pcall T_malloc malloc SIZEOF_SAMPLES | |
r = range SAMPLESIZE | |
i = _ ? r.i | |
t = fdiv (utof 4 i) 44100.0 | |
m = dspmain t | |
ofs = imul i 8:usize | |
_ = any | |
store (iadd samples ofs) m.l | |
store (iadd samples (iadd ofs 4:usize)) m.r | |
#_ = _ ? pcall printf_u64 printf "i = %llu\n" i | |
samples = r.i_last ? pass samples | |
_ = _ r.i_last ? pcall printf_ printf "buffer filled.\n" | |
_ = _ ? pcall T_sf_write_float sf_write_float handle samples NUM_SAMPLES | |
res = _ | |
_ = _ ? pcall printf_u64 printf "wrote %llu items\n" res | |
_ = _ ? pcall T_sf_close sf_close handle | |
_ = _ ? pcall printf_ printf "handle closed.\n" | |
return = pass 0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment