1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#ifndef UDO_FNMI_PORTCHORD
#define UDO_FNMI_PORTCHORD ##
/*
Portamento recursive chord players
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"
#include "sequencing_melodic_persistence.udo"
#include "sequencing_melodic_portamento.udo"
#include "wavetables.udo"
#include "sounddb.udo"
/*
Play continuous chords from melodic sequencer with portamento, using oscil as an instrument and a specified wavetable
aL, aR portchord_wave [iwavefn=gifnSine, ifreqmult=1, ivibdepth=1, ivibrate=3, index=0]
aL, aR stereo outputs
iwavefn the f-table to use with oscil
ifreqmult frequency multiplier of the chord note frequencies to be applied
ivibdepth vibrato depth
ivibrate vibrato rate in Hz
index internal start index of the chord notes; could also be used to specify starting note offset
*/
opcode portchord_wave, aa, jpjjo
iwavefn, ifreqmult, ivibdepth, ivibrate, index xin
iwavefn = (iwavefn == -1) ? gifnSine : iwavefn
ivibdepth = (ivibdepth == -1) ? 1 : ivibdepth
ivibrate = (ivibrate == -1) ? 3 : ivibrate
kamp table index, gimel_amps
kfreq table index, gimel_freqs
klfo = oscil:k(ivibdepth, ivibrate) ;oscil:k(7, 5)
kfreq += klfo
kfreq *= ifreqmult
;kamp portk kamp, (i(gkseq_beattime) * gimel_portamento_beatratio) ; fade out when change
aL oscil kamp*0.1, kfreq, iwavefn
ipan = random(0, 1)
aR = aL * ipan
aL *= (1 - ipan)
if (index + 1 < ftlen(gimel_amps)) then
aLx, aRx portchord_wave iwavefn, ifreqmult, ivibdepth, ivibrate, index + 1
aL += aLx
aR += aRx
endif
xout aL, aR
endop
/*
Play continuous chords from melodic sequencer with portamento, using a sounddb collection as source sounds
aL, aR portchord_sound icollectionid [, imode=1, kfreqmult=1, ifftsize=giFFTsize, index=0]
aL, aR stereo outputs
icollectionid collection ID from sounddb to use for the playback
imode 0 = read with sndwarp; 1 = read with mincer
kfreqmult frequency multiplier of the chord note frequencies to be applied
ifftsize FFT size to use when imode = 1 ; default to global setting in __config__.udo
index internal start index of the chord notes; could also be used to specify starting note offset
*/
opcode portchord_sound, aa, ipPjo
icollectionid, imode, kfreqmult, ifftsize, index xin
ifftsize = (ifftsize == -1) ? giFFTsize : ifftsize
inote = round(random(50, 80))
ibasefreq = cpsmidinn(inote)
ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, inote
ifn = gisounddb[ifileid][0]
ichannels = gisounddb[ifileid][1]
idur = gisounddb[ifileid][2]
irmsnorm = gisounddb[ifileid][3]
kampb table index, gimel_amps
kfreq table index, gimel_freqs
kamp portk kampb, (i(gkseq_beattime) * gimel_portamento_beatratio) ; fade out when change
kpitch = (kfreq / ibasefreq) * ipitchratio * kfreqmult ; actual pitch adjustment
istart = random(0.05, 0.2)
iend = random(istart+0.1, 0.8)
atime = (abs(oscil(iend - istart, random(0.001, 0.1), gifnSine, random(0, 1))) + istart) * idur
klfo = oscil:k(random(0.0001, 0.009), random(1, 5)) + 1
kpitch *= klfo
if (kamp != 0) then
if (imode == 0) then
kpitch *= (ftsr(ifn) / sr) ; adjustment for sndwarp required
;apitch interp kpitch
aL, aR sndwarpst kamp, atime, kpitch, ifn, istart, 4410, 441, 8, gifnHalfSine, 1
else
if (ichannels == 2) then
aL, aR mincer atime, kamp, kpitch, ifn, 0, ifftsize
else
aL mincer atime, kamp, kpitch, ifn, 0, ifftsize
aR = aL
endif
endif
endif
aL *= (1 - irmsnorm) * 0.5
aR *= (1 - irmsnorm) * 0.5
; recursion for all chord parts
if (index + 1 < ftlen(gimel_amps)) then
aLx, aRx portchord_sound icollectionid, imode, kfreqmult, ifftsize, index + 1
aL += aLx
aR += aRx
endif
xout aL, aR
endop
#end
|