Cabbage Logo
Back to Cabbage Site

Record Buffer and return it's length

Hi all, I am writing to ask how can I record audio from a live input, store it in a buffer, and return the length of it? Now I am only to record sound into a fixed length table, which has silence remaining in the buffer if the recorded time is smaller then the table length. I am hoping to using a button to toggle start and stop recording, with the buffer length changeable according to the recording time. Is that achievable?

Yes. All you need to do is store the number of samples you have recorded. If you post your code we can modify it to do this.

Hi Rory, thank you very much for the reply! I am using several UDO opcodes I found. I use BufCt1 for creating buffer, BufRecord1 for recording, and BufPlay1 for playing. It maybe not be a convenient way of doing record and play, Do you have better solution on that? Here is the code:

     opcode BufCt1, i, io
ilen, inum xin
ift        ftgen     inum, 0, -(ilen*sr), 2, 0
           xout      ift
  endop

  opcode BufRec1, k, aikkkk
ain, ift, krec, kstart, kend, kwrap xin
		setksmps	1
kendsmps	=		kend*sr ;end point in samples
kendsmps	=		(kendsmps == 0 || kendsmps > ftlen(ift) ? ftlen(ift) : kendsmps)
kfinished	=		0
krec		init		0
knew		changed	krec ;1 if record just started
 if krec == 1 then
  if knew == 1 then
kndx		=		kstart * sr - 1 ;first index to write minus one
  endif
  if kndx >= kendsmps-1 && kwrap == 1 then
kndx		=		-1
  endif
  if kndx < kendsmps-1 then
kndx		=		kndx + 1
andx		=		kndx
		tabw		ain, andx, ift
  else
kfinished	=		1
  endif
 endif
 		xout		kfinished
  endop

  opcode BufPlay1, ak, ikkkkkk
ift, kplay, kspeed, kvol, kstart, kend, kwrap xin
;kstart = begin of playing the buffer in seconds
;kend = end of playing in seconds. 0 means the end of the table
;kwrap = 0: no wrapping. stops at kend (positive speed) or kstart (negative speed). this makes just sense if the direction does not change and you just want to play the table once 
;kwrap = 1: wraps between kstart and kend
;kwrap = 2: wraps between 0 and kend
;kwrap = 3: wraps between kstart and end of table
;CALCULATE BASIC VALUES
kfin		init		0
iftlen		=		ftlen(ift)/sr ;ftlength in seconds
kend		=		(kend == 0 ? iftlen : kend) ;kend=0 means end of table
kstart01	=		kstart/iftlen ;start in 0-1 range
kend01		=		kend/iftlen ;end in 0-1 range
kfqbas		=		(1/iftlen) * kspeed ;basic phasor frequency
;DIFFERENT BEHAVIOUR DEPENDING ON WRAP:
if kplay == 1 && kfin == 0 then
 ;1. STOP AT START- OR ENDPOINT IF NO WRAPPING REQUIRED (kwrap=0)
 if kwrap == 0 then
kfqrel		=		kfqbas / (kend01-kstart01) ;phasor freq so that 0-1 values match distance start-end
andxrel	phasor 	kfqrel ;index 0-1 for distance start-end
andx		=		andxrel * (kend01-kstart01) + (kstart01) ;final index for reading the table (0-1)
kfirst		init		1 ;don't check condition below at the first k-cycle (always true)
kndx		downsamp	andx
kprevndx	init		0
 ;end of table check:
  ;for positive speed, check if this index is lower than the previous one
  if kfirst == 0 && kspeed > 0 && kndx < kprevndx then 
kfin		=		1
 ;for negative speed, check if this index is higher than the previous one
  else
kprevndx	=		(kprevndx == kstart01 ? kend01 : kprevndx) 
   if kfirst == 0 && kspeed < 0 && kndx > kprevndx then
kfin		=		1
   endif
kfirst		=		0 ;end of first cycle in wrap = 0
  endif
 ;sound out if end of table has not yet reached
asig		table3		andx, ift, 1	
kprevndx	=		kndx ;next previous is this index
 ;2. WRAP BETWEEN START AND END (kwrap=1)
 elseif kwrap == 1 then
kfqrel		=		kfqbas / (kend01-kstart01) ;same as for kwarp=0
andxrel	phasor 	kfqrel 
andx		=		andxrel * (kend01-kstart01) + (kstart01) 
asig		table3		andx, ift, 1	;sound out
 ;3. START AT kstart BUT WRAP BETWEEN 0 AND END (kwrap=2)
 elseif kwrap == 2 then
kw2first	init		1 
  if kw2first == 1 then ;at first k-cycle:
		reinit		wrap3phs ;reinitialize for getting the correct start phase
kw2first	=		0 
  endif
kfqrel		=		kfqbas / kend01 ;phasor freq so that 0-1 values match distance start-end
wrap3phs:
andxrel	phasor 	kfqrel, i(kstart01) ;index 0-1 for distance start-end
		rireturn	;end of reinitialization
andx		=		andxrel * kend01 ;final index for reading the table 
asig		table3		andx, ift, 1	;sound out
 ;4. WRAP BETWEEN kstart AND END OF TABLE(kwrap=3)
 elseif kwrap == 3 then
kfqrel		=		kfqbas / (1-kstart01) ;phasor freq so that 0-1 values match distance start-end
andxrel	phasor 	kfqrel ;index 0-1 for distance start-end
andx		=		andxrel * (1-kstart01) + kstart01 ;final index for reading the table 
asig		table3		andx, ift, 1	
 endif
else ;if either not started or finished at wrap=0
asig		=		0 ;don't produce any sound
endif
  		xout		asig*kvol, kfin
  endop


instr 1 ;creates the buffer and using button to create record and play event
	iSwitchPin1 init 0
	iLED_Pin1 init 1
	
kSwitch1 digiInBela iSwitchPin1
digiOutBela kSwitch1, iLED_Pin1
	
gibuf     BufCt1    10 ; **Create buffer of 10 seconds**

 ; If Button Pressed, call Recording 
gkRecord = kSwitch1
if changed(gkRecord) == 1 then
	prints    "PRESS THE button FOR RECORDING!\n"
	event     "i",2,0,-1
	
endif

;If button pressed, call Playing    
iSwitchPin2 init 2
iLED_Pin2 init 3

kSwitch2 digiInBela iSwitchPin2

gkPlay = kSwitch2
gkOnOff init 0 

kTrig trigger gkPlay, .5, 0
if  kTrig == 1 then
    gkOnOff += 1
endif

if changed(gkOnOff) == 1 then
	if  gkOnOff == 1 then
		prints    "PRESS THE button FOR PLAYING!\n"
		event     "i",3,0,-1
	else
		turnoff2 2, 1, 2
        gkOnOff = 0
    endif
endif

digiOutBela gkOnOff, iLED_Pin2	
endin

instr 2 ;Using BufRec1 for recording
krec      init      0 ;reset krec for multiple triggering
ain       inch      1 ;audio input from channel 1
kplay     BufRec1   ain*0.5, gibuf, krec, 0, 0, 0 ;record buffer without wrap
krec      =         1
endin

instr 3; Using BufPlay1 for playing
aout,k0   BufPlay1  gibuf, gkOnOff, 1, 0.5, 0, 0, 1 ;play back buffer
          out       aout
endin

It looks like this might work (warning: untested!)

Add this to the start of instr 2:

gkend timeinsts

That should save the recording time to a global gk variable. Then pass that to instr 3:

instr 3; Using BufPlay1 for playing
aout,k0   BufPlay1  gibuf, gkOnOff, 1, 0.5, 0, gkend, 1 ;play back buffer
          out       aout
endin

It looks like the playback opcode is already set up to accept the end time variable in seconds.

I think… :roll_eyes:. I hope… :laughing: