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.

Revisions

  1. paniq revised this gist Nov 5, 2024. 1 changed file with 58 additions and 15 deletions.
    73 changes: 58 additions & 15 deletions audio.ni
    Original file line number Diff line number Diff line change
    @@ -42,6 +42,7 @@ range = proc N :
    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

    @@ -85,6 +86,36 @@ sf_write_sync = dlimport 'sf_write_sync
    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
    @@ -110,16 +141,19 @@ dspmain = proc t :
    beat = / (* t bpm) 60.0
    beat = * 4.0 beat

    voice = proc idx beatofs :
    voice = proc idx :
    A-4 = 440.0

    beat = + beat beatofs
    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
    @@ -136,13 +170,15 @@ dspmain = proc t :
    * A-4
    freq
    s = sawosc
    * hz
    octave -3.0
    s = 0.0
    s = + s
    sawosc
    * hz
    octave -2.0
    s = + s
    sinosc
    * hz
    octave 0.0
    octave -1.0
    s = * (/ 1.0 16.0)
    * s
    - 1.0
    @@ -162,23 +198,30 @@ dspmain = proc t :
    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 0.0)
    mix s (voice 1 0.01)
    mix s (voice 0)
    mix s (voice 1)
    mix
    mix s (voice 2 0.02)
    mix s (voice 3 0.03)
    mix s (voice 2)
    mix s (voice 3)
    mix
    mix
    mix s (voice 4 0.04)
    mix s (voice 5 0.05)
    mix s (voice 4)
    mix s (voice 5)
    mix
    mix s (voice 6 0.06)
    mix s (voice 7 0.07)
    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
    @@ -202,7 +245,7 @@ export 'main
    _ = pcall printf_ptr printf "writing to handle %p\n" handle
    # fill buffer
    #SAMPLESIZE = (imul 44100:usize 16:usize)
    #SAMPLESIZE = 100:usize
    SAMPLESIZE = (imul 44100:usize 64:usize)
    NUM_SAMPLES = imul SAMPLESIZE 2:usize
    SIZEOF_SAMPLES = imul NUM_SAMPLES 4:usize
  2. paniq created this gist Nov 5, 2024.
    228 changes: 228 additions & 0 deletions audio.ni
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,228 @@
    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