I should start by saying I’m a hardware engineer turned sysadmin and project manager. I don’t make any significant claims of programming skills.
Prior to creating Acx-check by adapting code found in a number of other nyquist plugins, my lisp programming experience consisted of a couple of days of a programming course back in the 1970’s. I remember at the time that we all thought that the language was an interesting intellectual exercise but that no rational person would ever use it for a real task…
In any case I can happily add SND-SET-MAX-AUDIO-MEM to the code, reduce the “max-len” parameter or both and republish as version 3.1 if you like. The 100M sample limit that’s there now is nearly 40 minutes at 44.1kHz, and personally I don’t think this tool should be used on more than a short (less that 60 second) test. I think it was Koz who persuaded me to make it “as big as possible”. Any end user with the skills to run a text editor can easily increase the limit if desired.
If Steve can suggest nyquest code to find the “quietest 500ms” that doesn’t have the memory hogging issue I’m open to that as well. I’m pretty sure it not just that bit of code that has issues, I think the RMS code that is there has the same problem as well. I’ll also admit that I just looked at the code and have no idea what it is actually doing.
I tried to make it clear in the nodes on the Wiki page that this plugin is not a substitute for the ACX robot (never mind the ACX humans).
The problem as posted up the thread is an effective maximum limit under Audacity 2.4.1 of about 4 minutes. Not 45 minutes. So people are looking up from their hour-long read (ACX Maximum Chapter is 120 minutes) wondering what they’re going to do.
My suggestion is make it work as well as it used to. Because if we can’t do that, the only other option is that two-page long, detailed, step by step monster document I published. Or, of course, submit and wait two weeks…or longer.
“Audible/ACX is experiencing a high workload…”
republish as version 3.1 if you like.
3.0 is the Nyquist Version. The actual program will be Release 1.1, further down the code, next to the date and other release info. Hopefully, that red time-limit message will be obsolete.
This is the crucial question. How should the tool be used?
If, as you say, it should be used on short sections, then the the obvious quick fix is to reduce the “max-len” parameter.
Personally I’m not keen on “increasing SND-SET-MAX-AUDIO-MEM” as a solution because of the risk of crashing Audacity if the machine has insufficient free memory.
As you (flynwill) hint at, I’m also skeptical of the value in running this plug-in on very long selections. If I recall correctly, the code only looks for one quiet period in the selection. If the analysis is applied indiscriminately on a long track, the chance of getting a false “pass” result is high - even if the noise floor is too high in 99% of a long track, the analysis will show a “pass” if there is just half a second that meets the noise floor requirement.
As we now have a bug that needs to be fixed, I think we should take this opportunity to either modify the plug-in to suit the instructions, or modify the instructions to suit the plug-in. As you (Koz) have not only produced the documentation, but also field most of the questions about meeting ACX specifications, I’m happy for you to make this choice and either flynwill or myself will provide the code. What we need is a specification for what precisely this plug-in needs to do.
Ideally, it would replicate the efforts of The Robot at ACX without the two-week wait. But we only know what it’s doing by second-hand information, generic published specifications, and user experiences. ACX stopped talking to us when it became clear we didn’t care who owned the book or what the artwork looked like and they didn’t care which microphone we used.
There was one posting that suggested if you made it past publication rights and permissions issues, they had their own ACX Check they would allow us to use in semi-real time—without the two week wait. No further word on that. See: “ACX is swamped.” That’s still awkward and rights and permissions-based.
That wasn’t available when I submitted my reading. My reviewer was clear my submission was practically perfect in every way, but I can’t read out loud. No surprise there.
I can think of ways to fudge. They all leave a bad taste. Sample beginning, ending, and a mystery sample that wanders around the middle to keep people from gaming it.
There’s a developer solution. Who said it had to test the whole document in one sweep? Do it in chunks and make the performer wait. That’s still better than uploading and listing the rights-holder copyright information and dates every time.
We could take it upside down. Make the user drag-select which segment is to be tested. This, of course, without crashing like it does now. I don’t know of any existing, successful tool to use as a model.
I like that sample where the performer patched a small segment in the middle of a perfect reading with a trash reading. That’s rough to manage.
I’m looking a bit more closely at the code (and trying to re-learn Nyquist).
I see that a significant chunk of the code is inside a “progn” function, which the manual explains “execute expressions sequentially”… I’m not sure I know why that was needed, but I’m guessing that is the step that forces it to pull the whole sound into memory rather than work on it in stream fashion.
The rub is that the actual processing is done on a much-reduced sample. The snd-avg function is used to generate 100ms spaced, 500ms wide samples of the sum of the squared input.
That array (s-rms) should be smaller than the input array by a factor of samplerate/10 (or 4,410 in the case of 44.1 kHz). The 100M input limit becomes 23k samples.
The fix might be as simple as moving those three lines outside of the progn.
I thought you would like that
Interesting though, I didn’t even notice when casually listening. Even the “trash” part is very close to ACX specs (around -58 dB RMS) and the noise is a fairy innocuous low “shush” rather than a piercing “hiss”.
Personally I’m still not convinced that aiming for a “pass / fail” result is the best approach. It seems to me that this encourages user to game the system, and then become disappointed when ACX rejects their efforts.
That’s sort of what “Silence Finder” does. Silence / Sound finder looks for the peak in each 0.01 second block. The same technique can be used to find the RMS in blocks of a specified size. If the noise floor is below -60 dB, then we would expect to frequently see blocks of say 0.2 seconds below -60 dB.
If there are no blocks below -60 dB in a “long time”, then the noise floor is “probably” too high.
Some tuning may be necessary to determine what we mean by “a long time” and “probably”.
Nyquist uses “pointers” a lot internally, which can cause some confusion. Although snd-length is referencing the low sample rate copy of track, the low sample rate version is referencing track which is referencing the samples in the track. Unless you tell Nyquist that it can drop the reference to the original samples, they will be held in memory. By setting track to nil after creating the low sample rate version, you are telling Nyquist that it can release those samples. It can be tricky to get this right, but when it is right the error message with long selections should disappear.
First things first. I sent Koz a version of Acx-Check with the noise-floor code bypassed to test. That way we can be sure the noise-floor code is indeed the issue.
I can also see that I don’t really need to call snd-length. The length can easily be computed from values I already have so the next thing will be to send Koz a version with that change, that might just fix it.
I have a really odd system problem—new to me. What and where is audacityPortable? I’ve never had the Mac INFO system disagree…with itself. Only half of it thinks that exists. Terminal (shell) has no idea what’s going on.
What’s going on?
Step one in analysis is kill off all the ac-check entities on the machine so I don’t analyze the wrong one.
Can’t do it. I thought I knew where 100% of them were…
OK. That was probably long overdue. I went around with lethal force and cleaned out all the acx-checks except in download backup, and then forced the Audacity plugin registration and management system to start over.
[smell of brimstone]
This is what you’re expecting right?
That only happens in 2.3.3. In 2.4.1, it scans in good time, gives me the Processing Complete message…
… and then vanishes. No information panel.
Before we ride off in all directions, this is the older machine. I want to try it on a much newer one.
One other note. I get far fewer spinning beachballs than earlier. So the Mac thinks this is a more graceful process. The only one left is when the scan panel in 2.3.3 closes. 2.4.1 never gets that because it crashes.
Ok well that test makes it clear that the problem is not just with the noise-floor calculation (which is what I suspected)…
Reading the Nyquist manual it seems that the memory will get used anytime a sound is assigned to a local variable so for example looking at the code that calculates rms:
(defun my-rms (a len) ; compute the RMS of a sound
(setq chunk 2000000) ;emperically determined maximum blocksize for snd-avg
(setq bsize (truncate (/ len chunk))) ;blocksize to use for the first avg pass
(setq result (mult a a))
(when (> bsize 1)
(setq result (snd-avg result bsize bsize OP-AVERAGE))
)
(setq bsize (snd-length result chunk)) ;probably should thow an error if bsize gets chunk here
(setq result (snd-avg result bsize bsize OP-AVERAGE))
(sqrt (snd-fetch result))
)
The line (setq result (mult a a)) creates the var “result” and store the sound^2 in it. That right there takes up about 300MB of memory for Koz’s 30-minute example. That memory should get freed and garbage-collected as the “result” var is re-assigned and ultimately ends up with the single float answer.
Steve: I tried adding
(snd-set-max-audio-mem 1073741824)
to the top of the plugin but that returns an error
error: unbound function - SND-SET-MAX-AUDIO-MEM
on my version of Audacity (2.3.3 – lastest in the ubuntu repository). Is that function new to the newer version of Nyquist? If so then we want to use to that to expand the usable memory it’s going to be Audacity version dependent. The documentation indicates that the default value is “about 1GB”.
So I suggest the best immediate fix is to indeed reduce the maxlen as needed, if your calculations are accurate something on the order of 30M should be safe.
Koz: Can you do a binary search and determine how long a segment Acx-check can analyze with out crashing?
Yes, SND-SET-MAX-AUDIO-MEM is new. I think it came in with Audacity 2.4.0.
Unfortunately the ubuntuhandbook1 PPA version of Audacity appears to have major problems, but there has been a report of a good Flatpak version. I’ve not tried the latest Flatpak version myself, but might be worth giving it a go.