#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