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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
#ifndef UDO_MELSYS
#define UDO_MELSYS ##
/*
Melodic sampler system
Typical external usage should only refer to
mel_playnote
mel_getcollection
This file is part of the SONICS UDO collection by Richard Knight 2021
License: GPL-2.0-or-later
http://1bpm.net
*/
#include "sound_db.udo"
#include "pgdb.udo"
#include "host_tools.udo"
#include "pvs_tools.udo"
#include "bussing.udo"
opcode _mel_loadobject, i[][], S[][]
Sres[][] xin
imelmap[][] init 128, 16
index = 0
while (index < lenarray(Sres)) do
ifileid strtod Sres[index][0]
ichannels strtod Sres[index][2]
iduration strtod Sres[index][3]
inote strtod Sres[index][4]
if (imelmap[inote][0] == 0) then
imelmap[inote][0] = 1
endif
imelmap[inote][imelmap[inote][0]] _rdb_loadsound ifileid, ichannels, iduration, Sres[index][1]
imelmap[inote][0] = imelmap[inote][0] + 1 ; first index keeps track of length
index += 1
od
xout imelmap
endop
/*
Get soundcollection with basic analysis information
isounds[][] getcollection ScollectionName
isounds[][] soundcollection object
ScollectionName the name of the filecollection in the database
*/
opcode mel_getcollection, i[][], S
Scollection xin
Sbase = {{select file_id, f_localpath(%d, path), channels, duration, note
from svw.analysis_basic_collectionnorm a
join filecollection fc on fc.id = a.filecollection_id
join filecollectiontype fct on fct.id = fc.type_id
where fc.name = '%s'
and fct.name = 'melsys'
}}
Squery sprintf Sbase, gihost_type, Scollection
Sres[][] dbarray gidb, Squery
idata[][] _mel_loadobject Sres
xout idata
endop
/*
Get all melodic soundcollection names
Scollections[] mel_listcollections
Scollections[] list of soundcollections
*/
opcode mel_listcollections, S[], 0
Sres[][] dbarray gidb, "select distinct fc.name from filecollection fc join filecollectiontype fct on fct.id = fc.type_id where fct.name = 'melsys'"
ilen = lenarray(Sres)
Scollections[] init ilen
index = 0
while (index < ilen) do
Scollections[index] = Sres[index][0]
index += 1
od
xout Scollections
endop
/*
Get nearest note and a ratio to alter to specific note
*/
opcode _mel_getnearestnote, ii, ii[][]
inote, imelmap[][] xin
iratio = 0
inearest = -1
idistance = 999
index = 0
while (index < 128) do
if (imelmap[index][0] > 0) then
if (inote > index) then
imeasure = inote - index
if (imeasure < idistance) then
idistance = imeasure
inearest = index
endif
elseif (inote < index ) then
imeasure = index - inote
if (imeasure < idistance) then
idistance = imeasure
inearest = index
endif
else
idistance = 0
inearest = inote
goto output
endif
endif
index += 1
od
iratio = cpsmidinn(inote) / cpsmidinn(inearest)
output:
isoundindex = imelmap[inearest][int(random(1, imelmap[inearest][0]))]
xout isoundindex, iratio
endop
opcode mel_getrandnote, ii, ii[][]
inote, imelmap[][] xin
iout = -1
if (imelmap[inote][0] > 0) then
index = int(random(1, imelmap[inote][0]))
iout = imelmap[inote][index]
iratio = 1
else
iout, iratio _mel_getnearestnote inote, imelmap
endif
xout iout, iratio
endop
/*
*/
opcode _mel_playsound, 0, iSppooooo
index, Sbus, iamp, ipitchratio, iwhen, iusepvs, ikeepformant, ifadein, idurationoverride xin
Scoreline = sprintf("i\"mel_player_default\" %f 1 \"%s\" %f %f %f %d %d %d %f", iwhen, Sbus, index, iamp, ipitchratio, iusepvs, ikeepformant, ifadein, idurationoverride)
scoreline_i Scoreline
endop
opcode mel_playnote, 0, i[][]iSpooooo
imelmap[][], inote, Sbus, iamp, iwhen, idurationoverride, iusepvs, ikeepformant, ifadein xin
isoundindex, ipitchratio mel_getrandnote inote, imelmap
_mel_playsound isoundindex, Sbus, iamp, ipitchratio, iwhen, iusepvs, ikeepformant, ifadein, idurationoverride
endop
instr mel_player_default
Sbus = p4
isoundindex = p5
iamp = p6
ipitchratio = p7
iusepvs = p8
ikeepformant = p9
ifadein = p10
idurationoverride = p11
isound[] = get_sound(isoundindex)
if (idurationoverride == 0) then
p3 = isound[3] ; set duration
else
p3 = idurationoverride
endif
if (iusepvs == 1) then
iloscilratio = 1
else
iloscilratio = ipitchratio
endif
if (isound[2] == 1) then ; check channels
aL loscil iamp, iloscilratio, isound[0], 1
if (iusepvs == 1) then
aL pvscaler aL, ipitchratio, ikeepformant
endif
aR = aL
else
aL, aR loscil iamp, iloscilratio, isound[0], 1
if (iusepvs == 1) then
aL pvscaler aL, ipitchratio, ikeepformant
aR pvscaler aR, ipitchratio, ikeepformant
endif
endif
if (ifadein == 1) then
kenv linseg 0, p3*0.4, 1, p3*0.5, 1, p3*0.1, 0
else
kenv linseg 1, p3*0.9, 1, p3*0.1, 0
endif
bus_mix(Sbus, aL*kenv, aR*kenv)
endin
#end
|