Nyquist Ripping Stems from Stereo Loop Using Labels

Audacity Version: 3.1.3
Windows OS: Windows 10 Pro

I’ve read around on https://audionyq.com/ , https://www.cs.cmu.edu/~rbd/doc/nyquist/index.html , https://manual.audacityteam.org/index.html. Ordered from most helpful to least.

I have a project which uses a looper and adds a new instrument in subsequent loops over time.
I have been able to successfully rip the stems out of the loop manually by using Audacity functions. To put it simply I…

  1. Copy the first loop.
  2. Paste onto a separate stereo track
  3. Align the pasted first loop with the second loop
  4. Invert the material
  5. Check the alignment by having both unmuted creating close to silence depending on static from recording quality and alignment.
  6. Track >> Mix >> Mix and Render to New Track
  7. …Rinse and repeat

So long as the first loop is aligned (almost) perfectly then the remaining ones will always be aligned.

I can do this alignment setup on the audio in advance and later work toward automating it. I’m not worried yet about the alignment.

For now let’s assume I have the audio aligned, each loop split into its own clip in the track as shown in the following image.
AudacityManualStemRemoval.PNG
I’d like to make a Nyquist plugin to do most of the work for me since it’s a bunch of rinse and repeat iteration after the first alignment.


To breakdown the project I need to:

  1. REPEAT AUDIO ***

  2. CUMULATIVELY ADD INVERTED AUDIO

  3. ^^^ READ AND INTERPRET LABELS ^^^

  4. REPEAT AUDIO ***

This is the main operation.
I haven’t found a straightforward way to do this yet.
I can mess with the entire track but I have yet to figure out copying specific areas.

I think the most ideal way to do this is to use the track-clips since I can split the main train and get clip data. However I’ve been having difficulty with converting clips and I’m starting to wonder if a clip is just a list of a start and end time (since that is what is returned) and maybe there is another way to extract(?) the audio between those times.

I can select the entire track and easily make sure the loop starts at time 0 (even though it has a preceding silence as seen in the image) That may help if I can get specific sections of audio within track.

  1. CUMULATIVELY ADD INVERTED AUDIO

After knowing how to capture specific segments of audio. I imagine this is the “easiest” part.

I want a variable that stores the inverted audio together and gets used to “rip” the stems from the loop. I’ve been manually using ~Tracks >> Mix >> Mix and Render to New Track~ and removing a single stem from the loop as I worked through it.

  1. ^^^ READ AND INTERPRET LABELS ^^^

This is the brains of the operation.
I’ll be typing the labels manually in advance as seen in the image.

However each loop has to only rip the stems out from whatever audio is within the labels.
A label seems to have three properties. Start, End, StringName.

Here the labels may be within a single loop instance (e.g. “flute”, “kazoo”, “choir”) or span over a few (e.g. “strings2”, “trumpets”, “piano2”). It is rare that a label will be exactly the same length of the loop (e.g. “piano”, “strings”).

As the loop is generated, a second addition may not happen until a few go arounds of the loop.
To put another way: using the image as an example. The first clip is silence. The second clip is the loop segment. The third clip doesn’t add anything to the loop since there are no labels, so nothing is “CUMULATIVELY ADD INVERTED AUDIO” until the fourth clip with the strings label.

To put yet another way: What will be cumulatively added in #2 (“CUMULATIVE ADD INVERTED AUDIO”) should be only what is within the labels. Silence can be used to pad whatever is not there.


EXPECTED RESULTS:

I’m hoping that once I run the plugin I will obtain each stem.

That may be simply that the original track overwritten with the sound data of what was cumulatively added to the inverted audio…

Or, what I think is more advanced, each audio which was added cumulatively - as a separate track.

THAT’S ALL…
At which I export multiple files and import each into a DAW to mix together in a different way.

I understand that doing this I’m losing small artifacts depending on my recorded samples especially as I include instruments within similar stereo frequencies. I’ve plans to polish the sound afterwards.

I’ve considered using the “AUD-DO” command but that feels unnecessary.


HERE’s WHAT I HAVE ALREADY:
But I’m not against scrapping it.

NOTE: I’ve been doing my tests and learning on mono tracks knowing that I’ll have to do some work to get it using stereo. I’d prefer stereo.

I’m struggling with understanding:

  • Getting specific areas of audio
  • I’m misunderstanding the “extract-abs”
  • I’m misunderstanding the “(s-rest 0)” function.
  • I’m not understanding the “clip” data properties and how to use them in sim.


;;NOTE WORKS ONLY WITH MONO TRACKS SO FAR
;;Find clips
(setf track-clips (get '*track* 'clips))
(setf start (get '*selection* 'start))

;; Calculate the number of sounds in the selection.
(setf cliplength (get-duration 1))
(setf repeatamount 6)
(print cliplength)
(setf total 360)  ;total length required (seconds)


;; repeats the track a repeatamount number of times
;;
;;
(let 		(
			(sounddata (snd-copy *track*))
		)
		;;Not entirely certain about extract-abs but otherwise returns nil.
		;;Might use the absolute environment?
	(extract-abs 0 (mult repeatamount cliplength)
		(let 
			;;Set variables
			(
				(loopoutput (s-rest 0))
			)
			;;Loop through time
			(dotimes (i total loopoutput)
				;;Add to output of loop the same sound starting at an absolute
				;;position but relative to the selection? Since abs-env was not
				;;used maybe this goes through the whole signal with the offset
				;; already accounted for?
				(setf loopoutput 
					(sim loopoutput 
						(at-abs 
							(* i cliplength) 
							(cue sounddata)
						)
					)
				)
			)
		)
	)
)

Two ways. The choice between the two depends on what you are doing in the rest of the code.

  1. Pure Nyquist
(let ((snd *track*))
  (seqrep (i 9) (cue snd)))

The first line makes a local copy of the selected sound (from track).
The second line evaluates “(cue snd)” iteratively. “i” is the loop counter. “CUE” allows the start time of the sound “snd” to be reset.

We can’t use track directly in SEQREP due to an implementation detail in SEQREP. If we try to use it like this: (seqrep (i 9) (cue track) we get an error because track is garbage collected after the first evaluation. The first line “(let ((snd track))” retains the sound, bound to “snd” within the scope of the LET block.


  1. Scripting commands
    Rather than manipulating the sound directly in Nyquist, Nyquist can send “scripting / Macro” commands to Audacity that tell Audacity to do things. Nyquist plug-ins that work this way are called “Nyquist Macros”. More info here: Nyquist-Macros - Audacity Manual

Nyquist can access Audacity’s Macro commands (see: Scripting Reference - Audacity Manual) using “AUD-DO”.
Any of the macro commands may be used except for Nyquist plug-ins.

From the scripting reference:

Repeat: | Repeat… | int Count, (default:1) | Repeats the selection the specified number of times.

Nyquist can tell Audacity to apply the “Repeat” effect like this:

(aud-do  "Repeat: Count=9")

but note that “AUD-DO” returns a list, which we don’t want to return to Audacity (because Audacity does not know what to do with it), so we should ensure that the Nyquist code returns a valid value.

Nyquist Macros commonly return an empty string to Audacity. Audacity sees an empty string as a valid value, so there’s no error, and ignores it. In other words, an empty string is a “No-Op” (does nothing).

Running this in the Nyquist Prompt tells Audacity to repeat the selected audio 9 times, and returns an empty string.

(aud-do  "Repeat: Count=9")
""

When writing a Nyquist plug-in, it can either be a “normal” plug-in where Nyquist modifies the audio, or “Nyquist Macro” where it is Audacity that modifies the audio. It is generally not possible to mix the two approaches in the same plug-in.

I think that a “Nyquist Macro” will probably be the best approach.

Normal Nyquist effects can only access the audio that is selected at the time that the effect is launched, but you are wanting to act on one selection, then another, then another …

This is a bit tricky because Nyquist cannot directly access label tracks.

The way to do it is to use the macro / scripting command “GetInfo:”
You can test this command from Audacity’s “Extra” menu (Extra Menu - Audacity Manual)

“Extra menu > Scriptables II > Get Info…”

The GetInfo: command is documented in the Scripting Reference: Scripting Reference - Audacity Manual


We could use (aud-do “GetInfo: Type="Labels" Format="LISP"”)
For example:

(setf info (aud-do "GetInfo: Type=\"Labels\" Format=\"LISP\""))

(format nil "~a" info)

but the return data is a list in the form:
(“label-data” . t)
where “label-data” is a string.

For example, I have a project with two labels, and GetInfo: Type=“Labels” Format=“LISP” returns:

(((1
    ((0.278981 0.416561 "label 1")
      (0.643312 0.761783 "label 2")))) . T)

The first “1” indicates that it is the first label track,
(0.278981 0.416561 “label 1”) is the first label,
(0.643312 0.761783 “label 2”) is the second label.

Parsing this is a pain in the neck because

((1
    ((0.278981 0.416561 "label 1")
      (0.643312 0.761783 "label 2"))))

is a string (text) and not an actual list.


Fortunately there is an alternative to using AUD-DO in this case, which does a lot of the work for us. This is the higher level “AUD-GET-INFO” info command: Nyquist-Macros - Audacity Manual

There’s an example of using AUD-GET-INFO here: https://audionyq.com/label-track-info/

Thanks Steve for all your suggestions and support (and keeping the thread open for me to try things out). I spent some time digesting and trying things out with the added assistance.
Here is an update on my progress/attempts…

I was trying to access data outside of the original selection (as you noticed) which may be the real challenge instead of actually repeating the audio.
I did not yet try using the AUD-DO command to reselect part way through the script.


From your suggestion I decided to make a macro of it in Audacity first and then convert that to a Nyquist Macro.

Here is the Audacity Macro exported:

Repeat:Count="10"
Invert:Use_Preset="<Factory Defaults>"
ShiftUp:
MixAndRenderToNewTrack:
PrevTrack:
Toggle:
PrevTrack:
Toggle:
LastTrack:
Toggle:
CursorRight:
MoveToNextLabel:
MoveToNextLabel:
MoveToNextLabel:

SplitNew:
NewMonoTrack:
MoveToPrevLabel:
Silence:Use_Preset="<Current Settings>"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
TrackClose:
PrevTrack:
TrackClose:
LastTrack:
Toggle:
Repeat:Count="10"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
PrevTrack:
TrackClose:
Toggle:
LastTrack:
Toggle:
MoveToNextLabel:
MoveToNextLabel:
MoveToNextLabel:

SplitNew:
NewMonoTrack:
MoveToPrevLabel:
Silence:Use_Preset="<Current Settings>"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
TrackClose:
PrevTrack:
TrackClose:
LastTrack:
Toggle:
Repeat:Count="10"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
PrevTrack:
TrackClose:
Toggle:
LastTrack:
Toggle:
MoveToNextLabel:
MoveToNextLabel:
MoveToNextLabel:

SplitNew:
NewMonoTrack:
MoveToPrevLabel:
Silence:Use_Preset="<Current Settings>"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
TrackClose:
PrevTrack:
TrackClose:
LastTrack:
Toggle:
Repeat:Count="10"
PrevTrack:
Toggle:
MixAndRenderToNewTrack:
PrevTrack:
PrevTrack:
TrackClose:
Toggle:
LastTrack:
Toggle:
MoveToNextLabel:
MoveToNextLabel:
MoveToNextLabel:

I could not find a “way to loop” sections of the macro N times using the built-in “Macros…” managing tool so I used the samples and resources you provided to do just that in a Nyquist Macro along with a simple control menu.

Here is roughly the same macro but translated to a Nyquist Macro using the Nyquist Prompt and AUD-DO command:

;nyquist plug-in
;version 4
;type tool
;name "OutSTEMming RIP From Loop"
;author "A Cat"
;release 3.1.3

;control numberofloopsinaudio "Number of Loops in Recording" int " --- " 27 0 50
;control numberoffunctionrepeats "Unique Label of Stem Amount " int " --- " 10 0 25

(aud-do  (format nil "Repeat: Count=~S" numberofloopsinaudio))
(aud-do  "Invert:Use_Preset=<Factory Defaults>")
(aud-do  "ShiftUp:")
(aud-do  "MixAndRenderToNewTrack:")
(aud-do  "PrevTrack:")
(aud-do  "Toggle:")
(aud-do  "PrevTrack:")
(aud-do  "Toggle:")
(aud-do  "LastTrack:")
(aud-do  "Toggle:")
;(aud-do  "CursorRight:")

(let (
		(repeattimes numberofloopsinaudio )
	)
	
	(dotimes (i numberoffunctionrepeats)
		(setf repeattimes
			(- repeattimes 1)
		)

		(aud-do  "MoveToNextLabel:")
		(aud-do  "MoveToNextLabel:")
		(aud-do  "MoveToNextLabel:")
		(aud-do  "SplitNew:")
		(aud-do  "NewMonoTrack:")
		(aud-do  "MoveToPrevLabel:")
		(aud-do  "Silence:Use_Preset=<Current Settings>")
		(aud-do  "PrevTrack:")
		(aud-do  "Toggle:")
		(aud-do  "MixAndRenderToNewTrack:")
		(aud-do  "PrevTrack:")
		(aud-do  "TrackClose:")
		(aud-do  "PrevTrack:")
		(aud-do  "TrackClose:")
		(aud-do  "LastTrack:")
		(aud-do  "Toggle:")
		(aud-do  "Invert:Use_Preset=<Factory Defaults>")
		(aud-do  (format nil "Repeat: Count=~S" repeattimes))
		(aud-do  "PrevTrack:")
		(aud-do  "Toggle:")
		(aud-do  "MixAndRenderToNewTrack:")
		(aud-do  "PrevTrack:")
		(aud-do  "PrevTrack:")
		(aud-do  "TrackClose:")
		(aud-do  "Toggle:")
		(aud-do  "LastTrack:")
		(aud-do  "Toggle:")
	)
""
)

(print "COMPLETED")

They both work (from my designated starting point), but the Nyquist Macro allows for me to loop sections of the Macro functions easily.
I then performed the same operations on the same sample data using both the Audacity Macro (68seconds) and the Nyquist Macro (161seconds). The Nyquist Macro was 2.367x times slower.

This gif is at 10x speed using the Audacity Macro.
https://drive.google.com/file/d/1QQz9B-sh5QbHkgC-NtXKIA7PNKJPdE87/view?usp=sharing

I predict this time difference has something to do with Audacity caching AUD-DO commands as memory allocation when using the Nyquist Prompt. It is a noticeable difference however the process still worked on the sample data and was automated. So I consider it acceptable as a solution.
I have yet to apply it to larger audio data.

I do receive these WARNING MESSAGES though it does not stop the process:
AudacityErrorModuleNotFound.PNG
.
https://drive.google.com/file/d/1QQz9B-sh5QbHkgC-NtXKIA7PNKJPdE87/view?usp=sharing
To do this successfully I was using a single label track seen briefly at the start and top of the gif linked directly above.


In general the macro:

  1. Navigates to the label that spans the section of the next stem-instrument
  2. Splits it onto another track
  3. Creates another (mono) track
  4. Selects the wider label which represents the loop segment
  5. Creates silence for that duration
  6. Combines the two newly made tracks
  7. Inverts the track
  8. Repeats the track N times
  9. Mix and renders the inverted stem out of the loop
  10. Rinse and repeat…

Step 1 and 4 are important in that process.
This procedure requires the labels to be all in one label track.

Originally I found through your “Export Labels” forum post (https://forum.audacityteam.org/t/export-labels/54745/1) that I could export and re-import labels to merge all the label tracks into one. Which turned out to be unnecessary as I can simply double-click to select a loop segment and use the hotkey Ctrl+B to create a label spanning the exact required location.



Which leads me to my next challenge.

Since I require the Step 6 Mix and Rendered track to be the same loop length of a loop for when it gets to be repeated in Step 8 I suppose that for most applications I could simply place a label of the loop “over top” the stem segment. In theory that would work however there are times when these labels would be butted-up together so my next step has become

Use the resources provided on label reading and creation - which, yes, seems to be a pain - to read all the labels and split any labels that span across two loop segments into two segments.
You may be able to see what I’m suggesting in the following picture:
AudacityAlignmentSummary.PNG
.
After that I believe I can focus on the original assumption in the first post which is aligning the track at the start (which has been done manually so far). In summary for that the process will be to shift samples and take the shifted position where the subtraction of the two audio signals produce the lowest result. Then find the length of the loop by comparing and aligning with a third loop iteration.
AudacityCreateAndSplitLoopLabels.PNG

This first reply basically confirms your observations.
I’ll look at the “next challenge” separately.

Nyquist itself can only access the audio that is selected at the time that the script is launched.

To access audio outside of the selection you must use Macro / Scripting commands (which are “Audacity” commands rather than “Nyquist” commands).


That’s correct. Macros don’t do looping, or any kind of branching, or any other kind of logical operations. Audacity’s “normal” macros are just a list of commands that run in sequence from the first command to the last.

“Nyquist Macros” can do looping, branching, many sorts of logical operations, and can access most of Audacity’s macro commands (all except for Macro commands that run Nyquist scripts).


I’ve also noticed that Nyquist macro commands are rather slow. I don’t know why, other than it is an implementation issue in Audacity. My guess is that Audacity waits a short while after each command before accepting the next, but that’s just a guess.


The first line (“Context was passed in, but was ignored …”) is not an error. That’s normal when running Nyquist macro commands. I guess it was a debugging message that was added during the development of the Nyquist “AUD-DO” functionality.

The “Failed to load” messages about “avformat-58.dll” are created when Audacity starts up. Audacity is looking for the optional FFmpeg library. Audacity looks in several possible locations, and issues a “Failed to load …” message for each failed attempt to find FFmpeg.

The FFmpeg library is optional. If available to Audacity, it allows Audacity to import and export additional audio formats including M4A (AAC), AC3, AMR (narrow band) and WMA and also to import audio from most video files.

More information about installing FFmpeg for Audacity (Windows) here: Installing FFmpeg for Windows - Audacity Manual

This will be tricky to automate.

The problem is that the Nyquist plug-in must be either “normal” Nyquist code (where Nyquist accesses and manipulates the audio) or a Nyquist Macro (where the project is accessed / manipulated by Audacity). Generally you can’t mix the two in the same plug-in.

While Audacity can make copies and do the subtraction (invert one track and mix), Audacity does not have tools for measuring the resulting level - you would need to do that with a “normal” Nyquist effect.

The two major limitations of Nyquist macros:

  1. When using macro commands to modify the project, you can’t modify the project with Nyquist.
    “;type tool” plug-ins don’t even get access to track.

  2. Nyquist cannot call a Nyquist plug-in with macro commands.
    Example:
    With a normal Macro, you can call the High-Pass Filter (a Nyquist effect) with:

High-passFilter:frequency="1000" rolloff="dB48"

but if you try this from Nyquist:

(aud-do "High-passFilter:frequency=\"1000\" rolloff=\"dB48\"")
""

nothing happens - the command is not allowed and is ignored.


I don’t know off hand whether it is appropriate for your use case, but one workaround that I’ve used when automating a task that requires both “normal” Nyquist processing and “Nyquist Macro” processing, is to put the “normal” Nyquist processing into one plug-in, and write the Nyquist Macro as another plug-in. Then run the two plug-ins in sequence by adding them both to a normal Audacity Macro.

If it’s necessary to pass information from one plug-in to the other, then SCRATCH can be used (See: Missing features - Audacity Support)

I want to take a deeper dive into the Label examples posted at a later time, including https://audionyq.com/find-label-plug-in/

Here was a gentle attempt at reading the label data.

(dotimes (i alllabels *labels*)
	(setf singlelabeln (i alllabels))
	(dotimes (i2 singlelabeln)
		(print i2)
;		(print (first i2))
;		(print (second i2))
;		(print (third i2))
	)
	
)

The irony I found with this is that “printing” the labels in the loop resulted in the same as a “push” function and never printed the labels to the Audacity Log. Perhaps I have to specify using the debug for it to show. Not sure why. There is an offset too which I could fix from some other code but it’s simple enough to go to the start of the track.
AudacityCreateAndSplitLoopLabels.PNG
For the time being I’ve found a workaround procedure I’m willing to entertain before developing a Nyquist script to do the label splitting.

That procedure is as follows:

  • Export existing labels as a backup
  • Create Side 1 by selecting loop labels and using the split deletion method to remove one half of the label (Ctrl+Alt+K)
  • Export the labels as Side 1
  • Import the backed up labels from Step 1
  • Create Side 2 by selecting loop labels and using the split deletion method to remove the other half of the labels (Ctrl+Alt+K)
  • Export the labels as Side 2
  • Import Side1 labels and Side2 labels
  • Export labels again to merge all labels
  • Import as one label track.

Moving onward for now…

Thinking to tackle the alignment as things go.
From your feedback on the challenges associated with aligning here’s my thoughts.
AudacityFindAMarkerDBInRegion.PNG
Part 1 >> Instead I may be able to select parts of the audio and run a Nyquist script which tells me the highest dB in the selected range or at least the starting dB

Part 2 >> I can then use another Nyquist script on another portion of the audio and search for either exact or almost exact dB that match a user inputed and add a label to be output at the various locations that dB is reached.

Part 3 >> I can potentially use a Normalize or Amplify effect to help bring something to light in the audio.

There may be some sample-rate issues at higher than 44100 Hz. I have been using 384000 Hz (maximum) but that should be tweakable.


I am trying to review and augment the following code to do something like the Part 1:
(Original source: https://audionyq.com/how-to-detect-a-sound-in-just-a-few-lines-of-code/)

This is a first attempt and it currently fails:

(setf highdB 5)
(setf lowdB 3)
(let 
	(num)
	
	(setf num
		(do ((j 0 (1+ j)))
			(
				(if (and (< highdB (snd-fetch *track*))
							(> lowdB (snd-fetch *track*)))
							
					t
					(not t)
				j)

			)
		)
	)

	(list (list (/ (- num 0.5) *sound-srate*) "Start"))
)

Actually, PRINT does print to the Audacity log.
To view the Audacity log: “Help menu > Diagnostics > Show Log”

And here’s some code to print the text of each label into the log:

(setf all-label-tracks (aud-get-info "Labels"))


;; Iterate through "all-label-tracks" and return "Done" on completion.
(dolist (label-track all-label-tracks "Done")
  ; First element of the label track is the track number
  (setf track-num (first label-track))
  ; Second element of the label track is the list of labels
  (setf labels (second label-track))

  ;; Now iterate through the list of labels
	(dolist (label labels)
		; Third element of the label is the label text.
    (print (third label))))

Note that Audacity’s log mirrors Nyquist’s “debug” output, so you have two ways to view the printed statements - either by running the Nyquist code with the “Debug” button (the debug window pops up on completion), or by looking in Audacity’s log.


In Audacity, Nyquist’s PRINT function prints to the Audacity log / Debug output, and returns the argument passed to PRINT.
Example:

(print "Hello")
(print "World")

Note that “Hello” and “World” are both printed to the Audacity log / Debug out.
The first line prints “Hello” and returns “Hello”, but the return value is just garbage collected because we do nothing with it.
The second line prints “World” and returns “World”. Because this is the final return value in the script, this value is returned to Audacity, and because it is a string value, Audacity displays it in a message window.

(See also this short section about “return values” from Nyquist scripts: Missing features - Audacity Support)

If we want Audacity to display both “Hello” and “World”, we would need to collect the return value from (print “Hello”)

(setf mystring1 (print "Hello"))
(setf mystring2 (print "World"))
; concatenate the two strings and return to Audacity
(strcat mystring1 mystring2)

“Brief” update:

I’ve been able to test on one live data.

I want to politely reiterate that for whatever reason “printing” within a loop label values just assigns labels to a new label track.
So although the expected behaviour is to print to the Audacity log it actually, in practice, pushes labels onto a new label track. Weird and unexpected, I do not know why. I suspect some quirky bug. Maybe something is off with my version.

I have been using the largest sampling rate of 384000 Hz which leads to large file sizes and slow down on functions (i.e. Mix and Render). I was encountering data size challenges because of this. Using Steve’s response on the forum found and pasted from here (Enormous file sizes - #9 by steve) and someone else noting that my project rate really only needs to be 48000 Hz saving much desired time and storage. Thank you all.

Here is the text quoted:

It is normal and expected that AUP3 files will be big.
In older versions of Audacity, there was a separate “_data” folder that contained the audio data. That folder would grow very large due to the audio data.
In Audacity 3.x, the audio data is included in the AUP3 file.

On closing Audacity, unused “history” data should be automatically removed, and the saved AUP3 file should be approximately:
“4 x sample rate x number of channels” bytes per second of audio.
For example, 1 minute of 44100 Hz stereo audio would be approximately:
4 x 44100 x 2 x 60 = 21168000 = (approx) 21MB
In older versions of Audacity, the _data folder would be about 21 MB, plus a small .AUP file.
In current versions of Audacity, the AUP3 file will be about 21 MB.

This makes things more managable moving forward and the slow down rate of 2.3x using the Nyquist script less noticable since applying the totality of the effects has so far been under minutes.

The process stands as follows:


  1. Record & label the loop
  2. Find the start and loop length of the first loop iteration
  3. Resolve any labels to match a “standard” for the script/macro in the next step
  4. Apply the Nyquist script / Audacity Macro

Afterwards…
Another macro can be made to then align, normalize, and export the stems. Though this is fairly straightforward and hotkeyable by hand.

\


I think instead of checking for the alignment by trial&error I might be able to search for dB levels that “match” a pattern.

I’m thinking I’ll highlight a section and take things like the dB level of the first, last, and middle portion as well as the highest dB value within the highlighted portion and make a label for each.

Then highlight another portion and check for an area that “matches” those.
To start I’m going to simply aim for the “highest dB” to be labeled.




For the time being I’ve been able to reduce my process from 3-4 hours to 10 minutes or less which is a great boon. So aligning using a script is not right now something on my highest priority list. I want to test the process on more examples.
What I’m trying to say is I might not get to this post for another month as I do so.
We will see but thanks to this community (i.e. you, Steve) for all your support and direction.

Quick addendum from a quick search on the forum:

Will try using the find-peak.ny at this spot on the forum (https://forum.audacityteam.org/t/find-peak/54287/1)
Seems to do, generally, what I was hoping for - at least with finding the “highest dB” peak in a selected area.

Thank you again steve!