Log in

View Full Version : AviSynth behavior for redundant commands


manolito
2nd July 2015, 07:03
In the past I have learned that for example the command "ConvertToYV12()" will be completely ignored if the clip already has this color space. Very nice because I can freely use this command without having to know the color space of the source.

Now what about some audio conversion commands?

Will "ConvertAudioTo24Bit()" do anything if audio already is 24bit?
What about "ResampleAudio(xxxx)" or "SSRC(xxxx)" if the clip already has this sample rate?


Cheers
manolito

sneaker_ger
2nd July 2015, 07:18
AviSynth 2.6:
Will "ConvertAudioTo24Bit()" do anything if audio already is 24bit?
No.

What about "ResampleAudio(xxxx)" or "SSRC(xxxx)" if the clip already has this sample rate?
Both of them output float, so there will be a change unless input is also float. Which I think should not happen, i.e. might be considered a bug.

Gavino
2nd July 2015, 09:43
Both of them output float, so there will be a change unless input is also float.
For ResampleAudio(), 16-bit input is preserved, and not converted to float.
So if the target rate is the same as the original rate, the function is a no-op for 16-bit input.

sneaker_ger
2nd July 2015, 09:49
Yes, it seems only 24 bit and 32 bit integer are affected with ResampleAudio(). But all three formats are affected with SSRC().

manolito
2nd July 2015, 10:31
Thanks a lot guys, very helpful... :thanks:

The reason I was asking is my Wavi_Mod plugin for AVStoDVD which enables alternative methods for audio normalizing (SoX, EBU R128, DynamicAudioNormalizer).

It uses either pipes or temp files, and I figured it could be useful to generally employ 24bit integer intermediate WAVE files. LAV audio is used as the source filter, and it mostly decodes as 32bit float (unless the user has disabled some output formats). But the Wavi output is always integer, probably because AVStoDVD is written in VB6 which probably uses AviSynth through the VfW interface which does not support float.

So my idea is to always append "ConvertAudioTo24Bit" to the end of the AviSynth script. This should make sure that no precision is lost when the format would be 32bit float like after SSRC. (Got this from an older post from Gavino). Does this sound reasonable? Or is it just a waste of time since the final format will be AC3 ?


Thanks again
manolito

sneaker_ger
2nd July 2015, 10:37
I don't understand what you're trying to achieve. How is adding an additional conversion at the end of a chain making sure no precision is lost? There are only three cases:
1. input into ConvertAudioTo24Bit() is 16 bit: will be skewed to 24 bit, no additional precision, just a useless conversion
2: input into ConvertAudioTo24Bit() is 24 bit: no change
3: input into ConvertAudioTo24Bit() is 32 bit integer or float: loss of precision

manolito
2nd July 2015, 13:16
Quote from tebasuna:
Then at least 24 int is recommended, similar precission than 32 float.

Quote from Gavino:
SSRC() returns float audio.
If Avisynth is being used through the VfW interface, this is converted to 16 bit as VfW does not support float.

Add ConvertAudioTo24Bit() to the end of your script to force retention of 24 bits.


In AVStoDVD you can never know in advance which bit depth Wavi will get from AviSynth. If the input from LAV audio is 32 bit float or if SSRC() is used within AviSynth, the Wavi output will be 16 bit integer. In these cases forcing 24 bit integer makes sense IMO.


Your three cases:
1. Useless yes, but at very low cost in terms of speed.
2. Yes
3. Since float is not supported and would normally get converted to 16 bit integer, forcing 24 bit integer should (almost) preserve the precision according to tebasuna.

Of course I could first analyze what Wavi would output without interfering and then decide if I need to force 24 bit integer, but why should I do this if forcing 24 bit no matter what has no disadvantage?


Cheers
manolito

sneaker_ger
2nd July 2015, 13:22
Ah, I missed the part about Wavi. Well, if you have to continue using such limited software I think it's ok. You do of course get precision loss but I assume not enough to be audible.

manolito
2nd July 2015, 17:05
Ah, I missed the part about Wavi. Well, if you have to continue using such limited software I think it's ok.

Do you have a suggestion for a Wavi replacement? As I see it the latest version 1.06m does everything to extract a WAVE file from AviSynth at the highest possble quality, and it is absolutely stable.
1.04: added support for floating-point samples (thanks to tebasuna51)
And Wavi does support float samples, the downconversion to 16 bit int is done by AviSynth, not by Wavi.

Do you think that SoundOut or ffmpeg would do a better job? And there is another requirement: The tool must support large WAVE files > 4GB. I am not talking about WAV EXTENSIBLE or WAV 64 since these formats are not supported by SoX and Aften. I would need the standard WAV format (but larger than the standard allows). No problem for Wavi...


Cheers
manolito

sneaker_ger
2nd July 2015, 17:34
avs2pipemod

manolito
2nd July 2015, 18:01
Thanks for the suggestion...

Had a quick look at it, but compared to Wavi the capabilities are overkill, and here's the showstopper:
audio - output wav extensible format audio to stdout
Sure this is more up to date than Wavi, but I have to feed the WAVE (as a file or by piping) to Aften and/or SoX, and both cannot deal with WAVEFORMATEXTENSIBLE.

So I will stick with Wavi...


Cheers
manolito

sneaker_ger
2nd July 2015, 18:30
avs2pipemod does both WAVEFORMATEX and WAVEFORMATEXTENSIBLE and works fine here with SoX:
avs2pipemod -wav input.avs | SoX -t wav - output.wav

qyot27
2nd July 2015, 19:14
At least the way I'd understand it, AVStoDVD *should* be passing the script to the particular programs (where applicable), therefore whatever the program does to access AviSynth would matter more than whether AVStoDVD itself might use the VfW interface to talk to scripts. For FFmpeg this would mean accessing the library directly and - if using -acodec copy - getting out exactly whatever the audio format output from the script is.

ffmpeg -i input.avs -acodec copy output.wav

If the script outputs 16-bit integer, output.wav will be pcm_s16le. If it output 24-bit integer, it'll be pcm_s24le. If it output float, it'll be pcm_f32le. It's just copying the PCM samples output from AviSynth directly to the output file.


I am not talking about WAV EXTENSIBLE or WAV 64 since these formats are not supported by SoX and Aften.
FFmpeg writes WAVE_FORMAT_EXTENSIBLE headers for 24-bit and Float output, but not for 16-bit.

For Aften, you can work around this using qaac as a passthrough:
ffmpeg -i test.avs -acodec copy -f wav - | qaac --silent -D - -o - | aften - output.ac3
(forcing -f wav is necessary so aften doesn't puke)

SoX and Aften do support WAVE_FORMAT_EXTENSIBLE, but not when piped by FFmpeg (this is discussed in this thread (http://forum.doom9.org/showthread.php?t=170808) - the short version: some programs don't like the way FFmpeg writes the WAVE headers when piping). A standalone file with an extensible header does work, although I was testing with 30-second samples.

An alternative is to force FFmpeg to use a different format to pipe to SoX. WavPack works (and from how the docs read, the native libavcodec wavpack encoder only does lossless):
ffmpeg -i test.avs -acodec wavpack -f wv - | sox -t wv - output.wav


Although as sneaker_ger pointed out, avs2pipemod seems to handle this correctly without resorting to qaac passthrough tricks or using alternative pipe formats.

sneaker_ger
3rd July 2015, 04:22
SoX and Aften do support WAVE_FORMAT_EXTENSIBLE
Yes, looks like it. So for the sake of completeness avs2pipemod's WAVEFORMATEXTENSIBLE:
avs2pipemod -extwav input.avs | SoX -t wav - output.wav

I also remember having trouble with ffmpeg->sox pipes now that you mention it. I think Hybrid uses headerless PCM piping for that reason.

manolito
3rd July 2015, 07:43
Thanks guys,

you gave me a couple of ideas to rewrite my plugin to use the extensible wave format exclusively.

AVStoDVD can already use ffmpeg to extract a wave file from the avs script, but the wave is always 16 bit int. Took me a while to find out that the reason for this is that "-acodec copy" is missing from the command line.

Wavi always extracts 16 bit int wav files when the format is 32 bit float (even though the changelog says that it supports float).


Cheers
manolito

tebasuna51
6th July 2015, 08:06
Wavi always extracts 16 bit int wav files when the format is 32 bit float (even though the changelog says that it supports float).

Nope, wavi support 32 bit float without problems.

Is a AviSynth default than need be canceled with, for instance in a test.avs:

global OPT_AllowFloatAudio=True # enables WAVE_FORMAT_IEEE_FLOAT audio output.
NicAc3Source("D:\tmp\200.ac3") # Decoder output is 32 bits float

And:
wavi test.avs output.wav

Found PCM audio: 2 channels, 48000 Hz, 32 bits,
Audio track contains floating-point samples.

EDIT: Other soft like MeGUI or BeHappy don't need 'global OPT_AllowFloatAudio=True' because a special AvisynthWrapper.dll

manolito
6th July 2015, 13:11
Thanks very much Tebasuna... :thanks:

I did not even know that this AviSynth command even existed.
Question: Why is this command only needed for Wavi, but not for ffmpeg and avs2pipemod?

And since I'm at it: What is your opinion on the preferred intermediate WAV resolution for DVD audio conversion (I am not talking about professional audio recording and mixing/mastering).

I did quite a lot of reading about this topic in the audio forums, and there are different opinions. Most people say that 24bit int is more resolution than anyone will ever need, others say that the better clipping protection which float offers is indeed worth the trouble.


Cheers
manolito

StainlessS
6th July 2015, 13:37
Manolito,
OPT_AllowFloatAudio, occurs @ Avisynth Syntax/Internal Functions/Control Functions,
in Avisynth built-in docs, with a few more 'secret' bits and pieces.

EDIT: Or here on wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_AllowFloatAudio

manolito
6th July 2015, 18:20
Thanks for the tips,

just tried it with several sources, it works, but only if the global OPT_AllowFloatAudio=True comes at the beginning of the AVS script.

I first tried to append the command to the end of the script (after the "audiodub(video,audio)" command), but this did not work. Wavi would then complain that no PCM audio could be found at all.


//EDIT//
The global OPT_AllowFloatAudio=True does not need to be at the very beginning of the script, but it does need to come before the "audiodub(video,audio)" statement. And it also works if the "global" is omitted.


Cheers
manolito

manolito
19th July 2015, 20:23
Bumping this thread because the global OPT_AllowFloatAudio=True command does not work as expected for me... :confused:

From the ALLOW I assumed that the audio output will be float only if the source filter delivers float samples. But instead the command seems to FORCE float audio no matter what.

I disabled all audio formats except 8bit int in the LAV Audio settings. The LAV status window correctly reports the input format as 32bit float aac and the output format as 8bit int PCM. But with the "global OPT_AllowFloatAudio=True" present in the AVS script the audio output from AviSynth is 32bit float.

This means that AviSynth actively converts 8bit int audio samples as delivered by the source filter to 32bit float - which of course does not make much sense.

Can anyone confirm this behavior?


Cheers
manolito

Wilbert
19th July 2015, 21:13
Bumping this thread because the global OPT_AllowFloatAudio=True command does not work as expected for me... :confused:

From the ALLOW I assumed that the audio output will be float only if the source filter delivers float samples. But instead the command seems to FORCE float audio no matter what.

I disabled all audio formats except 8bit int in the LAV Audio settings. The LAV status window correctly reports the input format as 32bit float aac and the output format as 8bit int PCM. But with the "global OPT_AllowFloatAudio=True" present in the AVS script the audio output from AviSynth is 32bit float.

This means that AviSynth actively converts 8bit int audio samples as delivered by the source filter to 32bit float - which of course does not make much sense.

Can anyone confirm this behavior?


Cheers
manolito

I think the magic happens in main.cpp. The relevant code:


// Allow WAVE_FORMAT_IEEE_FLOAT audio output
bool AllowFloatAudio = false;

try {
AVSValue v = env->GetVar("OPT_AllowFloatAudio");
AllowFloatAudio = v.IsBool() ? v.AsBool() : false;
}
catch (IScriptEnvironment::NotFound) { }

filter_graph = return_val.AsClip();

if (!AllowFloatAudio && filter_graph->GetVideoInfo().IsSampleType(SAMPLE_FLOAT)) // Ensure samples are int
filter_graph = env->Invoke("ConvertAudioTo16bit", AVSValue(&return_val, 1)).AsClip();

filter_graph = env->Invoke("Cache", AVSValue(filter_graph)).AsClip();

filter_graph->SetCacheHints(CACHE_GENERIC, 999); // Give the top level cache a big head start!!

So if AllowFloatAudio is true, then the audio is passed through as it is. I can't explain what you are seeing :confused:

sneaker_ger
19th July 2015, 21:22
Set ConvertAudioTo8/16/24bit() and info() to absolutely make sure you really don't have float data.

manolito
20th July 2015, 00:01
Thanks guys :stupid:

I had completely forgotten that the SSRC(48000) command in my script always converts audio to 32bit float.


Cheers
manolito

manolito
15th September 2015, 03:49
Bumping this thread because I found some interesting AviSynth peculiarities:

Will "ConvertAudioTo24Bit()" do anything if audio already is 24bit?


The answer was NO, and this is correct. But for the same question if I change 24 to 32 then the answer has to be YES.

If my source is 32bit float and I use the command "ConvertAudioTo32Bit" then AviSynth will convert the audio to 32bit int.


Another item is the command "ConvertAudioToFloat()". The docs only say that the input gets converted to float, leading me to believe that the bit depth will not be altered. But in reality the command always converts any input to 32bit float, no matter what the source bit depth is.

Of course this makes sense, even though 16bit float and 24bit float are valid digital data formats, they are are just not used for digital audio samples. But I think that the AviSynth documentation should be clearer about this.


And finally something I have no explanation for:
Somehow I ended up with the following audio conversion:
32bit float -> 32bit int -> 32bit float
(using "ConvertAudioTo32Bit" and "ConvertAudioToFloat" on a 32bit float source)

A big waste of time, but IMO it should not hurt the audio. But this conversion changes the volume of the source up to 4dB depending on the source characteristics (the resulting volume will be lower). How in the world can this happen?


Cheers
manolito

tebasuna51
15th September 2015, 11:39
The answer was NO, and this is correct. But for the same question if I change 24 to 32 then the answer has to be YES.

Of course, a 24 bits int sample is converted to a 32 bits int sample filling the 8 less significant bits with 0's. BTW you can recover the 24 bits without lose precission.

Take in mind than convert 24 to 16 bits int you lose the 8 less significant bits and can't be recovered.

Another item is the command "ConvertAudioToFloat()". The docs only say that the input gets converted to float, leading me to believe that the bit depth will not be altered. But in reality the command always converts any input to 32bit float, no matter what the source bit depth is.

Of course this makes sense, even though 16bit float and 24bit float are valid digital data formats, they are are just not used for digital audio samples. But I think that the AviSynth documentation should be clearer about this.

Yep. The docs must specify than the only float sample format supported by AviSynth is 32 bits float. The 16 and 24 float are not used for audio samples but 64 bits float is very used to avoid lose precision in arithmetic operations.

A 32 bits float sample have 8 bits for coeficient and 24 bits for mantissa, the precision is, more or less, the same than 24 bits int.

But this conversion changes the volume of the source up to 4dB depending on the source characteristics (the resulting volume will be lower). How in the world can this happen?

Float samples can have volume values over 0dB, when you convert to int samples all values over 0dB are truncated (audio clip).
All audio with float samples over 0dB must be Normalized before convert to int samples or encode.

wonkey_monkey
15th September 2015, 11:50
A 32 bits float sample have 8 bits for coeficient and 24 bits for mantissa

It's not an IEEE 754 float? No sign bit?

Wilbert
15th September 2015, 13:03
It's not an IEEE 754 float? No sign bit?

Yes it is. See http://avisynth.nl/index.php/Float.

Yep. The docs must specify than the only float sample format supported by AviSynth is 32 bits float. The 16 and 24 float are not used for audio samples but 64 bits float is very used to avoid lose precision in arithmetic operations.
This is mentioned on several pages, but i will clarify it on the ConvertAudio page.

edit
Float samples can have volume values over 0dB, when you convert to int samples all values over 0dB are truncated (audio clip).
Are you sure about that? levels_max = 20 * log_{10} 1.0 = 0 dB. How can it have a volume larger than 0 dB (aside from rounding issues)?

manolito
15th September 2015, 16:07
Of course, a 24 bits int sample is converted to a 32 bits int sample filling the 8 less significant bits with 0's. BTW you can recover the 24 bits without lose precission.

Take in mind than convert 24 to 16 bits int you lose the 8 less significant bits and can't be recovered.


Sorry, I was not clear enough when I said "if I change 24 to 32". What I meant was:
Will "ConvertAudioTo32Bit()" do anything if audio already is 32bit?
If I convert a 32bit float source with "ConvertAudioTo32Bit" then this is not a NOP for AviSynth. Instead it will convert the 32bit float to 32bit int, and this is not lossless.



One other thing about the volume change when converting 32float to 32int and back to 32float:
When I analyzed the conversion result and compared it to the source, the RMS volume and also the BS1770 LUFS was a few dB lower than the source, but the sample peak level was the same in both cases (a slightly positive value). Strange...


Cheers
manolito

manolito
15th September 2015, 20:30
If someone is interested to reproduce my findings, I just uploaded a test archive with the relevant files (160MB):

http://www59.zippyshare.com/v/tAuCf3Cj/file.html

How I tested:
I used DirectShowSource with LAVFilters 0.65. In LAV audio I checked all output formats so LAV delivered 32bit float samples to AviSynth. The LAV mixer was disabled (no clipping protection active).

I used the following script:
global OPT_AllowFloatAudio=True
DirectshowSource("i:\test.mpg")
# ConvertAudioTo32Bit()
# ConvertAudioToFloat()

I used Wavi.exe to extract the WAV file from AviSynth. The first file "32.wav" was extracted with the above script, for the second file "32_2.wav" I activated the last two lines in the script.

The second file has an audible lower volume than the first one. I got the numbers from a Global Analysis in WaveLab.

Here are the pictures from WaveLab:

http://i.imgur.com/ZCA45MK.png

Note the positive peak values for the first file, and also the 3dB difference in the RMS value for the files.

Again my question: How can this happen? Converting from float to int might introduce clipping (if you don't normalize first), but it should not alter the volume.


Cheers
manolito