Apply gain to several files so the loudest one gets normalized to 1. ?
Sorry, I didn't find a better title for this question !
But let's say you have 8 audio files loaded in 8 buffers, and you want to find the one with the loudest amplitude peak, normalize it at max, get the corresponding gain, and apply that gain to the 7 other files ?
You can get the peak using [mxj buf.Op] (max message), find the biggest one of your buffers, get the ratio to normalize it, and multiply all buffers values with this ratio (multiply message).
Thanks, is it an external ?
No, but you need to have Java installed...
Thanks,
I'd rather find a way without installing it, any ideas ?
Well, except going through all sounds with peek~ and compare maximums, as it could be using too many resources.
To get the peak of multiple samples maybe the easiest is using javascript. Here's an example for one sample:
there is this array.frombuffer (array.tobuffer) object. But I cant get it work.
Thank you Double_UG and TFL !
My mehtod has mistakes, and [array.frombuffer] returns an array of arrays (one sub-array per channel). @flatsinglechannel 1 returns a flat array only if the buffer has one channel.
Here are both approaches corrected:
Instead of two [array.foreach] as I did above, using a combination of [array.max] and [array.min] is about 5 times faster (about as fast as the js approach):
This is so cool. It both gives me a good introduction to arrays and directly solves my problem, thanks !
Interesting use of the [array.] family.
But my quick tests show that [mxj buf.Op] is much faster than [array.*] and v8. It makes really a huge difference with long files.
No Java here either :(
Adding a [peek~] + [peak] approach for the sake of it (spoiler: not good):
Unrelated, but related question....
I've got the peak analysis and gain calculation of my (actually 14) files, and this part seems ok with the CPU, but applying the gain to the 14 stereo buffers (4-30seconds each) causes CPU spikes. As there's no way to get a bang out of the buffer when the gain has been applied, I'm out of ideas to quickly sequentially normalize them all (without setting an arbitrary, reasonable delay).
You could apply the gain dynamically by multiplying the output of whatever you use to read your buffers, instead of changing the buffers data.
why not condition audio files before using them in max in first place ?
@TFL : brilliant, why didn’t I think of that ?
@Source Audio : because I’ve already made thousands of files. I’m talking about hundreds of 14 file folders that are loaded manually during the performance
because I’ve already made thousands of files. I’m talking about hundreds of 14 file folders that are loaded manually during the performance
You could process all of them in a batch using your max patch, you don't mind CPU spikes if you don't play audio. It seems like apply gain is synchronous so you could [t b b], right b go to the apply message, left b to write and you get your file written as soon as the gain is applied. write is asynchronous though, but once the process is done you get a bang from the [buffer~] right outlet that you can use to read the next file and repeat.
You could process all of them in a batch using your max patch, you don't mind CPU spikes if you don't play audio.Indeed, I could use Max to pre-normalize the files.
That said, I've had answers in another thread that made be very careful when writing a lot of data on a hard drive. Should I be concerned in this case ?
It all depends on your patch, but loading files into buffers, getting their peak as we did above, using apply gain and writing the resulting buffer back into disk don't even require to have audio processing enabled, so which audio driver to use isn't a concern.
Well I'm not concerned about this but more about writing thousands of files on the disk.
I guess you are referring to this from Source Audio:
I would suggest you test what works and what not
while running in non-real time and in small portions,
and if possible use non system disk drive,
otherwise you could ruin your system drive.
Writing thousands of files on the disk is not really a problem in itself, it's more about how the writing is handled.
IMO issues could arrise if you write on disk through [record~] using NRT driver, but I would say there is much less risk with write sent to a [buffer~] since you would wait for the operation to be complete before loading the next buffer.
For safety I would:
try incrementally with 1 file , then 10, then 100, then 1000 and see how it goes
not overwrite existing files but write new ones instead either in a separate folder or by adding something in the file name
maybe add an emergency STOP bang button and a short 100 or 200ms delay between two files so that you have a little window to click the said button if anything goes wrong so you don't have to "force Max to quite"
add a counter to monitor the number of treated files and see how fast/slow things go, maybe even write treated file names into a text file, as a log
to be super extra safe, write your files on something else than the system drive, although I assume Source Audio advice is specifically for using [record~] with NRT driver.
can you be more precise about quantity and file sizes? Best approach may vary.
I currently have 663 folders of 14 files each, so 9282 files for a total of 12.32 Go.
That said I added the auto-gain to my player patch, so it’s having the same effect. But I’d happily remove this part if I knew the files were correctly normalized beforehand. And this would have the advantage of displaying the waveforms more accurately on screen.
The project is explained here :
One could understand that you create 14 files of same length in a folder
and want to normalize them as group, keeping relative loudness.
Could your player use multichannel buffer ?
if that is the case, I would normalize right after audio gets created
before writig 14 channel buffer to disk.
if that is an option, you could use
ffmpeg to merge and normalize that 663 folders with 14 tracks in batch processing
Files in the folders have various lengths (1, 2, 4,8 or 16 4/4 bars).
the new version of ffmpeg-normalize has batch normalization which keeps relative loudness. That seems exactly what you're looking for.
So normalization/gain happens on a folder by folder basis, not across all 9282 files?
Then you could go the readfolder->polybuffer~-[loop get max]-[loop apply gain]->writefolder route, - and have this loop over the list of your folders. This should quite fast, and stays within the Max domain.
Thank you all, I’m away for a few days, but will investigate as soon as I’m back !
if the buffer obejct would have an "undo" for that, one could abuse its normalize function to find its peak.