Looping Sections of an AudioBuffer

29 views
Skip to first unread message

George

unread,
Dec 6, 2025, 4:45:16 PM12/6/25
to Extempore
Andrew
I have not followed up on your suggestion of implementing a version of AudioBuffer_read but I followed your hint that "AudioBuffer_read_interp (and friends) look like they do".
In fact the read-interp version does exactly what I was looking for!
(I'll post the audio file below)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AudioBuffer_read_interp  has looping built-in

;; I opened the file "tmp/Tom&Greg_Devil_Deal.wav" in Audacity.app and found
;; starting points (frames) of 7 phrases
;; Laboriously copied the starting point and the length of each spoken phrase.
;; In xtlang I generated two vectors: one with 7 i64 integer starting points and
;; one with 7 i64 phrase lengths.
;; Then I randomly chose one of these starting points and the corresponding
;; phrase length.
;; Using AudioBuffer_set_loop_start and AudioBuffer_set_loop_frames I could
;; repeatedly play the selected phrase.

;; On re-evaluating the dsp:DSP code a different phrase may be selected and will
;; loop until another re-evaluation

(bind-func dsp:DSP
  (let ((ab dealWthDevl)
        (vStart:|7,i64|* (alloc))    ;; starting points (frames)
        (vFrame:|7,i64|* (alloc))    ;; representing loop-lengths (frames)
        (array-index (imp_rand1_i64 7)))   ;;
    (afill! vStart  24073 332207 505532 852183 1283089 1791028 2019721)
    (afill! vFrame  308134 175732 187769 334614 286468 113043 247951)
    (AudioBuffer_set_phase ab 0.0)
    (lambda (in time chan dat)
      (AudioBuffer_set_loop_start ab (aref vStart array-index)) ; silent pos
      (AudioBuffer_set_loop_frames ab (aref vFrame array-index)) ;; match length
      (AudioBuffer_read_interp ab (* 1.0 261.6) chan))))

(dsp:set! dsp)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

I have attempted to run a callback loop that re-evaluates the dsp:DSP code at regular intervals without success.
Also attempted to generate the arrays once only outside the dsp:DSP but ran into trouble with bad types.
Would appreciate some help with that.

Regards
George

George

unread,
Dec 6, 2025, 5:14:49 PM12/6/25
to Extempore
Andrew
The file is too big to post here.
I'll Try to find another way.
Or I could send it direct if you give me an address.
George

C K Kashyap

unread,
Dec 6, 2025, 8:04:16 PM12/6/25
to extemp...@googlegroups.com
To join the meeting on Google Meet, click this link: https://meet.google.com/jfu-hawj-dxm

Or open Meet and enter this code: jfu-hawj-dxm

--
You received this message because you are subscribed to the Google Groups "Extempore" group.
To unsubscribe from this group and stop receiving emails from it, send an email to extemporelan...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/extemporelang/9381681b-f050-4825-9998-f2d6348e7cebn%40googlegroups.com.

George

unread,
Jan 8, 2026, 8:13:07 PMJan 8
to Extempore

Hi all
I have worked out how to get the callback to retrigger the above dsp at regular intervals.
;; See for example:
;; https://github.com/digego/extempore/blob/81b1193dac2dd60f4cb51999c85a7cb9ce1f2bf0/examples/core/audio_101.xtm#L100
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; An xtlang function that changes the array-index function defined in the let in dsp:DSP
(bind-func change-index
  (lambda (array-index:i64)
    (dsp.array-index  (imp_rand2_i64 0 7)))) ; (imp_rand2_i64 0 7)

;; a "normal scheme" temporal recursion loop
;; for event level control

(define retrigger-loop
  (lambda (time index)
    (change-index
                  ($ (imp_rand2_i64 0 7)))
    ; (println (now))
    (callback time 'retrigger-loop (+ time (* 10 *second*)) 10))) ;; loop every 10 seconds

(retrigger-loop (now) ($ (imp_rand2_i64 0 7)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
In addition I have worked out how to avoid repeatedly creating and filling new arrays.
Now using halloc instead of alloc I build and fill the arrays just once outside the dsp.
;; Define phrase start positions and lengths using heap allocation for persistence
(bind-val phrase-starts |7,i64|* (halloc))
(bind-val phrase-lengths |7,i64|* (halloc))
($ (afill! phrase-starts 24073 332207 505532 852183 1283089 1791028 2019721))
($ (afill! phrase-lengths 308134 175732 187769 334614 286468 113043 247951))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(bind-func dsp:DSP
  (let ((ab dealWthDevl)
        ; (vStart:|7,i64|* (alloc))    ;; Don't need this now
        ; (vFrame:|7,i64|* (alloc))
        (array-index (imp_rand2_i64 0 7) ))   
    ; (afill! vStart  24073 332207 505532 852183 1283089 1791028 2019721) ;; already done
    ; (afill! vFrame  308134 175732 187769 334614 286468 113043 247951)

    (AudioBuffer_set_phase ab 0.0)
    (lambda (in time chan dat)
      (AudioBuffer_set_loop_start ab (aref phrase-starts array-index)) ;; a silent position
      (AudioBuffer_set_loop_frames ab (aref phrase-lengths array-index)) ;; phrase-length

      (AudioBuffer_read_interp ab (* 1.0 261.6) chan))))

(dsp:set! dsp)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

The complete file is on my Gists:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
The file "tmp/Tom&Greg_Devil_Deal.wav"  is too big to load here.
I can send it direct if anyone wants it.

However I think any wav audio file will do but you will have to do the work of gathering phrase data yourself.

Regards
George

Tim Roberts

unread,
Jan 9, 2026, 3:52:54 AMJan 9
to extemp...@googlegroups.com
Hey George,
While it’s hazy in my memory, this is something that I was dealing with in the TSM library. I remember getting confused because the function appeared to be processing each sample individually, but was actually being called on a buffer of samples.
Hopefully there’s enough documentation around my code for it to be useful. I think I ended up creating my own buffer that I would fill and draw from.
Cheers,
Tim

--
You received this message because you are subscribed to the Google Groups "Extempore" group.
To unsubscribe from this group and stop receiving emails from it, send an email to extemporelan...@googlegroups.com.

George

unread,
Jan 22, 2026, 11:57:02 PMJan 22
to Extempore

Thanks for the comment Tim
You were involved with the development stages of extempore well before me. I'm not familiar with the TSM library.
Maybe your work got absorbed in later work.

I have done some more work on dsp with random access to multiple buffers.

I intend to say something about it in a separate thread.

Regards
George
Reply all
Reply to author
Forward
0 new messages