diff options
Diffstat (limited to 'site/udo/sequencing_melodic_portamento.udo')
-rwxr-xr-x | site/udo/sequencing_melodic_portamento.udo | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/site/udo/sequencing_melodic_portamento.udo b/site/udo/sequencing_melodic_portamento.udo new file mode 100755 index 0000000..fe3bde2 --- /dev/null +++ b/site/udo/sequencing_melodic_portamento.udo @@ -0,0 +1,310 @@ +#ifndef UDO_MELSEQUENCINGPORT
+#define UDO_MELSEQUENCINGPORT ##
+
+/*
+ Extension to sequencing_melodic.udo which permits usage of k-rate frequency arrays
+
+ This file is part of the SONICS UDO collection by Richard Knight 2021
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+
+#include "__config__.udo" ; using fftsize for tuning
+#include "sequencing_melodic.udo"
+#include "wavetables.udo"
+#include "frequency_tools.udo"
+
+
+gimel_freqs ftgen 0, 0, -12, -7, 0 ; current notes: index 0 is the length
+gimel_amps ftgen 0, 0, -12, -7, 0 ; current notes: index 0 is the length
+
+gimel_portamento_beatratio init 0.5 ; portamento time as ratio of current beat time
+gimel_linetype init 0 ; 0=pre-section, 1=post-section
+
+
+/*
+ Automate a frequency/amp line
+*/
+instr _mel_linedraw
+ index = p4
+ ifreq = p5
+ iamp = p6
+
+ icurrentfreq table index, gimel_freqs
+
+ if (icurrentfreq == 0 && ifreq != 0) then
+ tablew ifreq, index, gimel_freqs
+ elseif (ifreq != 0 && icurrentfreq != ifreq) then
+ tablew line:k(icurrentfreq, p3, ifreq), index, gimel_freqs
+ endif
+
+ icurrentamp table index, gimel_amps
+ if (icurrentamp != iamp) then
+ tablew line:k(icurrentamp, p3, iamp), index, gimel_amps
+ endif
+endin
+
+
+instr _mel_linestep_inner
+ if (timeinstk() == 1) then
+ turnoff2 "_mel_linedraw", 0, 0
+ endif
+
+ if (table:i(1, gimel_next_notes) != 0) then
+ index = 0
+ while (index < table:i(0, gimel_next_notes)) do
+ event_i "i", "_mel_linedraw", 1/kr, p3, index, cpsmidinn(table:i(index + 1, gimel_next_notes)), 1
+ index += 1
+ od
+ while (index < ftlen(gimel_freqs)) do
+ event_i "i", "_mel_linedraw", 1/kr, p3, index, 0, 0
+ index += 1
+ od
+ endif
+endin
+
+
+instr _mel_linestep
+ icurrentduration mel_length
+ ilinetime = (i(gkseq_beattime) * gimel_portamento_beatratio)
+ if (gimel_linetype == 0) then
+ inextline = icurrentduration - ilinetime
+ else
+ inextline = icurrentduration
+ endif
+ event_i "i", "_mel_linestep_inner", inextline, ilinetime
+ turnoff
+endin
+
+
+/*
+ Portamento manager: respond to gkmel_section_change trigger by calling _mel_linestep instrument
+*/
+instr _mel_linemanager
+ ; set initial freqs
+ index = 0
+ while (index < table:i(0, gimel_current_notes)) do
+ tablew cpsmidinn(table:i(index + 1, gimel_current_notes)), index, gimel_freqs
+ tablew 1, index, gimel_amps
+ index += 1
+ od
+ while (index < ftlen(gimel_freqs)) do
+ tablew 0, index, gimel_amps
+ index += 1
+ od
+
+ schedkwhen gkmel_section_change, 0, 1, "_mel_linestep", 0, 1
+endin
+
+schedule "_mel_linemanager", 0.1, 36000 ; notes not ready on 0
+;alwayson "_mel_linemanager"
+
+
+
+
+
+/*
+ Recursively create a chord to be used by mel_tune_portamento; internal use only
+
+ aout _mel_tune_chord_portamento kfreqmult, ifn, imaxmult, imult, index
+
+ aout chord output
+ kfreqmult frequency multiplier to apply to tuning
+ ifn wavetable to use
+ imaxmult multiples of harmonics to generate in tuning
+ imult internal multiplier for recursion
+ index internal index for recursion
+
+*/
+opcode _mel_tune_chord_portamento, a, kiipo
+ kfreqmult, ifn, imaxmult, imult, index xin
+
+
+ if (index + 1 > ftlen(gimel_amps)) then
+ index = 0
+ imult += 1
+ endif
+
+ aout = oscil(table:k(index, gimel_amps), kfreqmult * table:k(index, gimel_freqs) * pow:k(2, imult), ifn) * 0.1
+ ; recursion for all chord parts
+ if (imult <= imaxmult) then
+ aout += _mel_tune_chord_portamento(kfreqmult, ifn, imaxmult, imult, index + 1)
+ endif
+
+ xout aout
+endop
+
+
+
+/*
+ PVS morph tuning to current melodic sequencer notes
+ aoutL, aoutR mel_tune_portamento ainL, ainR, [ifn=gifnSine, imult=4, ifftrate=giFFTsize, ifftdiv=giFFTwinFactor, kfreqmult=1]
+
+ aoutL, aoutR output audio
+ ainL, ainR input audio
+ ifn wavetable to use
+ imaxmult multiples of harmonics to generate in tuning (defaults to 4)
+ ifftrate fft size, defaults to config default
+ ifftdiv fft window division factor (eg 4, 8, 16), defaults to config default
+ kfreqmult frequency multiplier to apply to tuning
+*/
+opcode mel_tune_portamento, aa, aaooooP
+ aL, aR, ifn, imaxmult, ifftrate, ifftdiv, kfreqmult xin
+ ifn = (ifn == 0) ? gifnSine : ifn
+ imaxmult = (imaxmult == 0) ? 4 : imaxmult
+ ifftrate = (ifftrate == 0) ? giFFTsize : ifftrate
+ ifftdiv = (ifftdiv == 0) ? giFFTwinFactor : ifftdiv
+ fmods pvsanal _mel_tune_chord_portamento(kfreqmult, ifn, imaxmult), ifftrate, ifftrate/ifftdiv, ifftrate, 1
+ fL1 pvsanal aL, ifftrate, ifftrate/ifftdiv, ifftrate, 1
+ fR1 pvsanal aR, ifftrate, ifftrate/ifftdiv, ifftrate, 1
+ fL2 pvsmorph fL1, fmods, 0, 1
+ fR2 pvsmorph fR1, fmods, 0, 1
+ aL1 pvsynth fL2
+ aR1 pvsynth fR2
+ idel = (ifftrate)/sr
+ aL1 balance aL1, delay(aL, idel)
+ aR1 balance aR1, delay(aR, idel)
+ xout aL1, aR1
+endop
+
+
+/*
+ Bandpass tuning for internal use only, applied to each note frequency for full spectrum bandpass
+
+ aoutL, aoutR _mel_bandpass_portamento_freqgroup ainL, ainR, kfreq, kbw, iprecise, imult
+
+ aoutL, aoutR output audio
+ ainL, ainR input audio
+ kfreq frequency to tune to
+ kbw bandwidth of bandpass filters
+ iprecise if 1, use two serial bandpass filters for more precision
+ imult current multiplier for recursion
+*/
+opcode _mel_bandpass_portamento_freqgroup, aa, aakkip
+ ainL, ainR, kfreq, kbw, iprecise, imult xin
+ imaxmult = 24
+
+ aoutL butterbp ainL, kfreq*imult, kbw
+ aoutR butterbp ainR, kfreq*imult, kbw
+
+ if (iprecise == 1) then
+ aoutL butterbp aoutL, kfreq*imult, kbw
+ aoutR butterbp aoutR, kfreq*imult, kbw
+ endif
+
+ if (imult <= imaxmult) then
+ aoutLrec, aoutRrec _mel_bandpass_portamento_freqgroup ainL, ainR, kfreq, kbw, iprecise, imult * 2
+ aoutL += aoutLrec
+ aoutR += aoutRrec
+ endif
+ xout aoutL, aoutR
+endop
+
+
+/*
+ Bandpass tuning to current melodic sequencer notes
+
+ aoutL, aoutR mel_bandpass_portamento ainL, ainR [, kbw=1, iprecise=0, index=0]
+
+ aoutL, aoutR output audio
+ ainL, ainR input audio
+ kbw bandwidth of bandpass filters
+ iprecise if 1, use two serial bandpass filters for more precision
+ index recursion index for internal use
+*/
+opcode mel_bandpass_portamento, aa, aaPoo
+ ainL, ainR, kbw, iprecise, index xin
+ kamp = table:k(index, gimel_amps)
+
+ if (kamp > 0) then
+ kfreq = table:k(index, gimel_freqs)
+ aoutL, aoutR _mel_bandpass_portamento_freqgroup ainL, ainR, kfreq, kbw, iprecise
+ aoutL *= kamp
+ aoutR *= kamp
+ else
+ aoutL = 0
+ aoutR = 0
+ endif
+
+ if (index < ftlen(gimel_amps)) then
+ aoutLr, aoutRr mel_bandpass_portamento ainL, ainR, kbw, iprecise, index + 1
+ aoutL += aoutLr
+ aoutR += aoutRr
+ endif
+ xout aoutL, aoutR
+endop
+
+
+
+/*
+ Ringmod tuning to current melodic sequencer notes
+ aoutL, aoutR mel_ringmod_portamento ainL, ainR kfreqmult, index
+
+ aoutL, aoutR output audio
+ ainL, ainR input audio
+ kfreqmult frequency multiplier to apply to current frequencies
+ index recursion index for internal use
+*/
+opcode mel_ringmod_portamento, aa, aaPo
+ ainL, ainR, kfreqmult, index xin
+
+ kamp = table:k(index, gimel_amps)
+
+ if (kamp > 0) then
+ aoutL, aoutR ringmod1 ainL, ainR, table:k(index, gimel_freqs) * kfreqmult
+ aoutL *= kamp
+ aoutR *= kamp
+ else
+ aoutL = 0
+ aoutR = 0
+ endif
+
+ if (index < ftlen(gimel_amps)) then
+ aoutLr, aoutRr mel_ringmod_portamento ainL, ainR, kfreqmult, index + 1
+ aoutL += aoutLr
+ aoutR += aoutRr
+ endif
+ xout aoutL, aoutR
+endop
+
+
+
+/*
+ Reson tuning to current melodic sequencer notes
+
+ aoutL, aoutR mel_reson_portamento ainL, ainR kfreqmult, index
+
+ aoutL, aoutR output audio
+ ainL, ainR input audio
+ kfreqmult frequency multiplier to apply to current frequencies
+ index recursion index for internal use
+*/
+opcode mel_reson_portamento, aa, aaPo
+ ainL, ainR, kfreqmult, index xin
+
+ kamp = table:k(index, gimel_amps)
+ kfreq = table:k(index, gimel_freqs)
+
+ if (kamp > 0) then
+ aoutL resony ainL, kfreq * kfreqmult, 2, 8, 10
+ aoutR resony ainR, kfreq * kfreqmult, 2, 8, 10
+ aoutL balance aoutL, ainL
+ aoutR balance aoutR, ainR
+ aoutL *= kamp
+ aoutR *= kamp
+ else
+ aoutL = 0
+ aoutR = 0
+ endif
+
+ if (index < ftlen(gimel_amps)) then
+ aoutLr, aoutRr mel_reson_portamento ainL, ainR, kfreqmult, index + 1
+ aoutL += aoutLr
+ aoutR += aoutRr
+ endif
+ xout aoutL, aoutR
+endop
+
+
+#end
+
|