From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/udo/sound_melsys.udo | 215 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100755 site/udo/sound_melsys.udo (limited to 'site/udo/sound_melsys.udo') diff --git a/site/udo/sound_melsys.udo b/site/udo/sound_melsys.udo new file mode 100755 index 0000000..588f137 --- /dev/null +++ b/site/udo/sound_melsys.udo @@ -0,0 +1,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 -- cgit v1.2.3