Additive Synth Upgrade Jacob Joaquin March 17, 2010 jacobjoaquin@gmail.com csound.noisepages.com sr = 44100 kr = 4410 ksmps = 10 nchnls = 2 0dbfs = 1.0 ; Instruments # define GEN_Multiply # 1 # # define GEN_Saw # 2 # # define GEN_Square # 3 # # define GEN_Triangle # 4 # # define Synth # 5 # ; F-Tables # define T_Sine # 1 # ; Sine wave # define T_Tri # 2 # ; Triangle wave ; F-tables gitemp ftgen $T_Sine, 0, 2 ^ 16, 10, 1 gitemp ftgen $T_Tri, 0, 2 ^ 16, -7, -1, 2 ^ 15, 1, 2 ^ 15, -1 opcode GEN_Multiply, 0, iii ; Multiplies two tables together, interpolating the sizes of the ; two tables differ. The size of the new table will be the size ; of the largest of the two source tables. ifn, \ ; Table to create/overwrite itable_1, \ ; Source table 1 itable_2, \ ; Source table 2 xin ; get size of largest table if (ftlen(itable_1) >= ftlen(itable_2)) then isize = ftlen(itable_1) else isize = ftlen(itable_2) endif ; create or re-create table 3 itemp ftgen ifn, 0, isize, 10, 0 ; generate data for table 3 i_index = 0 loop_start: ; Needs work. Will probably need to write a custom table reader ; that doesn't interpolate between the last and first value. ivalue_1 tablei i_index / isize, itable_1, 1, 0, 0 ivalue_2 tablei i_index / isize, itable_2, 1, 0, 0 ; Non-interpolation ; ivalue_1 tab_i i_index / isize, itable_1, 1 ; ivalue_2 tab_i i_index / isize, itable_2, 1 ivalue = ivalue_1 * ivalue_2 tabw_i ivalue, i_index, ifn ; Print data ; prints "%d:\t%f\t%f\t%f\n", i_index, ivalue_1, ivalue_2, ivalue loop_lt i_index, 1, isize, loop_start endop opcode GEN_Saw, 0, ii ; Generates data for a band-limited saw wave in Add_Synth format: ; frequency ratio, amplitude, phase ifn, \ ; Table number in_harmonics \ ; Number of harmonics xin isize = abs(in_harmonics * 3) * -1 itemp ftgen ifn, 0, isize, 10, 0 i_index = 0 loop_start: ifreq = i_index + 1 iamp = 1 / ifreq iphase = 0 tabw_i ifreq, i_index * 3, ifn tabw_i iamp, i_index * 3 + 1, ifn tabw_i iphase, i_index * 3 + 2, ifn prints "GEN_Saw %d: %f %f %f\n", i_index, ifreq, iamp, iphase loop_lt i_index, 1, in_harmonics, loop_start endop opcode GEN_Square, 0, ii ; Generates data for a band-limited square wave in Add_Synth format: ; frequency ratio, amplitude, phase ifn, \ ; Table number imax_harmonic \ ; Highest Harmonic xin in_harmonics = int((imax_harmonic + 1) / 2) isize = abs(in_harmonics * 3) * -1 itemp ftgen ifn, 0, isize, 10, 0 i_index = 0 loop_start: ifreq = i_index * 2 + 1 iamp = 1 / ifreq iphase = 0 tabw_i ifreq, i_index * 3, ifn tabw_i iamp, i_index * 3 + 1, ifn tabw_i iphase, i_index * 3 + 2, ifn prints "GEN_Square %d: %f %f %f\n", i_index, ifreq, iamp, iphase loop_lt i_index, 1, in_harmonics, loop_start endop opcode GEN_Triangle, 0, ii ; Generates data for a band-limited triangle wave in Add_Synth format: ; frequency ratio, amplitude, phase ifn, \ ; Table number imax_harmonic \ ; Highest Harmonic xin in_harmonics = int((imax_harmonic + 1) / 2) isize = abs(in_harmonics * 3) * -1 itemp ftgen ifn, 0, isize, 10, 0 i_index = 0 loop_start: ifreq = i_index * 2 + 1 iamp = 1 / ((i_index * 2 + 1) ^ 2) * (-1 ^ i_index) iphase = 0 tabw_i ifreq, i_index * 3, ifn tabw_i iamp, i_index * 3 + 1, ifn tabw_i iphase, i_index * 3 + 2, ifn prints "GEN_Triangle %d: %f %f %f\n", i_index, ifreq, iamp, iphase loop_lt i_index, 1, in_harmonics, loop_start endop opcode Get_Note_Data, iii, ii ; Returns Add_Synth data ifn, \ ; Table number i_index, \ ; Index of data xin isize = ftlen(ifn) / 3 iratio tab_i i_index * 3, ifn iamp tab_i i_index * 3 + 1, ifn iphase tab_i i_index * 3 + 2, ifn ; Returns frequency ratio, amplitude and phase xout iratio, iamp, iphase endop opcode Add_Synth, a, kkiiii kfreq, \ ; Frequency kfreq_mod, \ ; Frequency modulation itone_table, \ ; Harmonic table ibody_table, \ ; Additive body amplitude table ipch_table, \ ; Additive body tuning table i_index \ ; Index of current harmonic xin ; Get frequency ratio, amplitude, phase iratio, iamp, iphase Get_Note_Data itone_table, i_index prints "%d: %f %f\n", i_index, iratio, iamp ; Calculate this frequency kthis_freq = kfreq * iratio ; Apply tuning transfer function (experimental) ; kcurve logcurve kthis_freq / 22050, 0.5 ; kpch tablei kcurve, ipch_table, 1, 0, 0 ; kthis_freq = kthis_freq * kpch ; kcurve = 1 / ((22050 - kthis_freq) ^ 2) ; kpch tablei kcurve, ipch_table, 1, 0, 0 ; kthis_freq = kthis_freq * kpch kcurve = 1 / ((1 - (kthis_freq / 22050)) ^ 2) kpch tablei kcurve, ipch_table, 1, 0, 0 kthis_freq = kthis_freq * kpch ; Frequency modulation kthis_freq = kthis_freq + kthis_freq * kfreq_mod ; Amplitude transfer function kamp tablei kthis_freq / 22050, ibody_table, 1, 0, 0 ; Generate this voice a1 oscil kamp * iamp, kthis_freq, $T_Sine, iphase ; Recursive oscillator a2 init 0 if (i_index < (ftlen(itone_table) / 3) - 1 && i(kthis_freq) < 16000) then a2 Add_Synth kfreq, kfreq_mod, itone_table, ibody_table, ipch_table, \ i_index + 1 endif xout a1 + a2 endop instr $GEN_Multiply ; Wrapper for UDO of the same name ifn = p4 ; Function number of table to create itable_1 = p5 ; Source table 1 itable_2 = p6 ; Source table 2 GEN_Multiply ifn, itable_1, itable_2 turnoff endin instr $GEN_Saw ; Wrapper for UDO of the same name ifn = p4 ; Function number of table to create in_harmonics = p5 ; Number of harmonics GEN_Saw ifn, in_harmonics turnoff endin instr $GEN_Square ; Wrapper for UDO of the same name ifn = p4 ; Function number of table to create in_harmonics = p5 ; Number of harmonics GEN_Square ifn, in_harmonics turnoff endin instr $GEN_Triangle ; Wrapper for UDO of the same name ifn = p4 ; Function number of table to create in_harmonics = p5 ; Number of harmonics GEN_Triangle ifn, in_harmonics turnoff endin instr $Synth idur = p3 ; Duration iamp = p4 ; Amplitude ipch = cpspch(p5) ; Pitch in octave point pitch-class ibody = p6 ; Additive body amplitude table ipch_table = p7 ; Additive body tuning table ipan = p8 ; Pan position irap_table = p9 ; Ratio amplitude phase table ; Pitch vibrato k2 linsegr 0, 0.4, 0, 0.7, 1, 1, 1, 1, 0.3, 0.01, 1 klfo oscil k2, 4.8 + rnd(0.4), $T_Tri krand randh rnd(0.9) + 0.1, 0.125 + rnd(0.25) kvibrato = (klfo + krand) * (0.003 + rnd(0.007)) * 0.3 ; Pitch kpch expseg 2 ^ (-1 / 12), 0.05 + rnd(0.05), 2 ^ (0 / 12), 0.001, \ 2 ^ (0 / 12) ; Generate audio a1 Add_Synth ipch, kvibrato + kpch, irap_table, ibody, ipch_table, 0 ; Amp aenv linsegr 0, 0.1 + rnd(0.105), 0.2 + rnd(0.3), 0.1, 0.5, 2, 0.333, \ 0.2 + rnd(0.1), 0 asig = a1 * aenv * iamp * (0.9 + rnd(0.1)) outs asig * sqrt(1 - ipan), asig * sqrt(ipan) endin ; Instruments # define GEN_Multiply # 1 # # define GEN_Saw # 2 # # define GEN_Square # 3 # # define GEN_Triangle # 4 # # define Synth # 5 # t 0 28 ; Transfer functions ;f 100 0 16 -2 1 1 0 0 1 0 1 0 1 1 1 0 0 0 1 1 ;f 101 0 [2 ^ 11] 21 3 1 ;f 102 0 [2 ^ 11] 21 3 1 ;f 103 0 2 -2 1 1 ;f 200 0 16 -2 1 0.5 1 1 1 1 1 1 1 1 1.5 1 1 1 2 1 ;f 201 0 256 -7 1.059 256 1 ;f 202 0 16 -2 1 1 1.059 1 0.998 1 1 1 1.2 1 1 1 1 1 1 1 f 203 0 16 -2 1 0.999 1.059 1 0.998 1.059 1 0.98 1.2 1 1 1.1 0.98 1 1 1 f 204 0 16 -2 1 0.999 1.001 1 0.998 1.001 1 0.98 1.001 1 1 1 1 1 1 1 f 300 0 128 -2 0 1 0.333 1 0.333 1 0.333 1 0.333 1 0.333 1 0.333 1 0.333 1 \ 0.333 1 0.333 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f 301 0 [2 ^ 12] 21 3 1 f 302 0 8 -2 0.5 1 0.3 1 -0.3 1 0.3 -1 f 303 0 [2 ^ 8] 21 3 1 i $GEN_Multiply 0 1 401 300 301 i $GEN_Multiply 0 1 400 302 303 i $GEN_Saw 0 1 500 32 i $GEN_Square 0 1 501 32 i $GEN_Triangle 0 1 502 128 i $Synth 0 0.125 2 5.00 401 203 0.25 500 i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + . . 5.00 . . . . i $Synth + . . 5.03 . . . . i $Synth + . . 5.07 . . . . i $Synth + . . 5.09 . . . . i $Synth + . . 6.00 . . . . i $Synth + 2 . 5.00 . . . . i $Synth 0.625 1 1.4 8.00 400 204 0.75 501 i $Synth + . . 7.09 . . . . i $Synth + . . 7.07 . . . . i $Synth + . . 7.05 . . . . i $Synth + . . 7.03 . . . . i $Synth + . . 7.02 . . . . i $Synth + . . 7.04 . . . .