aboutsummaryrefslogtreecommitdiff
path: root/site/udo/sound_sdb.udo
blob: 82fe009c40fa80652677ccbc61573f71a18b344d (plain)
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#ifndef UDO_SOUNDSDB
#define UDO_SOUNDSDB ##
/*
	SQL database interface to sound object management

	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 "bussing.udo"
#include "host_tools.udo"
#include "pvs_tools.udo"

/*
	soundcollection object structure: 2D array with first dimension as sound index and second as
		0	runtime sound db index
		1	rms normalised over all collections
		2	average pitch hz
		3	average centroid hz
	   	4	match distance; optional depending on returning opcode
*/



;gisdb_data[][] init 99999, 4

/*
	Internal: format a standard soundcollection database result as soundcollection object
	isounds[][] _load_sdbobject Sresult[][], [ihasdistance]

	isounds[][]		soundcollection object
	Sresult[][]		the raw database result string array
	ihasdistance		whether to include the additional distance dimension

*/

opcode _sdb_loadobject, i[][], S[][]o
	Sres[][], ihasdistance xin
	iarraylength = lenarray(Sres)
	idata[][] init iarraylength, 4 + ihasdistance
	index = 0
	while (index < lenarray(Sres)) do
		ifileid strtod Sres[index][0]
		ichannels strtod Sres[index][2]
		iduration strtod Sres[index][3]
		idata[index][0] _rdb_loadsound ifileid, ichannels, iduration, Sres[index][1]
		idata[index][1] strtod Sres[index][4] ; rmsnormal
		idata[index][2] strtod Sres[index][5] ; pitch
		idata[index][3] strtod Sres[index][6] ; centroid
		if (ihasdistance == 1) then
			idata[index][4] strtod Sres[index][7]
		endif
		index += 1
	od
	xout idata
endop


/*
	Get a string array of all current filecollections
	Scollections[] sdb_listcollections

	Scollections[]	list of collections
*/
opcode sdb_listcollections, S[], 0
	Sres[][] dbarray gidb, "select name from filecollection"
	ilen = lenarray(Sres)
	Scollections[] init ilen
	index = 0
	while (index < ilen) do
		Scollections[index] = Sres[index][0]
		index += 1
	od
	xout Scollections
endop


/*
    Get soundcollection(s) with basic analysis information
    isounds[][] sdb_getcollection ScollectionName

    isounds[][]		soundcollection object 
    ScollectionName the name of the filecollection in the database or comma separated list of collections
*/

opcode sdb_getcollection, i[][], S
	Scollection xin
	Sbase = {{select file_id, f_localpath(%d, path), channels, duration, rmsnormal, pitch, centroid
		from svw.analysis_basic_collectionnorm a
		join filecollection fc on fc.id = a.filecollection_id
		where %s
	}}

	if (strindex(Scollection, ",") > 0) then
		Sclause = "(1=2"
		index = 1
		Stemp = Scollection
		while (index > 0) do
			index strindex Stemp, ","
			if (index > 0) then
				Sclause strcat Sclause, sprintf(" or fc.name='%s'", strsub(Stemp, 0, index))		
				Stemp strsub Stemp, index+1
			else
				Sclause strcat Sclause, sprintf(" or fc.name='%s'", Stemp)
			endif
		od
		Sclause strcat Sclause, ")"
	else
		Sclause = sprintf("fc.name = '%s'", Scollection)
	endif

	Squery sprintf Sbase, gihost_type, Sclause
	Sres[][] dbarray gidb, Squery
	idata[][] _sdb_loadobject Sres
	xout idata
endop



/*
    Bubble sort a soundcollection 'object' by a specified analysis element
    iordered[][] orderby isounds[][], ielement, [isortorder=0]

    iordered[][]    the sorted soundcollection 'object'
    isounds[][]     the input soundcollection 'object'
    ielement        which analysis element to order by:
                        0	duration
                        1	rms
                        2	pitch
                        3	centroid
			4	distance, if collection is provided from a matching opcode
    isortorder      optional sort order:
                        0   descending
                        1   ascending

*/
opcode sdb_orderby, i[][], i[][]io
	idata[][], ielement, iordering xin
	ilen = lenarray(idata)
	index = 0
	while (index < ilen) do
		index2 = 0
		while (index2 < ilen) do
			; duration requires an obnoxious looking cross array reference
			if (\
				(ielement == 0 && ( \
					(iordering == 0 && gisoundsdb[idata[index][0]][3] > gisoundsdb[idata[index2][0]][3]) \
					|| (iordering == 1 && gisoundsdb[idata[index][0]][3] < gisoundsdb[idata[index2][0]][3]) \
				)) || ( \
					(iordering == 0 && idata[index][ielement] > idata[index2][ielement]) \
					||(iordering == 1 && idata[index][ielement] < idata[index2][ielement]) \
				) \
			) then
				iswap[] getrow idata, index
				iswap2[] getrow idata, index2
				idata setrow iswap2, index
				idata setrow iswap, index2
			endif
			index2 += 1
		od
		index += 1
	od
	xout idata
endop






/*
    Filter a soundcollection object with min and max parameters of basic analysis data applied
    ifiltered[][], ivalid subselect isounds[][],
        [iminduration, imaxdur, iminrms, imaxrms, iminpitch, imaxpitch, imincent, imaxcent]

    ifiltered[][]   the new soundcollection 'object' with sounds limited to scope specified
    ivalid          1 if records returned, 0 if the returned array is effectively empty
    isounds[][]     the input soundcollection 'object' to be filtered
    iminduration    optional minimum duration
    imaxduration    optional maximum duration
    iminrms         optional minimum rms
    imaxrms         optional maximum rms
    iminpitch       optional minimum pitch
    imaxpitch       optional maximum pitch
    imincent        optional minimum centroid
    imaxcent        optional maximum centroid

*/
opcode sdb_subselect, i[][]i, i[][]iii
    idata[][], ielement, imin, imax xin
    
    indexes[] init lenarray(idata)
    imaxindex = 0
    index = 0

    while (index < lenarray(idata)) do
        if ( \
		idata[index][ielement] >= imin && idata[index][ielement] <= imax \
        ) then
            indexes[imaxindex] = index
            imaxindex += 1
        endif
        index += 1
    od

    if (imaxindex == 0) then
        ifiltered[][] init 1, 1
        ivalid = 0
    else
        ifiltered[][] init imaxindex, 7
        ivalid = 1
        index = 0
        while (index < imaxindex) do  ; TODO setrow here?????
            index2 = 0
            while (index2 < 7) do
                ifiltered[index][index2] = idata[indexes[index]][index2]
                index2 += 1
            od
            index += 1
        od
    endif
    xout ifiltered, ivalid
endop




opcode _sdb_playsound, 0, iSppoooo
	index, Sbus, iamp, ihz, iwhen, iusepvs, ikeepformant, ifadein xin
	Scoreline = sprintf("i\"sdb_player_default\" %f 1 \"%s\" %d %f %f %d %d %d", iwhen, Sbus, index, iamp, ihz, iusepvs, ikeepformant, ifadein)
	scoreline_i Scoreline
endop


opcode sdb_playsound, 0, i[][]iSpooooo
	isounds[][], index, Sbus, iamp, iwhen, ihz, iusepvs, ikeepformant, ifadein xin
	_sdb_playsound isounds[index][0], Sbus, iamp, ihz, iwhen, iusepvs, ikeepformant, ifadein
endop


opcode sdb_playrandom, 0, i[][]Spooooo
	isounds[][], Sbus, iamp, iwhen, ihz, iusepvs, ikeepformant, ifadein xin
	index = round(random(0, lenarray(isounds)-1))
	_sdb_playsound isounds[index][0], Sbus, iamp, ihz, iwhen, iusepvs, ikeepformant, ifadein
endop


instr sdb_player_default
	Sbus = p4
	isoundindex = p5
	iamp = p6
	ihz = p7
	iusepvs = p8
	ikeepformant = p9
	ifadein = p10
	isound[] = get_sound(isoundindex)

	p3 = isound[3]

	aL, aR loscil iamp, 1, isound[0], 1

	kenv linseg 1, p3*0.9, 1, p3*0.1, 0

	bus_mix(Sbus, aL*kenv, aR*kenv)
endin

#end