Skip to content

Instantly share code, notes, and snippets.

@paniq
Last active November 5, 2024 18:26
Show Gist options
  • Select an option

  • Save paniq/942b4aa2b89b2e312037d06ad44a4115 to your computer and use it in GitHub Desktop.

Select an option

Save paniq/942b4aa2b89b2e312037d06ad44a4115 to your computer and use it in GitHub Desktop.
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
# 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
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 beatofs :
A-4 = 440.0
beat = + beat beatofs
bar = ftou 4 beat
fidx = utof 4 idx
flip = ntoc (utof 4 (iand idx 1))
freq = fidx
freq = + freq 1.0
bit = ishl 1 idx
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 = sawosc
* hz
octave -3.0
s = + s
sinosc
* hz
octave 0.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
s = (silent)
s = mix
mix
mix
mix s (voice 0 0.0)
mix s (voice 1 0.01)
mix
mix s (voice 2 0.02)
mix s (voice 3 0.03)
mix
mix
mix s (voice 4 0.04)
mix s (voice 5 0.05)
mix
mix s (voice 6 0.06)
mix s (voice 7 0.07)
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 = (imul 44100:usize 16: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