“normalize to 0 dB” <= requires definition of which dB you mean; Ardour can trivially normalize to 0 dbFS (or any other dBFS level if you prefer). Select all regions (Ctrl-a), then right click on one of the and find Gain > Normalize in the context menus, or in the top level “Regions” menu.
RMS and dBFS don’t really mix. You either normalize so that the peak amplitude is 0 dBFS or you normalize so that the peak RMS reaches some level (not measured in dBFS but dB<other>)
@paul I mean second case: custom RMS(?) energy level. I just want set “identical” levels for different regions. I do it by hand looking at the meter.
Probably, algorithm can be something like this (not tested for sound, pseudocode):
// preferences
nrz = 1.0; // normalize "RMS" tolerance value
// normalized frames (0 db max)
frames = [
0.0,
1.0,
-0.222,
0.194,
-0.166,
0.138,
-0.111,
0.083,
-0.055
];
// internal defaults
sum = 0.0; // sum of abs values
mid = 0.5; // middle abs value
bst = 1.0; // boost multiplier
// calculate sum
each frames as frm {
sum += abs(frm); // can be heavily by RMS formula: pow(frm, 2)
}
// calculate middle and boost
mid = sum / numberOfFrames;
bst = nrz / 2 / mid;
// apply boost
each frames as frm {
frm *= bst;
}
Fixed it for you, apparently the CODE tag on the filtered HTML input that is used by default, doesn’t like whitespace lines in it, they probably turn into breaks or something similar and throws it off for some reason.
@seablade CODE tag missing indents )) very cracked ))
Ok. For algorithm above – this work I do it by hand looking at the meter. I want make it for many regions. By hand it very long time. I want add custom action for menu or make it otherwise. For fast and dirty: I can write C application for rewrite files of ardour project. But problem - this is not regions.
How I can make it with ardour lua? This is possible?
Where is reference to original file(id?) and data for offset/length frames?
Presume:
position=“19548606” - first frame (offset in original file) for this region
length=“213504” - length of region (frames)
scale-amplitude=“1” - potential for change
source-0=“754132” - reference to original file id
master-source-0=“754132” - reference to original file id to?
Can you explain how the “middle abs value” is significant for audio?
Gain > Normalize can to normalize regions to a given peak dBFS and has the option to additionally not exceed a given RMS level. It can also be constrained for multiple-regions. In any case if you really need something different, since Ardour 5.4-399-gb2aaffa (earlier today) there are now Lua bindings to process raw region data and set the region-gain.
Select one or more audio region in the editor. then Menu > Window > Scripting In the dropdown select Snippets > Region Gain click “Run”
(You can also make it an action script and bind it to a button or keyboard shortcut…)
@x42 explain: Each actor says short phrases. These phrases are very different in level. I must first align regions level of actor, and then align level of different actors. Yes, I know about compression and faders. But compressor smooths peaks, and fader I use for automation.
not exceed a given RMS level for each region or for all regions?
Oh… I made it today without ardour scripts (just CLI). Parse xml data of ardour project file, get source files for regions, read binary wav data frame by frame (start-length-channels) for any calculation, calculate it, rewrite value for “scale-amplitude” attribute of region tag. It works. ~3k regions. You will not believe what language I did it. OMG - php! I’m shocked myself…
It’s interesting that the average digital peak works for voice. If you cut all the silence from the regions it seems plausible though. Though RMS peak-hold should do the trick, too in this case.
Did you try the Region Normalize? I’d expect that leaving peak at 0dBFS, but constraining it to at most -20dBFS RMS (or thereabouts) would do the trick as well. For the final step tick the “Normalize each region using the peak of all regions” checkbox and use digital peak.
Anyway, it’s great that you managed to help yourself! Now try that with ProTools
PHP is perfectly fine. I think it’s even the language where reading XML and iterating over elements needs the fewest lines of code. Then again perl would probably win a code golf for the whole thing - and neither code win a security or beauty test
Yes, I tried normalize to 0db. Incorrect between cries and whispers.
And -20db by RMS (“bottom”) will make “top” peak as great than 0db or not? I want soft limit for peaks. Yes, top as 0db, and bottom as -20 just for example.
Thanks for ProTools, but no )) I chose php as language for fast experiment. I lazy yesterday for use libxml with C.
The RMS normalization option was only added in Ardour 5.1 (in case you run an older version). It’s an additional constraint (logical AND).
If you have a sine-wave of -18dBFS and select to normalize to “0 dBFS peak” but at most “-12dBFS RMS” the normalization operation will apply 6dB of gain. The digital peak in this case will be -12dBFS as well (not 0).
Sounds right. It keeps the same level for each region.
This is close of what I want.
I joke named it “intelligent leveler”.
I do not like my algorithm (magic numbers) but it makes what need:
No, there is no built-in way to do exactly that. An average of the digital peak value is not a standard measure. It’s really medium related, so even while it may work well in your case we’ll have a hard time justifying this. I think it’s a good candidate for a script. Look at at region_gain.lua, if you remove the comments and “undo” it’s less than 20 lines and even similar to your code. Or if you really want to change the line 1469 in audioregion.cc from rms += buf[i] * buf[i]; to rms += abs(buf[i]);, recompile Ardour, and RMS normalize to -22.5dBFS (your hardcoded 0.075).
While it may sound crazy, actually being able to hack the DAW was a major selling point for me doing post-production work: You can create the tool that you need for the project at hand. For movie postprod, which is usually a long process, it’s entirely worth it. I bet you’ll also find use-cases for your PHP script later doing some fancy batch modifications on the timeline: let’s swap scenes 3 and 4 shall we ?!
As for n_chan > 0: I’m not entirely sure if it is still possible these days to obtain an AudioRegion with zero audio channels. But you can add/remove I/O ports, effectively turning an audio track into a midi-track post factum and there are also audio+midi tracks. That check probably just catches potential or historical edge case bugs.
Digital peak just for experiment, it so close of what I want. Just close. I will try it more.
No, 0.075 not hardcoded, it only for example. Ideally I want set something (like this value) from Ardour interface.
Thanks for https://github.com/Ardour/ardour/blob/master/scripts/s_region_gain.lua yes, it can be modified.
No, I don’t want change standard ardour code (for upgrade without problem).
My php script? No… I think php is not good idea for audio processing.
Maybe for make something with xml structure - not bad.
But this is shit:
class Source
{
private $_sourceXml = null;
private $_sourceFile = null;
private $_sourceStream = null;
private $_dataOffset = null;
public function __construct($sourceXml, $audioDirectory)
{
$this->_sourceXml = $sourceXml;
// check source audio file
$sourceFile = $audioDirectory . '/' . $this->getAttrValue('name');
if (!is_file($sourceFile)) {
throw new Exception('Source file not exists: ' . $sourceFile);
}
if (!is_readable($sourceFile)) {
throw new Exception('Source file has not readable: ' . $sourceFile);
}
$this->_sourceFile = $sourceFile;
}
public function getAttrValue($attrName)
{
if (null === $this->_sourceXml[ $attrName ]) {
throw new Exception(
'Source entry not contain ' . $attrName . ' attribute'
);
}
return $this->_sourceXml[ $attrName ]->__toString();
}
public function getSourceSize()
{
return filesize($this->_sourceFile);
}
public function getFrames($start, $length, $channels)
{
if (!$this->_sourceStream) {
$this->_openSourceStream();
}
$frames = [];
fseek(
$this->_sourceStream,
$this->_dataOffset + ($start * $channels * 4), // 4 (bytes) as 32 bit float
SEEK_SET
);
for ($pos = 0; $pos < $length; $pos += 1) {
for ($ch = 0; $ch < $channels; $ch += 1) {
$frame = unpack('f*', fread($this->_sourceStream, 4));
$frames[] = $frame[1];
}
}
return $frames;
}
private function _openSourceStream()
{
$this->_sourceStream = @ fopen($this->_sourceFile, 'rb');
if (!$this->_sourceStream) {
throw new Exception(
'Can\'t open source file: ' . $this->_sourceFile
);
}
if ('RIFF' !== fread($this->_sourceStream, 4)) {
throw new Exception(
'This is not RIFF file: ' . $this->_sourceFile
);
}
fseek($this->_sourceStream, 4, SEEK_CUR);
if (
'WAVE' !== fread($this->_sourceStream, 4) ||
'fmt ' !== fread($this->_sourceStream, 4)
) {
throw new Exception(
'This is not WAVE file: ' . $this->_sourceFile
);
}
$subChunk1Size = unpack('L*', fread($this->_sourceStream, 4));
$subChunk1Size = $subChunk1Size[1];
$audioFormat = unpack('S*', fread($this->_sourceStream, 2));
$audioFormat = $audioFormat[1];
if ($audioFormat !== 3) {
throw new Exception(
'Support only WAVE_FORMAT_IEEE_FLOAT Wave files'
);
}
fseek($this->_sourceStream, $subChunk1Size - 2, SEEK_CUR);
do {
// nothing here, seek only
} while('data' !== fread($this->_sourceStream, 4));
$this->_dataOffset = ftell($this->_sourceStream);
}
}
Swap scenes impossible with Ardour lua?
I ask about it because I know little bit about Ardour features, and lua documentation (class reference) crack my brain ))