aboutsummaryrefslogtreecommitdiff
path: root/site/udo/sounddb.udo
diff options
context:
space:
mode:
Diffstat (limited to 'site/udo/sounddb.udo')
-rwxr-xr-xsite/udo/sounddb.udo270
1 files changed, 270 insertions, 0 deletions
diff --git a/site/udo/sounddb.udo b/site/udo/sounddb.udo
new file mode 100755
index 0000000..91f6f10
--- /dev/null
+++ b/site/udo/sounddb.udo
@@ -0,0 +1,270 @@
+#ifndef UDO_SOUNDDB
+#define UDO_SOUNDDB ##
+/*
+ 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
+
+*/
+
+; if XDB extract has been loaded, don't use database
+#ifdef XDB_SET
+#include "soundxdb.udo"
+#else
+
+#include "pgdb.udo"
+#include "host_tools.udo"
+
+; set max number of files for global array allocation
+imaxindex dbscalar gidb, "SELECT MAX(id)+1 FROM file"
+gisounddb[][] init imaxindex, 4
+
+
+/*
+ Load file to gisounddb: to be used internally and passed parameters from database
+
+ _sounddb_loadfile ifileid, Spath, ichannels, iduration, irmsnorm, isamplerate [, imono=0]
+
+ ifileid database file ID, corresponds to index of gisounddb
+ Spath path to load sound file from
+ ichannels number of channels
+ iduration sound duration
+ irmsnorm normalisation factor
+ isamplerate sample rate
+ imono whether to load sound as mono
+*/
+opcode _sounddb_loadfile, 0, iSiiiio
+ ifileid, Spath, ichannels, iduration, irmsnorm, isamplerate, imono xin
+ if (imono == 1) then
+ ichannels = 1
+ iloadchan = 1
+ else
+ iloadchan = 0
+ endif
+ isize = iduration * isamplerate * ichannels; HACK: grain cannot use deferred time: TODO: pass in samplerate and length to opcode (TODO: database needs samplerate)
+ ifn = ftgen(0, 0, isize, 1, Spath, 0, 0, iloadchan)
+ gisounddb[ifileid][0] = ifn
+ gisounddb[ifileid][1] = ichannels
+ gisounddb[ifileid][2] = iduration
+ gisounddb[ifileid][3] = irmsnorm
+endop
+
+
+/*
+ Get file details for a give file ID
+
+ ifn, ichannels, iduration, irmsnorm sounddb_get ifileid
+
+ ifn ftable number containing sound
+ ichannels number of channels in file
+ iduration duration of file in seconds
+ irmsnorm RMS normalisation factor
+ ifileid file ID to look up
+*/
+opcode sounddb_get, iiii, i
+ ifileid xin
+ xout gisounddb[ifileid][0], gisounddb[ifileid][1], gisounddb[ifileid][2], gisounddb[ifileid][3]
+endop
+
+
+/*
+ Load files to gisounddb if not already loaded, to be passed a 2D string array as returned from a database query. Returns the file IDs in an array
+
+ ifileids[] _sounddb_loadobject SqueryResult[][] [, imono=0]
+
+ ifileids[] database file IDs, which also correspond to indexes in gisounddb
+ SqueryResult[][] query result from database with each row containing file ID, path, channels, duration, RMS normalisation factor and samplerate
+ imono whether to load all sounds as mono
+*/
+opcode _sounddb_loadobject, i[], S[][]o
+ Sres[][], imono xin
+ iarraylength = lenarray(Sres)
+ idata[] init iarraylength
+ index = 0
+ while (index < iarraylength) do
+ ifileid strtod Sres[index][0] ; fileid
+ idata[index] = ifileid
+
+ if (gisounddb[ifileid][0] == 0) then ; load required
+ _sounddb_loadfile ifileid, Sres[index][1], strtod(Sres[index][2]), strtod(Sres[index][3]), strtod(Sres[index][4]), strtod(Sres[index][5]), imono
+ endif
+ index += 1
+ od
+ xout idata
+endop
+
+
+/*
+ Load a sound to gisounddb if not already loaded, based on a specified query using f_nearestnote.
+ Return the file ID and the result of column 6, which is the ratio to the nearest pitch requested.
+ Used internally by the sounddb_mel_nearestnote opcodes which select one row
+
+ ifileid, ipitchratio _sounddb_mel_nearestnote_inner Squery
+
+ ifileid file ID
+ ipitchratio pitch ratio to note requested
+ Squery query to evaluate
+*/
+opcode _sounddb_mel_nearestnote_inner, ii, S
+ Squery xin
+ Sres[][] dbarray gidb, Squery
+ ifileid strtod Sres[0][0]
+
+ if (gisounddb[ifileid][0] == 0) then ; load required
+ _sounddb_loadfile ifileid, Sres[0][1], strtod(Sres[0][2]), strtod(Sres[0][3]), strtod(Sres[0][4]), strtod(Sres[0][5])
+ endif
+ xout ifileid, strtod(Sres[0][6])
+endop
+
+
+; nearest note query base
+#define SOUNDDB_NNQUERYBASE #SELECT file_id, f_localpath(%d, path), channels, duration, rmsnormal, samplerate, pitchratio FROM f_nearestnote#
+
+
+/*
+ Get the nearest note in a filecollection, return the file ID and the pitch ratio adjustment required to the requested note.
+
+ ifileid, ipitchratio sounddb_mel_nearestnote Scollection, inote
+
+ ifileid file ID, corresponding to index in gisounddb
+ ipitchratio pitch ratio adjustment required to make the file match the requested note
+ Scollection collection name
+ inote MIDI note number
+*/
+opcode sounddb_mel_nearestnote, ii, Si
+ Scollection, inote xin
+ ifileid, ipitchratio _sounddb_mel_nearestnote_inner sprintf("$SOUNDDB_NNQUERYBASE (%f, '%s')", gihost_type, inote, Scollection)
+ xout ifileid, ipitchratio
+endop
+
+
+/*
+ Get the nearest note in a filecollection, return the file ID and the pitch ratio adjustment required to the requested note.
+
+ ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, inote
+
+ ifileid file ID, corresponding to index in gisounddb
+ ipitchratio pitch ratio adjustment required to make the file match the requested note
+ icollectionid collection ID
+ inote MIDI note number
+*/
+opcode sounddb_mel_nearestnote, ii, ii
+ icollectionid, inote xin
+ ifileid, ipitchratio _sounddb_mel_nearestnote_inner sprintf("$SOUNDDB_NNQUERYBASE (%f, %d)", gihost_type, inote, icollectionid)
+ xout ifileid, ipitchratio
+endop
+
+
+/*
+ List file collections
+
+ Sout[][] list of file collection name and type
+*/
+opcode sounddb_listcollections, S[][], 0
+ Squery = "select fc.name, fct.name from filecollection fc join filecollectiontype fct on fc.type_id = fct.id"
+ Sout[][] dbarray gidb, Squery
+ xout Sout
+endop
+
+
+/*
+
+*/
+opcode sounddb_getbypathpart, i[], S
+ SpathPart xin
+ Sbase = {{select file_id, f_localpath(%d, path), channels, duration, rmsnormal, samplerate
+ from svw.analysis_basic_collectionnorm
+ where path ilike '%s'
+ }}
+ Squery = sprintf(Sbase, gihost_type, SpathPart)
+ Sres[][] dbarray gidb, Squery
+ idata[] _sounddb_loadobject Sres
+ xout idata
+endop
+
+
+/*
+ Get the collection ID and file IDs of a filecollection, also loading each file to gisounddb
+
+ ifileids[], icollectionid sounddb_getcollection Scollection [, imono=0]
+
+ ifileids[] file IDs in the collection, accessible as indexes to f-tables in gisounddb
+ icollectionid collection ID
+ Scollection collection name
+ imono whether to load all sounds in mono
+*/
+opcode sounddb_getcollection, i[]i, So
+ Scollection, imono xin
+ Sbase = {{select file_id, f_localpath(%d, path), channels, duration, rmsnormal, samplerate, fc.id
+ 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[] _sounddb_loadobject Sres, imono
+ icollectionid = strtod(Sres[0][6])
+ xout idata, icollectionid
+endop
+
+
+/*
+ Get the ID of a filecollection by name
+
+ icollectionid sounddb_getcollectionid Scollection [, ipreload = 0, imono = 0]
+
+ icollectionid collection ID
+ Scollection collection name
+ ipreload preload the files to gisounddb
+ imono whether to load all sounds in mono
+*/
+opcode sounddb_getcollectionid, i, Soo
+ Scollection, ipreload, imono xin
+ if (ipreload == 0) then
+ icollectionid = dbscalar(gidb, sprintf("SELECT id FROM filecollection WHERE name = '%s'", Scollection))
+ else
+ i_[], icollectionid sounddb_getcollection Scollection, imono
+ endif
+ xout icollectionid
+endop
+
+/*
+ Get the file IDs of a filecollection, also loading each file to gisounddb
+
+ ifileids[] sounddb_getcollection Scollection [, imono = 0]
+
+ ifileids[] file IDs in the collection, accessible as indexes to f-tables in gisounddb
+ Scollection collection name
+ imono whether to load all sounds in mono
+*/
+opcode sounddb_getcollection, i[], So
+ Scollection, imono xin
+ idata[], icollectionid sounddb_getcollection Scollection, imono
+ xout idata
+endop
+
+; end of XDB_SET
+#end
+
+#end