#ifndef UDO_BSAMP #define UDO_BSAMP ## /* Live buffer sampling and glitch out playback This file is part of the SONICS UDO collection by Richard Knight 2023 License: GPL-2.0-or-later http://1bpm.net */ #include "bussing.udo" #include "tab2wav.udo" #ifndef BSAMP_BUFFERNUM #define BSAMP_BUFFERNUM #8# #end #ifndef BSAMP_CHANNELS #define BSAMP_CHANNELS #1# #end #ifndef BSAMP_BUFFERLENGTH #define BSAMP_BUFFERLENGTH #8# #end #ifndef BSAMP_IOPROCRATE #define BSAMP_IOPROCRATE #10# #end #ifndef BSAMP_IOBLOCKSIZE #define BSAMP_IOBLOCKSIZE #2048# #end gibsamp_buffernum = $BSAMP_BUFFERNUM gibsamp_channels = $BSAMP_CHANNELS gibsamp_buffers[][] init gibsamp_buffernum, gibsamp_channels gibsamp_bufferused[] init gibsamp_buffernum isize = sr * $BSAMP_BUFFERLENGTH index = 0 while (index < gibsamp_buffernum) do indexchan = 0 while (indexchan < gibsamp_channels) do gibsamp_buffers[index][indexchan] = ftgen(0, 0, isize, 2, 0) gibsamp_bufferused[index] = isize indexchan += 1 od index += 1 od instr _bsamp_setbufferusedsize ibufferindex = p4 ilens = p5 gibsamp_bufferused[ibufferindex] = round(ilens * sr) turnoff endin opcode bsamp_save, k, iSjj ibufferindex, Spath, iprocrate, iblocksize xin if (gibsamp_channels == 2) then SpathL = sprintf("%s.L", Spath) SpathR = sprintf("%s.R", Spath) else SpathL = Spath SpathR = Spath endif kdoneL tab2wav gibsamp_buffers[ibufferindex][0], SpathL, gibsamp_bufferused[ibufferindex], $BSAMP_IOPROCRATE, $BSAMP_IOBLOCKSIZE if (gibsamp_channels == 2) then kdoneR tab2wav gibsamp_buffers[ibufferindex][1], SpathR, gibsamp_bufferused[ibufferindex], $BSAMP_IOPROCRATE, $BSAMP_IOBLOCKSIZE else kdoneR init 1 endif xout (kdoneL & kdoneR) endop opcode bsamp_load, k, iSjj ibufferindex, Spath, iprocrate, iblocksize xin SpathR = sprintf("%s.R", Spath) if (filevalid(SpathR) == 1) then SpathL = sprintf("%s.L", Spath) else SpathL = Spath SpathR = Spath endif gibsamp_bufferused[ibufferindex] = min(round(filelen(SpathL) * sr), ftlen(gibsamp_buffers[ibufferindex][0])) kdoneL wav2tab SpathL, gibsamp_buffers[ibufferindex][0], 0, $BSAMP_IOPROCRATE, $BSAMP_IOBLOCKSIZE if (gibsamp_channels == 2) then kdoneR wav2tab SpathR, gibsamp_buffers[ibufferindex][1], 1, $BSAMP_IOPROCRATE, $BSAMP_IOBLOCKSIZE else kdoneR init 1 endif xout (kdoneL & kdoneR) endop instr bsamp_record ibufferindex = p4 Sbus = strget(p5) ifnL = gibsamp_buffers[ibufferindex][0] if (gibsamp_channels == 2) then ifnR = gibsamp_buffers[ibufferindex][1] else ifnR = -1 endif ilen = ftlen(ifnL) apos lphasor 1 aL, aR bus_tap Sbus tablew aL, apos, ifnL, 0, 0, 1 if (gibsamp_channels == 2) then tablew aR, apos, ifnR, 0, 0, 1 endif ktimes timeinsts kreleasing init 0 if (release:k() == 1 && kreleasing == 0) then kreleasing = 1 if (ktimes > $BSAMP_BUFFERLENGTH) then ktimes = ktimes % $BSAMP_BUFFERLENGTH if (ktimes == 0) then ktimes = $BSAMP_BUFFERLENGTH endif endif schedulek("_bsamp_setbufferusedsize", 0, 1, ibufferindex, ktimes) endif endin opcode bsamp_clear, 0, i ibufferindex xin gibsamp_bufferused[ibufferindex] = 0 ftset gibsamp_buffers[ibufferindex][0], 0 if (gibsamp_channels == 2) then ftset gibsamp_buffers[ibufferindex][1], 0 endif endop opcode bsamp_play, aa, ikkOo ibufferindex, kreadstart, ktriglen, kreverse, iratiotimes xin ifnL = gibsamp_buffers[ibufferindex][0] if (gibsamp_channels == 2) then ifnR = gibsamp_buffers[ibufferindex][1] else ifnR = -1 endif ilen = gibsamp_bufferused[ibufferindex] ; ftlen(ifn) ilens = ilen / sr areadstart = upsamp(kreadstart) if (iratiotimes == 0) then areadstart = areadstart / ilens else ktriglen *= ilens endif klenchanger metro 1 / ktriglen async upsamp klenchanger irate = (1 / ((ilen) / sr)) apos, a_ syncphasor irate, async ;aamp triglinseg klenchanger, 0, 0.001, 1, 3600, 1 ;kamp loopseg 0.01, klenchanger, 0, 0, 0.01, 1, 3600, 1 ;aamp = upsamp(kamp) aamp init 1 apos += areadstart apos *= ilen if (kreverse == 1) then apos = ilen - apos endif aL tablei apos, ifnL, 0, 0, 1 aL *= aamp if (gibsamp_channels == 2) then aR tablei apos, ifnR, 0, 0, 1 aR *= aamp else aR = aL endif xout aL, aR endop #end