Batch process effects in .mp3 (speech) files

OS X 10.10.2; Audacity 2.1.2 obtained via .dmg installer.

I download and listen to approx 20 separate and distinct .mp3 speech (not music) files daily. I listen to them with a mp3 player at work, in a noisy manufacturing environment. The quality of some of the files is acceptable. Others have portions that are way too quiet, but then have small, very loud portions, such as loud bumper music, or one soft spoken person with another being very loud.

Unfortunately, I don’t have the time to examine each one, so they need to be done in a batch (chain?). Also, I don’t know to decide whether to use, for instance, the Leveler, or Limiter, or Amplifier, or Compressor, or Normalizer; or in what combination or order.

Some only need to be leveled. Some only need to be amplified. Some need to be both leveled and amplified. And it would be nice if they were all normalized (but this part isn’t required).

The distortions, say, from clipping aren’t really important. The important part is being able to hear and understand the speech.

Then I need to export the results into an 96 kbps .mp3 file.

What is the best way to construct the chain so that it will fix the problematic .mp3 files without seriously degrading the good .mp3 files?

Thanks

The “Leveler” effect should generally be avoided unless you want to add distortion to the audio.

Chris’s Dynamic compressor is likely to be a good choice. It’s available here: https://theaudacitytopodcast.com/chriss-dynamic-compressor-plugin-for-audacity/
Installation instructions (Audacity 2.1.2) are here: http://manual.audacityteam.org/man/effect_menu.html#nyquist_effects

Generally Chris’s compressor works best with the “Compress ratio” increased to about 0.7 (higher values have more effect), and all other settings at their defaults.
Chris’s compressor may be used in a “Chain” (see: http://manual.audacityteam.org/man/chains_for_batch_processing_and_effects_automation.html)

Note that exporting as MP3 always reduces the sound quality a bit. The lower the bit-rate (“kbps”) the more loss of sound quality. The loss of sound quality can never be recovered, so be sure to keep backup copies of any important original versions.

Thanks for Chris’ Dynamic Compressor. Works exactly as I wanted.

But I’m running into a problem. Every batch (chain) I run does not complete. There is an occasional .mp3 file that, for some reason I can’t find, will not compress using Chris’.

The problem .mp3 file will load, but once the Compressor starts, the file displays, then the routine stops. The compressor does not compress the problem file, nor does it skip the problem file and move on to the next file in the chain. The compressor simply stops running.

Also, when I try to run the problem file individually with the compressor, not in a chain, it also will not run.

The problem file does, however, load into audacity, will play in audacity, and the amplify effect does work on the problem file.

The problem file does not appear to be unusual, not to loud, not too many peaks, etc.

If necessary, I can deal with the problem files separately, but at a minimum, I need the Compressor to skip the problem file and continue on with the others in the chain.

Is there a fix for this problem, or a workaround that would either detect the problem files first so I could remove them from the chain, or a way to skip the problem file and move on to the others in the chain?

Thanks

It’s a feature request that Chains skips over a failed file and carries on to the next.

Is the problem too much silence at the start or end of the file? It may be possible to add a plugin to the Chain to trim the silence before Chris’s Compressor gets to it.

Does the Audacity Compressor work on the file?


Gale

I checked just the latest “.mp3 problem file” and, Yes, the Audacity Compressor does work on it. Audacity compressor amplifies the sound a bit and Audacity seems to play the compressed file fine.

So, I clicked to undo the Audacity Compressor. Then I deleted a section of about 1 minute of trailing silence from the problem file, but Chris’ Compressor still would not work.

I clicked to undo my delete of the trailing silence, then deleted about 0.2 seconds off of the front, leading end, of the file, and then Chris’ Compressor did work on the trimmed file.

I have processed 3 sets of files. Of the first and second sets of files, 2 of 20 files would not process using Chris’ Compressor. Of the third set of files, only one file would not process. So it’s a problem with each batch I’ve processed so far.

Any idea of what might be happening?

If not, where would I get a plugin to facilitate chain-deleting a tiny bit off of the start and the end of the .mp3 file?

Thanks

As Gale wrote, there may be too much silence at the start or end of the file. To find out if that is the problem, try applying Chris’s compressor to just one of the problem files (manually, not in a Chain), but rather than clicking the “OK” button, click the “Debug” button. If the processing fails it should give an error message. Copy and paste the error message into your reply.

Steve:

Here is the text of the debug text from my most recent "problem .mp3 file’

----------

break: float loop
if continued: return from BREAK
Function: #<Subr-BREAK: #3b66994>
Arguments:
  "float loop"
Function: #<FSubr-WHEN: #3b659a4>
Arguments:
  (> COUNT 10000)
  (BREAK "float loop")
Function: #<FSubr-DO: #3b671b0>
Arguments:
  NIL
  ((< (ABS (- DY Y)) 0.1) I)
  (INCF COUNT)
  (WHEN (> COUNT 10000) (BREAK "float loop"))
  (SETF I (+ START (/ (- END START) 2)))
  (SETF DY (- (INTERP (+ I X)) (INTERP I)))
  (IF (> DY Y) (SETF END I) (SETF START I))
Function: #<FSubr-LET: #3b638a4>
Arguments:
  ((START (- I 1)) (END (+ I 1)) (DY 0) (COUNT 0))
  (DO NIL ((< (ABS (- DY Y)) 0.1) I) (INCF COUNT) (WHEN (> COUNT 10000) (BREAK "float loop")) (SETF I (+ START (/ (- END START) 2))) (SETF DY (- (INTERP (+ I X)) (INTERP I))) (IF (> DY Y) (SETF END I) (SETF START I)))
Function: #<Closure-BINARY-SEARCH-FLOAT: #3454298>
Arguments:
  897
  870.978
  1
  NIL
Function: #<FSubr-IF: #3b6715c>
Arguments:
  (OR (= RES 0) (= RES (1- (LENGTH PARA))))
  RES
  (BINARY-SEARCH-FLOAT RES Y X LEFT)
Function: #<FSubr-LET*: #3b65878>
Arguments:
  ((LEFT (< Y 0)) (RES (BINARY-SEARCH-INT Y X LEFT)) (I (IF (OR (= RES 0) (= RES (1- (LENGTH PARA)))) RES (BINARY-SEARCH-FLOAT RES Y X LEFT))) (YOFF (- Y1 (INTERP I))) (I (- I X1)))
  (LAMBDA (X) (+ (INTERP (+ X I)) YOFF))
Function: #<FSubr-LET: #3b638a4>
Arguments:
  ((Y (- Y2 Y1)) (X (- X2 X1)))
  (WHEN (> (ABS Y) (AREF PARA (1- (LENGTH PARA)))) (ERROR "y is too big"))
  (WHEN (<= X 0) (ERROR "x is too small"))
  (WHEN (>= X (LENGTH PARA)) (RETURN NIL))
  (LET* ((LEFT (< Y 0)) (RES (BINARY-SEARCH-INT Y X LEFT)) (I (IF (OR (= RES 0) (= RES (1- (LENGTH PARA)))) RES (BINARY-SEARCH-FLOAT RES Y X LEFT))) (YOFF (- Y1 (INTERP I))) (I (- I X1))) (LAMBDA (X) (+ (INTERP (+ X I)) YOFF)))
Function: #<Closure-SOLVE-PARA: #345554c>
Arguments:
  0
  -1000
  1
  -129.022
Function: #<FSubr-SETF: #3b63724>
Arguments:
  CUR-PARA
  (SOLVE-PARA I IY J JY)
  CUR-PARA-END
  J
Function: #<FSubr-TAGBODY: #3b65c14>
Arguments:
  AGAIN
  (SETF J (1+ I) JY (SAMP J))
  (SETF CUR-PARA (SOLVE-PARA I IY J JY) CUR-PARA-END J)
  (LOOP (INCF J) (WHEN (NULL (SAMP J)) (PROGN (WHEN (NULL CUR-PARA) (SETF CUR-PARA (SOLVE-PARA I IY J JY))) (RETURN))) (SETF JY (SAMP J)) (LET (IY-CHANGED (PARY -1)) (WHEN (AND FIRST (> (/ (/ (- JY IY) RIGHT-WIDTH) (- J I)) 0.01)) (PROGN (SETF IY-CHANGED T) (SETF IY (- JY (* 0.01 (* RIGHT-WIDTH (- J I))))))) (WHEN CUR-PARA (SETF PARY (FUNCALL CUR-PARA J))) (WHEN (>= PARY 0) (RETURN)) (WHEN (OR (< PARY JY) IY-CHANGED (NULL CUR-PARA)) (PROGN (SETF CUR-PARA (SOLVE-PARA I IY J JY)) (SETF CUR-PARA-END J)))))
  (WHEN FIRST (PROGN (SETF FIRST NIL) (GO AGAIN)))
Function: #<FSubr-LET: #3b638a4>
Arguments:
  ((IY (SAMP I)) (FIRST (NULL CUR-PARA)) J JY)
  (TAGBODY AGAIN (SETF J (1+ I) JY (SAMP J)) (SETF CUR-PARA (SOLVE-PARA I IY J JY) CUR-PARA-END J) (LOOP (INCF J) (WHEN (NULL (SAMP J)) (PROGN (WHEN (NULL CUR-PARA) (SETF CUR-PARA (SOLVE-PARA I IY J JY))) (RETURN))) (SETF JY (SAMP J)) (LET (IY-CHANGED (PARY -1)) (WHEN (AND FIRST (> (/ (/ (- JY IY) RIGHT-WIDTH) (- J I)) 0.01)) (PROGN (SETF IY-CHANGED T) (SETF IY (- JY (* 0.01 (* RIGHT-WIDTH (- J I))))))) (WHEN CUR-PARA (SETF PARY (FUNCALL CUR-PARA J))) (WHEN (>= PARY 0) (RETURN)) (WHEN (OR (< PARY JY) IY-CHANGED (NULL CUR-PARA)) (PROGN (SETF CUR-PARA (SOLVE-PARA I IY J JY)) (SETF CUR-PARA-END J))))) (WHEN FIRST (PROGN (SETF FIRST NIL) (GO AGAIN))))
Function: #<FSubr-WHEN: #3b659a4>
Arguments:
  (OR (NULL CUR-PARA) (AND (= I CUR-PARA-END) (SAMP (+ I 2))))
  (LET ((IY (SAMP I)) (FIRST (NULL CUR-PARA)) J JY) (TAGBODY AGAIN (SETF J (1+ I) JY (SAMP J)) (SETF CUR-PARA (SOLVE-PARA I IY J JY) CUR-PARA-END J) (LOOP (INCF J) (WHEN (NULL (SAMP J)) (PROGN (WHEN (NULL CUR-PARA) (SETF CUR-PARA (SOLVE-PARA I IY J JY))) (RETURN))) (SETF JY (SAMP J)) (LET (IY-CHANGED (PARY -1)) (WHEN (AND FIRST (> (/ (/ (- JY IY) RIGHT-WIDTH) (- J I)) 0.01)) (PROGN (SETF IY-CHANGED T) (SETF IY (- JY (* 0.01 (* RIGHT-WIDTH (- J I))))))) (WHEN CUR-PARA (SETF PARY (FUNCALL CUR-PARA J))) (WHEN (>= PARY 0) (RETURN)) (WHEN (OR (< PARY JY) IY-CHANGED (NULL CUR-PARA)) (PROGN (SETF CUR-PARA (SOLVE-PARA I IY J JY)) (SETF CUR-PARA-END J))))) (WHEN FIRST (PROGN (SETF FIRST NIL) (GO AGAIN)))))
Function: #<FSubr-LABELS: #3b648a0>
Arguments:
  ((SAMP (I) (GET-BUFFER-SAMPLE INPUT-BUF I)))
  (WHEN (OR (NULL CUR-PARA) (AND (= I CUR-PARA-END) (SAMP (+ I 2)))) (LET ((IY (SAMP I)) (FIRST (NULL CUR-PARA)) J JY) (TAGBODY AGAIN (SETF J (1+ I) JY (SAMP J)) (SETF CUR-PARA (SOLVE-PARA I IY J JY) CUR-PARA-END J) (LOOP (INCF J) (WHEN (NULL (SAMP J)) (PROGN (WHEN (NULL CUR-PARA) (SETF CUR-PARA (SOLVE-PARA I IY J JY))) (RETURN))) (SETF JY (SAMP J)) (LET (IY-CHANGED (PARY -1)) (WHEN (AND FIRST (> (/ (/ (- JY IY) RIGHT-WIDTH) (- J I)) 0.01)) (PROGN (SETF IY-CHANGED T) (SETF IY (- JY (* 0.01 (* RIGHT-WIDTH (- J I))))))) (WHEN CUR-PARA (SETF PARY (FUNCALL CUR-PARA J))) (WHEN (>= PARY 0) (RETURN)) (WHEN (OR (< PARY JY) IY-CHANGED (NULL CUR-PARA)) (PROGN (SETF CUR-PARA (SOLVE-PARA I IY J JY)) (SETF CUR-PARA-END J))))) (WHEN FIRST (PROGN (SETF FIRST NIL) (GO AGAIN))))))
  (WHEN (= 0 (REM I 1000)) (SET-BUFFER-POS INPUT-BUF I))
  (LET* ((V (FUNCALL CUR-PARA I)) (RES (IF (> V FLOOR) V (+ (* (- V FLOOR) -1 NOISE-FACTOR) FLOOR)))) (IF FIRST-SAMP (PROGN (SETF FIRST-SAMP NIL) RES) (PROGN (INCF I) (IF (AND (NULL (SAMP I)) (NULL (SAMP (1- I)))) NIL RES))))
Function: #<Subr-SEND: #3b679cc>
Arguments:
  #<Object: #3cb9b38>
  #<Object: #3cb9b38>
1>

I ran into that recently. I’ve been happily using Chris for years. I change the first value, Compress ratio from the default 0.5 to 0.77 or 0.78 to simulate the broadcast compressors at the local radio station. Your mileage may vary, consult your local listings, void where prohibited.

This is what Chris does. From top: None, default and 0.77.

I cut down a radio show and the show started snugging content directly up against the entertainment. I don’t cut it off, I Command-L silence a bit of it and then cut it off. Command-L produces a dead-silent gap at the beginning of the show that Chris hates.

The solution is to cut everything else and leave the bad content connected at the start. Compress and then cut it off.

Koz

As we thought. The error “break: float loop” is due to the presence of “absolute silence” with a length of more than 10000 samples.

Absolute silence hardly ever occurs in recordings other than as a result of editing, so as koz suggests, the problem could be avoided by using the compressor before applying other edits. If it’s too late for that, then “Truncate Silence” could be used to remove audio that is below -80 dB: http://manual.audacityteam.org/man/truncate_silence.html

Steve, I’m not following what you are saying.

You say to use the compressor before applying other edits.

But Chris’ Dynamic Compressor is the first and only edit I wish to apply to the .mp3 files.

And when I apply Chris’ to the .mp3 as the first Effect to the file, Chris’ is the Effect that is failing.

Should I instead apply the “TruncateSilence” BEFORE applying Chris’?

If so, must I apply the “TruncateSilence” on every .mp3 file in the batch in order to insure that the batch completes, rather than abort on finding a file with excess silence? Or, is there some way to evaluate all the files in the batch (in a chain…not one-by-one) as to whether they contain excess silence so as to exclude them from the process?

Yes, put Truncate Silence above Chris’s Compressor in the Chain which should make the Chain complete for all the files.


Gale