Embed Simreps?

So I recently stumbled across a hard limit to the simrep command (and assume a similar limit is on seqrep). It seems that it cannot repeat more than 128-ish times before hitting a Stack Overflow. I know it’s a limit to the command itself rather than the content it tries to combine because I’ve tested this with combining 128 tiny snippits of audio (about 0.5 sec in length each) and larger sections (about 5 seconds each) and they both function perfectly up until they hit the 128th rep and send out a Stack Overflow error.

The question I had was, is it possible to bypass this limit? Such as, as an example, embedding a function that calls different simreps within one large simrep? Like let’s say, instead of trying to combine 200 audio pieces in a single simrep, you instead combine 50 pieces with 4 different simreps, then combine those 4 pieces with one final simrep. Or is there simply a programming limitation here that I’m missing?

For reference, I’m using a plug-in to add a beat of silence between every beat of a song. Seeing as songs can have hundreds of beats, or more if it’s fast/long enough, it’s annoying to have to repeat the plug-in every 128 beats instead of simply highlighting the whole song and applying it once. If I could embed simreps, the beat limit would increase from 128 to 128*128 or 16384, a limit I’m unlikely to hit anytime soon.

Thank you in advance! :smiley:

Yes it is possible to bypass the limit.

Example:
Rather than:

(defun small-sig()
;just an arbirary sound
  (mult 0.005 (hzosc (+ 100 (random 900)))))

(simrep (j 200)(small-sig)) ;error: argument stack overflow

we can do:

(defun small-sig()
;just an arbirary sound
  (mult 0.005 (hzosc (+ 100 (random 900)))))

(do ((j 0 (1+ j))
     (sig (small-sig)(sum sig (small-sig))))
    ((= j 200) sig))

Ah! A Do loop! Thank you! I’m still rather fresh to nyquist in general so I had assumed Sim and Seq were pretty much the only ways to combine sound in the manner I was thinking. The fact that a simple Sum can do so as well could really open a lot of doors for me.

The only issue I had was the fact that I needed to pass along the counter (in your case, the variable ‘j’) to the function I used to segment the track (the equivalent of your ‘small-sig’) but when I did something like:

(do ((j 0 (1+ j))
     (sig (small-sig j)(sum sig (small-sig j))))
    ((= j 200) sig))

It somehow passed along ‘0.5’ through ‘j’ during execution. Fortunately simply adding a ‘(setf j (truncate j))’ to the first line of my function fixed the issue and the final result comes out perfect.

Thank you again!

SIM and SUM are equivalent. They both “add”.
They differ from “+” in that they can operate on sounds (and multi-channel sounds), whereas “+” only works with numbers.

An alternative to using SEQ is to use SIM (or SUM) with “AT” (http://www.cs.cmu.edu/~rbd/doc/nyquist/part8.html#index583)

Example - a sequence of three tones, each of length 1.5

(defun generate()
;An arbirary behaviour returning a sound
  (osc (+ 60 (random 20)) 1.5))

(seq (generate)(generate)(generate))

or

(defun generate()
;An arbirary behaviour returning a sound
  (osc (+ 60 (random 20)) 1.5))

(sim
  (generate)
  (at 1.5 (generate))
  (at 3 (generate)))

or

(defun generate()
;An arbirary behaviour returning a sound
  (osc (+ 60 (random 20)) 1.5))

(sum
  (generate)
  (at 1.5 (generate))
  (at 3 (generate)))

Time shifting sounds can sometimes be tricky. For example, if you want to shift the selected track audio, you may be tempted to think that this will work (it won’t):

(at-abs 0.5 *track*)

The first problem is that track is a sound, not a behaviour.
track already has a start time at 0, so the above will give the error:

Warning: cannot go back in time to 0, sound came from *TRACK*

This first problem may be resolved by using “CUE” (http://www.cs.cmu.edu/~rbd/doc/nyquist/part8.html#index344). In effect, CUE causes Nyquist to treat sounds as behaviours.
Our next attempt might be something like:

(at-abs 0.5 (cue *track*))

This fixes the error, but it still does not shift the selected audio. The reason that it still does not work is because we are not only dealing with Nyquist - we are dealing with Nyquist in Audacity. Nyquist is a separate program from Audacity, and all that they know of each other is the data that they pass from one to the other. In the above code, Audacity passes the selected sound to Nyquist in the variable *track", and Nyquist passes the audio back to Audacity as its return value, but Audacity has no knowledge of Nyquist’s local environment, so it knows nothing of the time shift in Nyquist.

To make it work, we need Nyquist to return not only the (shifted) sound, but also a reference for time=0. We can do this by creating a null sound at time = 0, and the (shifted) track sound at time = 0.5

(sim
  (s-rest 0)  ;a null sound at time=0
  (at-abs 0.5 (cue *track*)))

You can find a couple of examples of time shifting sounds in the included plug-ins rhythmtrack.ny and delay.ny