; REBEAT ; ; simple pedal-like looper ; ; code based on TabRecPlay example by Iain McCurdy ; (s) Severák 2019 ; licensed with MIT license form caption("REBEAT") size(300, 200), colour(58, 110, 182), pluginid("rebe") button bounds(48, 164, 192, 27) text("REBEAT", "REBEAT") channel("rebeat") identchannel("rebeatWidget") fontcolour:0(128, 128, 128, 255) gentable bounds(2, 6, 296, 131) identchannel("gentable") tablenumber(101.0) label bounds(50, 144, 191, 16) text("waiting...") identchannel("statusbar") -n -d -+rtmidi=NULL -M0 -m0d ; Initialize the global variables. ksmps = 32 nchnls = 2 0dbfs = 1 gistorageL ftgen 0,0,1048576,-7,0 ;AUDIO DATA STORAGE SPACE (ABOUT 23 SECONDS) gistorageR ftgen 0,0,1048576,-7,0 ;AUDIO DATA STORAGE SPACE (ABOUT 23 SECONDS) gkRecDur init 0 ; --- gkRecord init 0 gkPause init 0 gkPlayLoop init 0 ; --- gkInGain init 1 gkLoopBeg init 0 gkLoopEnd init 1 gkSpeed init 1 gkOutGain init 1 instr GUI ; 0 = stopped; 1 = recording; 2 = looping kStatus init 0 kRebeat chnget "rebeat" Scolor init "" gitablelen = ftlen(gistorageL) if changed:k(kRebeat)==1 then if kStatus==0 then chnset "text(\"recording...\")", "statusbar" Scolor strcatk "fontcolour:0(255, 0, 0, 255), fontcolour:1(255, 0, 0, 255)", "" kStatus = 1 event "i", "Record", 0, 23 printks "recording...\n", 0 elseif kStatus==1 then chnset "text(\"playing...\")", "statusbar" Scolor strcatk "fontcolour:0(0, 100, 0, 255), fontcolour:1(0, 100, 0, 255)", "" kStatus = 2 printks "playing...\n", 0 gkPlayLoop = 1 event "i", "PlayLoop", 0, 3600 elseif kStatus==2 then chnset "text(\"waiting...\")", "statusbar" Scolor strcatk "fontcolour:0(128,128,128,255),fontcolour:1(128,128,128,255)", ")" kStatus = 0 gkPlayLoop = 0 printks "waiting...\n", 0 endif chnset Scolor, "rebeatWidget" endif endin ;instr setTable ; Stablenum sprintf "tablenumber(%d)", gistorageL ; printks "tablenumber(%d)", 0, gistorageL ; chnset Stablenum, "gentable" ;endin instr Record if gkPlayLoop == 1 then turnoff endif if gkPause == 1 goto SKIP_RECORD ;IF PAUSE BUTTON IS ACTIVATED TEMPORARILY SKIP RECORDING PROCESS ;printks "rec...\n", 2 ainL,ainR ins ;READ AUDIO FROM LIVE INPUT CHANNEL 1 aRecNdx line 0,gitablelen/sr,1 ;CREATE A POINTER FOR WRITING TO TABLE - FREQUENCY OF POINTER IS DEPENDENT UPON TABLE LENGTH AND SAMPLE RATE aRecNdx = aRecNdx*gitablelen ;RESCALE POINTER ACCORDING TO LENGTH OF FUNCTION TABLE gkRecDur downsamp aRecNdx ;CREATE A K-RATE GLOBAL VARIABLE THAT WILL BE USED BY THE 'PLAYBACK' INSTRUMENT TO DETERMINE THE LENGTH OF RECORDED DATA tablew ainL*gkInGain, aRecNdx, gistorageL;WRITE AUDIO TO AUDIO STORAGE TABLE tablew ainR*gkInGain, aRecNdx, gistorageR;WRITE AUDIO TO AUDIO STORAGE TABLE ; scruber Sscruber sprintfk "scrubberposition(%d, %d), tablenumber(%d)", k(aRecNdx), k(gistorageL), k(gistorageL) chnset Sscruber, "gentable" if gkRecDur>=gitablelen then ;IF MAXIMUM RECORD TIME IS REACHED... kRecord=0 printks "limit reached!\n", 0 turnoff endif ;END OF CONDITIONAL BRANCH SKIP_RECORD: endin instr PlayLoop if gkPlayLoop==0 then turnoff endif if gkPause=1 goto SKIP_PLAY_LOOP ;IF PAUSE BUTTON IS ACTIVATED SKIP ALL RECORDING AND PLAYBACK... kporttime linseg 0,0.001,0.05 ;PORTAMENTO TIME RAMPS UP RAPIDLY TO A HELD VALUE kLoopBeg portk gkLoopBeg, kporttime ;APPLY PORTAMENTO SMOOTHING TO CHANGES OF LOOP BEGIN SLIDER kLoopEnd portk gkLoopEnd, kporttime ;APPLY PORTAMENTO SMOOTHING TO CHANGES OF LOOP END SLIDER kLoopBeg = kLoopBeg * gkRecDur ;RESCALE gkLoopBeg (RANGE 0-1) TO BE WITHIN THE RANGE 0-FILE_LENGTH. NEW OUTPUT VARIABLE kLoopBeg. kLoopEnd = kLoopEnd * gkRecDur ;RESCALE gkLoopEnd (RANGE 0-1) TO BE WITHIN THE RANGE 0-FILE_LENGTH. NEW OUTPUT VARIABLE kLoopEnd. kLoopLen = kLoopEnd - kLoopBeg ;DERIVE LOOP LENGTH FROM LOOP START AND END POINTS kPlayPhasFrq divz gkSpeed, (kLoopLen/sr), 0.00001 ;SAFELY DIVIDE, PROVIDING ALTERNATIVE VALUE INCASE DENOMINATOR IS ZERO aPlayNdx phasor kPlayPhasFrq ;DEFINE PHASOR POINTER FOR TABLE INDEX kLoopBeg = (kLoopBeg < kLoopEnd ? kLoopBeg : kLoopEnd) ;CHECK IF LOOP-BEGINNING AND LOOP-END SLIDERS HAVE BEEN REVERSED aLoopLen interp abs(kLoopLen) aLoopBeg interp kLoopBeg aPlayNdx = (aPlayNdx*aLoopLen) + aLoopBeg ;RESCALE INDEX POINTER ACCORDING TO LOOP LENGTH AND LOOP BEGINING ; scruber Sscruber sprintfk "scrubberposition(%d, %d), tablenumber(%d)", k(aPlayNdx), k(gistorageL), k(gistorageL) chnset Sscruber, "gentable" aL tablei aPlayNdx, gistorageL ;READ AUDIO FROM AUDIO STORAGE FUNCTION TABLE aR tablei aPlayNdx, gistorageR ;READ AUDIO FROM AUDIO STORAGE FUNCTION TABLE outs aL*gkOutGain,aR*gkOutGain ;SEND AUDIO TO OUTPUTS SKIP_PLAY_LOOP: endin ;causes Csound to run for about 7000 years... f0 z ;starts instrument 1 and runs it for a week i "GUI" 0 z ;i "setTable" 0 1