#ifndef UDO_TABLETOOLS #define UDO_TABLETOOLS ## /* Table tools This file is part of the SONICS UDO collection by Richard Knight 2022, 2024 License: GPL-2.0-or-later http://1bpm.net */ /* Normalise an audio ftable to to between -1 and 1 ftnormalise ifn ifn ftable to analyse */ opcode ftnormalise, 0, ip ifn, iscaling xin imaxpos = -999 imaxneg = 999 iendpoint = 0 index = 0 while (index < ftlen(ifn)) do ival table index, ifn if (ival > 0 && ival > imaxpos) then imaxpos = ival elseif (ival < 0 && ival < imaxneg) then imaxneg = ival endif index += 1 od iscale = ((0.999/max(abs(imaxneg), abs(imaxpos)))) * iscaling index = 0 while (index < ftlen(ifn)) do ival table index, ifn tablew ival * iscale, index, ifn index += 1 od endop opcode tab_record, i, aj ain, iduration xin if (iduration == -1 || iduration > p3) then iduration = p3 endif ifn ftgen 0, 0, -(iduration * sr), -2, 0 apos lphasor 1 tablew ain, apos, ifn xout ifn endop /* Sample rate agnostic audio file loading */ opcode tab_loadaudio, iik, S Sfile xin kdone init 0 ilen = filelen(Sfile) ilensamp = ilen * sr ikcycles = ilen * kr ichannels = filenchnls(Sfile) ifnL ftgen 0, 0, ilensamp, 2, 0 if (ichannels == 2) then ifnR ftgen 0, 0, ilensamp, 2, 0 else ifnR = -1 endif ktimek timeinstk kcount init 0 if (ktimek == 1) then while (kcount < ikcycles) do apos linseg 0, ilen, ilensamp - 1 if (ichannels == 1) then asig soundin Sfile tablew asig, apos, ifnL else aL, aR soundin Sfile tablew aL, apos, ifnL tablew aR, apos, ifnR endif kcount += 1 od else kdone = 1 endif xout ifnL, ifnR, kdone endop opcode tab_samplerateconvert, iik, ijpj ifnL, ifnR, ifreeafter, isourcesr xin isr = (isourcesr == -1) ? ftsr(ifnL) : isourcesr kdone init 0 if (isr != sr) then ilen = ftlen(ifnL) ilens = ftlen(ifnL) / isr inewlen = (sr / isr) * ilen ifnnewL ftgen 0, 0, -inewlen, -2, 0 if (ifnR != -1) then ifnnewR ftgen 0, 0, -inewlen, -2, 0 else ifnnewR = -1 endif ktimek timeinstk ikcycles = ilens * kr if (ktimek == 1) then kcount = 0 while (kcount < ikcycles) do aposw linseg 0, ilens, inewlen - 1 aposr linseg 0, ilens, ilen - 1 asig table3 aposr, ifnL tablew asig, aposw, ifnnewL if (ifnR != -1) then asig table3 aposr, ifnR tablew asig, aposw, ifnnewR endif kcount += 1 od else kdone = 1 endif if (ifreeafter == 1) then ftfree ifnL, 1 if (ifnR != -1) then ftfree ifnR, 1 endif endif else kdone init 1 ifnnewL = ifnL ifnnewR = ifnR endif xout ifnnewL, ifnnewR, kdone endop opcode tab_samplerateconvert, ik, ipj ifn, ifreeafter, isourcesr xin ifnnew, i_, kdone tab_samplerateconvert ifn, -1, ifreeafter, isourcesr xout ifnnew, kdone endop ; table opcode tab_serialise, S, i ifn xin ilen = ftlen(ifn) index = 0 Sout = "[" while (index < ilen) do if (index != 0) then Sout = strcat(Sout, ",") endif ivalue = table:i(index, ifn) SprintfChar = (frac(ivalue) == 0) ? "%d" : "%f" Sout = strcat(Sout, sprintf(SprintfChar, ivalue)) index += 1 od Sout = strcat(Sout, "]") xout Sout endop opcode tab_unserialise, 0, Si Sdata, ifn xin ilen = strlen(Sdata) ichar = 0 inarray = 0 ivalstart = -1 index = 0 while (ichar < ilen) do Schar = strsub(Sdata, ichar, ichar + 1) if (strcmp(Schar, "[") == 0) then inarray = 1 ivalstart = ichar + 1 elseif (inarray == 1 && strcmp(Schar, "]") == 0) then inarray = 0 elseif (inarray == 1 && strcmp(Schar, ",") == 0) then tablew strtod(strsub(Sdata, ivalstart, ichar)), index, ifn ivalstart = ichar + 1 index += 1 endif ichar += 1 od endop opcode tab_bubblesort, 0, i ifn xin itemp = 0 ilen = ftlen(ifn) index1 = 0 while (index1 < ilen - 1) do index2 = 0 while (index2 < ilen - 1 - index1) do ival1 = tab_i(index2, ifn) ival2 = tab_i(index2 + 1, ifn) if (ival1 > ival2) then itemp = ival1 tabw_i ival2, index2, ifn tabw_i itemp, index2 + 1, ifn endif index2 += 1 od index1 += 1 od endop opcode tab_destroy, 0, i ifn xin if (ftexists(ifn) == 1) then ftfree ifn, 0 endif endop /* get condensed table eg for waveform view */ opcode tab_overview, i, io ifn, isamples xin isamples = (isamples == 0) ? 256 : isamples ifnlen = ftlen(ifn) istep = round(ifnlen / isamples) ifndata ftgen 0, 0, -isamples, 7, 0 index = 0 indexwrite = 0 while (index < ifnlen) do ival tab_i index, ifn if (!(indexwrite > isamples - 1)) then tabw_i ival, indexwrite, ifndata endif indexwrite += 1 index += istep od xout ifndata endop #end