Log in

View Full Version : AviSynth+ thread Vol.2


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 [65] 66 67 68 69 70 71 72 73 74 75

Z2697
8th March 2025, 06:53
Maybe keep the old behavior, but add a parameter to force the interpolation? Like what fmtconv does with fh and fv.

Z2697
8th March 2025, 07:01
I tried ICX version and it's indeed faster, about 2.5x on my machine.
But I think it's because it uses Intel Math Libraries (the runtime requirements are libmmd.dll and svml_dispmd.dll)
But whatever.

Even x86/x64 users can benefit from this speedup: if the Expr contains specific trigonometric functions (tan, asin, acos, atan) that have no JIT implementation, then Avisynth cannot use JIT and falls back to the C implementation.
ICX is x64 only though.
BTW tan is sin/cos why is it not optimized like sin and cos?

pinterf
8th March 2025, 07:03
I tried to register at the AVS wiki to add about new resizers but I have not received an activation email for months at my @gmail.com email address.
[...]

Thanks, I try to integrate it.
The source of online documentation in maintained on github, that is the 'master'. It's in .rst format, which has its learning curve (formatting, to keep the conventions we use throughout the documentation, linking between pages and titles - which I always forget how to do it). But after doing so may pages, I start to get used to it.

When I'm ready, I build with Sphynx into html. Sphynx is a Python module, so you have to have a Python and do a simple "pip install sphynx" afaik. The I run 'make html' from distrib/docs/english and check the result from the local file system in a browser. distrib/docs/english/build/html/index.html

This must be the very same look, what is automatically generarated into
https://avisynthplus.readthedocs.io/en/latest/
(automatic build of rst changes is set up on github)


https://github.com/AviSynth/AviSynthPlus/blob/master/distrib/docs/english/source/avisynthdoc/corefilters/resize.rst

pinterf
8th March 2025, 07:09
Maybe keep the old behavior, but add a parameter to force the interpolation? Like what fmtconv does with fh and fv.
I think I left the exact size check there because I'm sure most people would expect this behavior. I admit wonkey_monkey's use case needs to be addressed, and his request is perfectly understandable.

pinterf
8th March 2025, 07:23
I tried ICX version and it's indeed faster, about 2.5x on my machine.
But I think it's because it uses Intel Math Libraries (the runtime requirements are libmmd.dll and svml_dispmd.dll)
But whatever.


ICX is x64 only though.
BTW tan is sin/cos why is it not optimized like sin and cos?
I simply did not have time for that, nor was there public demand for it. But since Avisynth is getting smarter by users' requests, it can be arranged if you really need that. In JIT, we have to manually assemble and calculate the Taylor series and handle the edge case preparations. The tangent function has its own Taylor series; we could implement it in JIT, or calculate it twice using sine and cosine.

Imagine it like this:
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/exprfilter/exprfilter.cpp#L835

In C, Intel is probably using its own quasi-SIMD functions like _mm_sin_ps, _mm_cos_ps, etc., which are all implemented in their math library. If used, these beat the speed of other compiler implementations by a huge margin.

EDIT:
Last time I implemented atan2.
I took a feasible C implementation, and converted it into our JIT commands.

https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/exprfilter/exprfilter.cpp#L682

EDIT2:
O.K. tangent is almost done in JIT, will do the rest and cleanup in the evening (work awaits me in the garden :))

tormento
8th March 2025, 11:03
I've just documented your "new" resizers.
Oh, wow! :thanks:

tormento
8th March 2025, 11:07
I tried ICX version and it's indeed faster, about 2.5x on my machine.
What I told you? :p

Z2697
8th March 2025, 15:48
What I told you? :p

The thing is, it's the optimized math library that contributes most to the speed, which makes much more sense to me than the compiler alone.

tormento
8th March 2025, 16:56
The thing is, it's the optimized math library that contributes most to the speed, which makes much more sense to me than the compiler alone.
It could actually be a solar flare or a fluke in the electricity.

The important thing is that, for our needs, it's faster.

Z2697
8th March 2025, 17:58
It could actually be a solar flare or a fluke in the electricity.

The important thing is that, for our needs, it's faster.

It's certainly not those random stuff.

Yeah... if your need is voluntarily disable JIT optimization when it's available? (Or other SIMD / assembly optimizations in other libraries)
Covering edge cases where there's no "written" optimization available is a good thing though, I must say.

DTL
8th March 2025, 19:18
Other long-awaiting feature for 'Geometric deformation filters' section : AddBorders() and LetterBox() must have an option to create 'filtered/conditioned' transients to save from ringing at displaying or other processing of this new created transients with interpolation engines. Currently it is possible to workaround only with scripting with extracting-filtering-inserting_back of filtered area of new created transients.
These are still very frequently used filters by users of analog captures like VHS and others.

At the *perfect world of AVS+ for moving pictures* the script like

BlankClip(100, 100, 100, color=$FFFFFF, pixel_type="YV12")
LetterBox(10,10,10,10,color=$000000)
LanczosResize(width*2, height*2, taps=10) (or other sinc-based upsizer with not very low taps number)
ConvertToRGB24(matrix="PC.601")

Must produce white frame with black borders without overshoots (flat/film look/makeup) and without ringing at the edges or corner. With current AVS+ user must use some more or less complex scripting to workaround this issue.

With release r4212 it still produce:
https://i.postimg.cc/G20P5YZt/image-2025-03-09-013416421.png

Expected output in some day new version:
(full-frame simulation with 2 of the several possible conditioning filters)
BlankClip(100, 100, 100, color=$FFFFFF, pixel_type="YV12")
LetterBox(10,10,10,10,color=$000000)
UserDefined2Resize(width, height, src_left=0.00001, src_top=0.00001) (or GaussResize(width, height, p=12, src_left=0.00001, src_top=0.00001))
LanczosResize(width*2, height*2, taps=10)
ConvertToRGB24(matrix="PC.601")

https://i.postimg.cc/cLnr5jZ7/image-2025-03-09-013805513.png

With Gauss p=12
https://i.postimg.cc/Gtd566Z4/image-2025-03-09-015049867.png

tormento
8th March 2025, 19:26
It's certainly not those random stuff.
I was joking…

FranceBB
8th March 2025, 20:22
I tried to register at the AVS wiki to add about new resizers but I have not received an activation email for months at my @gmail.com email address.

Try to reach out to Wilbert (https://forum.doom9.org/member.php?u=2705) directly or just ask him here (https://forum.doom9.org/showthread.php?t=105205&page=11). I'm sure he can enable your account on the wiki.

isidroco
8th March 2025, 20:35
Not sure if it's the right place. There's a bug in Normalize (v3.7.3+ r4066). Using 48k16b stereo will horribly saturate audio (even using normalize values as low as 0.02). Previously converting same audio to Float works fine.

DTL
9th March 2025, 10:48
Also it may be recommended to add user-defined support for GaussResize(). As s-param same as in UserDefined2Resize. Gauss kernel is also variable-sized and its useful size significantly depends on p-param value (the distance from zero argument to the low enough return values around zero). Currently support for GaussResize is fixed to 4.0

https://github.com/AviSynth/AviSynthPlus/blob/b038d0225e549fb5e329e68580cb0f3fdcc49d56/avs_core/filters/resample_functions.h#L247

to be some average value to fit many versions of kernel. But it may be too wide for narrow versions (and waste some performance) or too narrow for 'very wide' kernels and limit possible filtering/blurring effect if required. So it may be defaulted to 4.0 to keep compatibility with old scripts and workflows but may be controlled by user with second to p - s-param. The practical limits may be at least 1 to 10 or even more. In the param1 param2 param3 set of params for ConvertXXX for chroma resampling (or possible new applications of resize kernels to filtering like expected in AddBorders/LetterBox) it may be mapped to param2 (or param3 ?).

Also it may be good to add to resizers documentation support values for all resizers (from file https://github.com/AviSynth/AviSynthPlus/blob/b038d0225e549fb5e329e68580cb0f3fdcc49d56/avs_core/filters/resample_functions.h )
PointResize - support 0.0001 (expect = 0)
BilinearResize - support 1.0
BicubicResize - support 2.0
LanczosResize, BlackmanResize, SincResize, SincLin2Resize - support=taps
Spline16Resize - support 2.0
Spline36Resize - support 3.0
Spline64Resize - support 4.0
GaussResize - support 4.0 (expected to be used-defined)
SinPowerResize - support 2.0 (fixed by design)
UserDefined2Resize - support is user-defined by s-param (default 2.3 ?)

So we have 3 different classes of resizers with different support values for resampler:

1. Fixed by design:
PointResize, BilinearResize, BicubicResize, SinPowerResize, SplineXResize

2. Hard fixed to other param:
LanczosResize, BlackmanResize, SincResize, SincLin2Resize

3. Can be user-defined for performance/quality balance or special effects:
UserDefined2Resize, GaussResize

Also it is possible to make 'auto-support' option for GaussResize with limiting lowest usable kernel level to something like 0.01. It is the soultion of current kernel equation of https://github.com/AviSynth/AviSynthPlus/blob/b038d0225e549fb5e329e68580cb0f3fdcc49d56/avs_core/filters/resample_functions.cpp#L209

pow(2.0, - p*value*value);

by 'value' member. I.e. 0.01 = pow(2.0, - p*value*value); (note p = p-param * 0.1 at https://github.com/AviSynth/AviSynthPlus/blob/b038d0225e549fb5e329e68580cb0f3fdcc49d56/avs_core/filters/resample_functions.cpp#L208)

Online solvers gives
https://i.postimg.cc/Kz4qkzjF/image-2025-03-09-131927402.png

Auto-support for GaussResize may be activated if user set s-param to zero ?

After simplification for static members - auto-support=SQRT(6.64/p) (for kernel members above 0.01 of max of 1)
https://i.postimg.cc/bYtSyhgt/image-2025-03-09-151651035.png

It shows current support=4.0 is enough for p-param in range of about 4 to 100 and too big for range 20 to 100 but too low for p-param in current valid range of 0.1 to about 4.

Emulgator
9th March 2025, 12:54
There's a bug in Normalize (v3.7.3+ r4066). Using 48k16b stereo will horribly saturate audio.
Can confirm a horribly boosted-to-clip-at-FS audio while touching it with simple internal algos since maybe that version.
No time to give a decent in-depth description ATM though.

StainlessS
9th March 2025, 13:25
Can confirm a horribly boosted-to-clip-at-FS audio while touching it with simple internal algos since maybe that version.
No time to give a decent in-depth description ATM though.

About 12 months ago I had similar problem with nasty normalize, I think I mis-diagnosed the problem due to pretty massive scripts and hurry to get result, so I just kludged the problem.

I suspect that the problem I had may be this exact same thing. [I probably wrongly blamed LSmash]

Here thread that I was gonna delete but did not (thanks Emulgator),
the date of thread post is probably a good-ish indicator of problem oranges ( or should that be "origin" :) ). [Oranges by orange man:- https://www.youtube.com/watch?v=qUPsNgmXR7M ]

LSmash weird Audio [JFYI] (20 Feb 2024):- https://forum.doom9.org/showthread.php?p=1997964#post1997964

EDIT: The kludge I used involved conversion to Float audio, I think.

EDIT: In above thread the problem seemed to come from MeGUI normalized audio, but I also (depending upon some things) normalized in Avisynth instead,
I presume that MeGUI normalize is done via Avisynth anyway.
I never did pin down the actual culprit, and continue with the kludge.

pinterf
9th March 2025, 18:41
Not sure if it's the right place. There's a bug in Normalize (v3.7.3+ r4066). Using 48k16b stereo will horribly saturate audio (even using normalize values as low as 0.02). Previously converting same audio to Float works fine.
It was probably this one, which is a Microsoft MSVC compiler bug.
https://github.com/AviSynth/AviSynthPlus/commit/d78be370b6f5ef997bc15343b81f519931bf0d54
I made a workaround and reported the issue to Microsoft
https://developercommunity.visualstudio.com/t/Bad-code-gen-with-inlined-functions-with/10813706
See my repo which I created for just this report:
https://github.com/pinterf/msvc_bad_codegen_demo_2

In three month they still reached in problem solving the "Under Consideration" flag. I'm glad I don't write software for nuclear plants.

EDIT: It seems they silently fixed their optimizer compiler. The code built with Visual Studio 17.13.1 no longer has the bug.

pinterf
9th March 2025, 19:12
Implemented 'tan' in Expr (the JitASM way). I don't know who and why would use it but it was an interesting task.

Preliminary info:
Expr: implement tan (32 bit float) in JisASM

Benchmark script

BlankClip(1000,1280,720,pixel_type="Y8")
# swipes the range between -Pi to +Pi
s = "sxr 2 * 1 - 3.14159254 * 1 * tan 10 * 128 +"
# swipes the range between -5Pi to +5Pi
# s = "sxr 2 * 1 - 3.14159254 * 5 * tan 1 0 * 128 +"
a= Expr(s, optSSE2 = false, optAVX2=false, OptVectorC=False)
b= Expr(s, optSSE2 = false, optAVX2=false)
c= Expr(s, optSSE2 = True, optAVX2=false)
d= Expr(s, optSSE2 = True, optAVX2=True)

a # or b or c or d

Results:

MSVC Intel ICX LLVM
SinglePixel C : 48 66 [fps]
Vector friendly C: 122 175
JitASM SSE : 345 (same for both)
JitASM AVX : 727 (same for both)

DTL
9th March 2025, 21:18
About update for GaussResize : This commit may be used (after testing) - https://github.com/DTL2020/ResampleMT/commit/cbece7356bc06a7cccab69289c883525aaae934d

More detailed description - https://forum.doom9.org/showthread.php?p=2016041#post2016041

It have both user-defined b (base value) added and user-defined 's' or auto-controlled support value. So it is second resizer with 3 control params.

Also the Note can be added to Blur() filter documentation: If larger radius gauss blur is requred - the GaussResize() filter can be used in no-resize mode (convolution only) with low enough p-param values (below 10..15). It can be used for fade-in/out and blur-in/out use cases and also animated with Animate().

pinterf
9th March 2025, 21:21
AviSynth+ 3.7.3 r4217

https://github.com/pinterf/AviSynthPlus/releases/tag/v3.7.3.4217

Implement "tan" for Expr JITasm. See benchmarks in the post above.

DTL
10th March 2025, 05:52
icx build from r4217 not working in Win10 x64 again - 'version' script in VirtualDub returns "Avisynth open failure: Avisynth: script open failed!". Only x64_xp_or_better is working.

pinterf
10th March 2025, 08:45
There was no build method difference since the previous build. Zero extra geek optimizations, tools did not update themselves (neither msvc, nor ICX).
What does avsmeter64 and Avspmod say? Virtualdub opens avs though VfW interface, the others work differently.
Are your VC redistributables up-to-date? No more question comes into my mind.

DTL
10th March 2025, 10:05
Are your VC redistributables up-to-date?

VC++ vcp140.dll files are from 2021. It looks non-updated Win10. At other Win10 host r4217 icx is working.

Can we have some software-way to check for required OS/external components dependencies at avisynth.dll loading/running/startup ? We do not have installer now and it can not check requirements and display any warning.

Some owners of Windows hosts may not like updates like 'to not import new bugs from Microsoft or any other sources to already working software' and restrict to install possibly dangerous software. So not all Win10 hosts are auto-updated with latest Microsoft VC++ redistributables. Also may be in best case the required microsoft components can be 'statically linked' to single .dll so AVS+ can be more 'portable' ?

pinterf
10th March 2025, 10:16
We don't have tools to know what works and what not in recent test builds. It's an unfortunate thing that your 2021 redist causes problems _if_ running an ICX based AviSynth.
Install the official 3.7.3 installer, specifically the one with the VC redistributables bundle. Then you have a system with a bit more updated. Then you can copy and exchange the different DLLs as you want. Dependencies are clear in this aspect.

gispos
10th March 2025, 10:31
icx build from r4217 not working in Win10 x64 again - 'version' script in VirtualDub returns "Avisynth open failure: Avisynth: script open failed!". Only x64_xp_or_better is working.
The version works for me.
You wrote it yourself, the latest VC runtimes are required. The 4212 should not work on the system with the old runtimes either.

https://forum.doom9.org/showpost.php?p=2015433&postcount=3142

DTL
10th March 2025, 11:15
Also note about Animate(): It can only interpolate with linear function. For highly-non-linear processing it causes as result the very non-linear effects on 'timeline'. Is it possible somehow add user-prodived non-linear time function ? May be close to the way how user enter equation to Expr() ?

"You wrote it yourself, the latest VC runtimes are required."

I tried at different Win hosts. Some are 'public usage' and may not have right to install 'common use components updates'. VC++ files installed into system32 may damage other software at given host. It may be nice if Avisynth.dll with all required MS .dlls can be loaded from separate 'portable' folder. So no other software can access that .dlls and possibly become unstable.

pinterf
10th March 2025, 13:10
I think I've found another version of this old issue (https://forum.doom9.net/showthread.php?p=1849921) (has it really been six years?!):

version.crop(8,32,16,16)
animate(0,100,"bicubicresize",\
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0)

There's a discontinuity at frame 50 because resizing is skipped. With b=1.0/3.0, c=1.0/3.0 (which is the default), or indeed anything other than b=0,c=0.5 (which I still maintain should be the default :sly: ), BicubicResize always blurs or sharpens its output, regardless of resizing, and that blur is missing from frame 50.
Added "force" boolean to resizers, which forces the resizer algorithm to work even if the clip dimensions would not change at all. Replaces the src_left, src_top is 0.000001 workaround.
.
version.crop(8,32,16,16)
w=width()
h=height()
force=True
# at frame 50 Force=false (default) omits resizing, thus the intentional blur.
animate(0,100,"bicubicresize",\
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

See it in the next build.

DTL
10th March 2025, 13:30
"Added "force" boolean to resizers, which forces the resizer algorithm to work even if the clip dimensions would not change at all. "

It is also long-awaited update because resizers also used as convolution-filters engines in 'no-resize' mode.

But in old hack-mode user can force H and/or V processing with non-zero src_left and/or src_top param. If only 1D processing is requred it is good control. With 'force' it will enable both H and V ? It may be not always good. Better to make 2 dimensions separated logic so user can enable 1D convolution only. Separated control may be by 1 integer or text param like
0 - auto
1 - force H
2 - force V
3 - force H and V

Or 2 new bool params separated like forceH and forceV.

Usage example: If process UV planes of 4:2:2 format with some low-pass filtering - only H convolution is required.


Function Convert422ToRGB24mon_lin_x4_709(clip c)
{
uc=UToY(c)
vc=VToY(c)
uc=UserDefined2ResizeMT(uc,src_left=0.001,uc.width, uc.height, b=125, c=18)
vc=UserDefined2ResizeMT(vc,src_left=0.001,vc.width, vc.height, b=125, c=18)
uc=SincLin2ResizeMT(uc, src_left=0, uc.width*2, uc.height, taps=16)
vc=SincLin2ResizeMT(vc, src_left=0, vc.width*2, vc.height, taps=16)
yuv444=CombinePlanes(c, uc, vc, planes="YUV", source_planes="YYY", pixel_type="YUV444P10")
rgb_lin=ConvertYUVToLinearRGB(yuv444,Color=2)
rgb_lin=SincLin2ResizeMT(rgb_lin,rgb_lin.width*4, rgb_lin.height*4, taps=16)
yuv_out=ConvertLinearRGBToYUV(rgb_lin,Color=2)
return yuv_out.ConvertToRGB24(matrix="PC.709")
}

pinterf
10th March 2025, 16:09
What's the use case of blurring just either the H or V direction?

DTL
10th March 2025, 16:35
One example is shown in the post above - end_of_chain 'conditioning' of chroma subsampled channels. Before displaying (or format conversion with frame resizing or other RGB geometry changes like rotation may be). The 'intermediate' RGB<->subsampled_YUV conversions are not require this filtering (because in a long sequence of RGB<->subsampled_YUV conversions it will degrade colour sharpness). It is in the core design of chroma-subsampled digital moving pictures systems from the ages of ITU BT rec.601.

Also in the 'nice future' it is expected to have some flag for ConvertToYUV42xToRGB() (or to YUV 4:4:4) to perform unfiltered (intermediate) or filtered UV (final/end_of_chain) processing. Where for 4:2:2 input the UV filtering must be only in H direction.

Currently as AVS used as processing only software (intermediate conversions) the filtering is not (frequently) required. But high quality resize via (linear) RGB from YUV 4:2:0 to low res YUV 4:2:0 (sort of Main Rip Creation Process) also requires it for example.

Example of 'intermediate' workflow with YV12 input and 'unfiltered intermediate RGB' (this also 'nice to have' to be supported in the frame properties metadata - 'is RGB from unfiltered subsampled chroma ?' also 'is RGB half-banded chroma H ?' (from previous YUV 4:2:2 for example), 'is RGB half-banded chroma V ?' (from 4:2:0 YUV for example):

ConvertToRGB24()
RGBAdjust(...)
ConvertToYV12()

Example of 'display RGB' workflow for frame downsize for YV12 input:

ConvertToRGB24() (with filtering UVs to save from ringing at resize if resizer can do it) - restore 'flat RGB'
optional - convert to linear RGB
SinPowerResize(width/2, height/2) - re-condition RGB for lower frame size (also got full-band RGBs from any source - 4:4:4 or 4:2:x)
optional - convert to System Transfer Function RGB
ConvertToYV12() - half-band UV but left unconditioned ringing UVs for next (unlimited) processing stages if required

Example of 'display RGB' workflow for frame upsize for YV12 input (like SD to HD):

ConvertToRGB24() (with filtering UVs to save from ringing at resize if resizer can do it (sinc-based resize will do it)) - restore 'flat RGB'
optional - convert to linear RGB
SincLin2Resize(HD_width, HD_height)
optional - convert to System Transfer Function RGB
ConvertToYV12() - half-band UV but left unconditioned possibly ringing UVs for next (unlimited) processing stages if required

Current working script-function for conversion of 4:2:2 YUV to 'UVfiltered/display/monitor RGB' is

Function Convert422ToRGB24mon_709(clip c)
{
uc=UToY(c)
vc=VToY(c)
uc=UserDefined2Resize(uc,src_left=0.001,uc.width, uc.height, b=125, c=18)
vc=UserDefined2Resize(vc,src_left=0.001,vc.width, vc.height, b=125, c=18)
uc=SincLin2Resize(uc, src_left=0, uc.width*2, uc.height, taps=16)
vc=SincLin2Resize(vc, src_left=0, vc.width*2, vc.height, taps=16)
yuv444=CombinePlanes(c, uc, vc, planes="YUV", source_planes="YYY", pixel_type="YUV444P10")
return yuv444.ConvertToRGB24(matrix="PC.709")
}

And it uses H-only UV planes filtering. It can be created in compiled more optimized for RAM transfer and cache usage form in the future (as expansion of ConvertToRGB() with more arguments like UV conditioning kernel filter params). Though it is really a sequence of Convert422ToYUV444(using_UVfiltering) and next ConvertYUV444ToRGB(as today). But it is currently hidden in the logic of multi-input formats ConvertXXX filters.

Simple idea: If user not need to filter H+V - the old way of src_left !=0 can be used to force H-only filtering.

StvG
10th March 2025, 18:28
"You wrote it yourself, the latest VC runtimes are required."

I tried at different Win hosts. Some are 'public usage' and may not have right to install 'common use components updates'. VC++ files installed into system32 may damage other software at given host. It may be nice if Avisynth.dll with all required MS .dlls can be loaded from separate 'portable' folder. So no other software can access that .dlls and possibly become unstable.

If you want newer runtimes only for AviSynth.dll then put them next to AviSynth.dll. This way they be loaded instead the system runtimes in C:\System32.

DTL
10th March 2025, 18:36
But to load any version of Avisynth.dll at opening .avs script in some process I need to set somewhere (windows registry ?) path to the folder with that version of Avisynth.dll ? Instead of c:\windows\system32 (as default installer make ?). Why installer copy Avisynth.dll into system32 and not in the setup folder of Avisynth (in ProgramFiles or any other if possible to select by hands in installer) ?

I make search via windows registry for avisynth.dll string - but only found some path to SysWOW64. No path to \system32 (for 64bit .dll). I expect it is auto-loaded from that path only (for 64bit process) ?

StvG
10th March 2025, 18:41
But to load any version of Avisynth.dll at opening .avs script in some process I need to set somewhere (windows registry ?) path to the folder with that version of Avisynth.dll ? Instead of c:\windows\system32 (as default installer make ?). Why installer copy Avisynth.dll into system32 and not in the setup folder of Avisynth (in ProgramFiles or any other if possible to select by hands in installer) ?

The easiest way (without bothering with the registry) is to put AviSynth.dll next to the program you use. For e.g., next to VirtualDub64.exe/AvsPmod.exe.

Edit: Or add the location of AviSynth.dll to PATH.

DTL
10th March 2025, 18:58
Thank you. I copy files

Avisynth.dll (r4217 icx build)
msvcp140.dll
vcruntime140.dll
vcruntime140_1.dll
(from working host)

in the same filder with VirtualDub x64 at the 'restricted to install VC++ runtime updates' host and now VirtualDub can open 'version' script and shows r4217 build.

StvG
10th March 2025, 19:01
Thank you. I copy files

Avisynth.dll (r4217 icx build)
msvcp140.dll
vcruntime140.dll
vcruntime140_1.dll
(from working host)

in the same filder with VirtualDub x64 at the 'restricted to install VC++ runtime updates' host and now VirtualDub can open 'version' script and shows r4217 build.

If you didn't notice my edit of the previous post - also you can add the custom location of AviSynth.dll to PATH so to not have copies of AviSynth.dll+deps for every program you use with AviSynth.

DTL
10th March 2025, 19:38
If you didn't notice my edit of the previous post - also you can add the custom location of AviSynth.dll to PATH so to not have copies of AviSynth.dll+deps for every program you use with AviSynth.

But it can again cause some interference with unknown other software if OS .dll loader will somehow found that VC++ runtimes in the PATH location. Too dangerous.

Some more safe way may be to add to PATH in current process (or console prompt) only for the lifetime of this process.

And attempt to start VirtualDub and other software with batch file like


SET PATH=%PATH%; C:\Distr\Avisynth_3.7.3_20250309_r4217\x64_intel_icx\
start Veedub64.exe
exit


But sadly it is not working - looks like can not load VC++ runtimes near Avisynth.dll located in current process PATH (may be \system32 have higher priority in search order) .

Working solution: copy
msvcp140.dll
vcruntime140.dll
vcruntime140_1.dll
(required version) to the same folder with Virtualdub.exe and now AVS r4217 can be loaded via added PATH from batch file. It is also good enough as do not expose these possibly dangerous .dlls to other processes.

StvG
10th March 2025, 20:57
But it can again cause some interference with unknown other software if OS .dll loader will somehow found that VC++ runtimes in the PATH location. Too dangerous.

Put AviSynth.dll in X location alongside with the required deps. Add the location to the user PATH. The user PATH is appended to the system PATH.
"Local" PATH is check firstly->system PATH is checked secondly->user PATH is checked thirdly.

The two cases you can have:
1. You load app that requires same deps. The deps from system32 are loaded because the system PATH is checked before the user PATH.
2. You load AviSynth.dll. The deps next to AviSynth.dll are loaded because they are "local" and the "local" PATH is the very first that is checked. The deps in this location will be ever used only for the binaries next to them.

DTL
11th March 2025, 06:47
What's the use case of blurring just either the H or V direction?

Oh - I remember second use case - noted in the https://forum.doom9.org/showthread.php?p=2015981#post2015981

https://i.postimg.cc/MKQbDdNF/2025-03-11-084529.png

For better AddBorders/LetterBox filters also 1D filtering is required.

pinterf
11th March 2025, 08:59
Oh - I remember second use case - noted in the https://forum.doom9.org/showthread.php?p=2015981#post2015981

For better AddBorders/LetterBox filters also 1D filtering is required.
Sound reasonable, for me it's zero effort to implement 0..3 allowing different H and V settings instead of a simple boolean.

pinterf
11th March 2025, 09:12
Meanwhile, a nice "Animate" addition works on my test bench. This work is perhaps the last one before a feature freeze (Now the "Resize" force parameter, Gauss new parameters, and Animate is in the queue).

Animate can take an external function if you'd like more than a linear interpolation.

Even if you don't use an external function, a finer, more precise interpolation of integer values was implemented, and now 64-bit values are handled just fine. Internally, a 96.32-bit integer arithmetic is used for calculation. The calculated values are properly rounded.

Still undecided whether the custom function should return 0.0 at the beginning and 1.0 at the end of the range.

Now this is possible:

version.crop(8,32,16,16)
w=Width()
h=height()
force=3 # both H and V

Function Diff(clip src1, clip src2)
{
return Subtract(src1.ConvertBits(8),src2.ConvertBits(8)).Levels(120, 1, 255-120, 0, 255, coring=false)
}

# rules for animate callback: float param named "stage"
# stage is called for values (0.0 , 1.0)
# For proper start-end conditions
# f(0.0) = 0.0 and f(1.0) = 1.0 is a nice to have

function animhelper_lin(float "stage")
{
return stage # full linear
}

function animhelper_exp(float "stage")
{
return (stage*stage*stage)
}

fn_lin = Func(animhelper_lin)
fn_exp = Func(animhelper_exp)

#function
a=animate(0,100,"bicubicresize", fn_exp, \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

#function implemented as linear
b=animate(0,100,"bicubicresize", fn_lin, \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

# classic, always linear
c=animate(0,100,"bicubicresize", \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

#check
d=Diff(b,c) # they are the same

StackHorizontal(a,b,c,d)

DTL
11th March 2025, 13:54
Sound reasonable, for me it's zero effort to implement 0..3 allowing different H and V settings instead of a simple boolean.

Yes - integer control with 0 to 3 cases is enough.

About better versions of ConvertToXXX for conversions between full-band and sub-sampled chroma:

1. Downconversions (from 4:4:4 to 4:2:x) should work as today with single resize filter params.
The pre-filtering and resizing can be done in single call to resampler with user-provided kernel params.

2. Upconversions (from 4:2:x to 4:4:4) need addition of special 'pre-filter' params set (same as current resize filter). And optional 1 more stage for UV passing to resampler in no-resize mode.

If user make 'standard intermediate' upconversion to 4:4:4 (YUV or dematrix to RGB) - the 'pre-filter' params is not set and this stage is skipped. Short kernel resizer used to save from ringing at 2x upsampling of unconditioned UVs - like Bicubic or short Spline (16?) or even Point. Today we have default Bicubic and it work about good.

If user make 'final end_of_chain' upconversion to 4:4:4 - the 'pre-filter' params set to anti-gibbs low pass filtering (like Gauss or SinPow or UD2) and resize filter can be long kernel sinc with many taps (like Sinc or SincLin2 or Lanczos or Blackman).

Default 'pre-filter' params set is 'not set' and pre-filtering stage is disabled/skipped.

The minimum required is new version of

ConvertToYUV444(clip, [ string matrix, bool interlaced,
string ChromaInPlacement,
string chromaresample,
float param1, float param2, float param3] )

With added UV prefiltering stage it expected:

ConvertToYUV444(clip, [ string matrix, bool interlaced,
string ChromaInPlacement,
string chromaprefilter,
float pre_param1, float pre_param2, float pre_param3,
string chromaresample,
float param1, float param2, float param3] )

where prefilter is only applied to further upsampled direction (H if input is 4:2:2 or H and V if input is 4:2:0). This expected to have performance and RAM usage benefit over user-script with extracting UV planes for prefiltering (and optional resizing) and combining back to YUV.

pinterf
11th March 2025, 14:23
Until I understand why on earth a second treat is needed on chroma :), a question:
Since those Gauss extra parameters don't do any harm and give some freedom, I adopted them. Since defaults are kept, this is fully compatible.
It's so simple, that I don't think I can expect change of mind on this topic, isn't it?

DTL
11th March 2025, 14:40
a question:
Since those Gauss extra parameters don't do any harm and give some freedom, I adopted them. Since defaults are kept, this is fully compatible.
It's so simple, that I don't think I can expect change of mind on this topic, isn't it?

Yes - I hope the changes are final. Some post-ideas on sources text:

1. The 'support' limits for SincResize and GaussResize are properties of resampler engine used and not kernels - so we can make
#define MAX_SUPPORT 150

(as current SincResize - it really depends on resampler's ability to process with enough performance and require not very small frame size) and make clamping of support (and taps) (0, MAX_SUPPORT) in both SincResize and GaussResize.

2. The highest p for GaussResize is naturally limited to about 50..100 where it becomes equal to PointResize (support falls greatly below 1) and do not decrease 'blur' any more. But lowest of 0.01 may be not enough if user process HD or UHD frame and want more soft blur and have enough compute resources. So the MAX_SUPPORT and min valid p-param for GaussResize may be subject of research and/or user-requests for max softening required. If we allow min p-param to 0.001 (or lower) - the MAX_SUPPORT define also need to be somehow higher (may be 250 or 500 - need to check the s-equation output). Or some research need about how much 'support' size can use current AVS+ resample engine (at how large frame sizes and colour-subsampling formats).

DTL
11th March 2025, 14:46
"Until I understand why on earth a second treat is needed on chroma "

You need to dig deeply to the beginning of the digital moving pictures on this planet at the current civilization - it is about 1/2 or century in the past. When the very first ITU BT 601 rec/standard on digitizing of analog video was developed. There were (may be still present) some articles about that times at EBU website (or Internet archive). The key words is something about 'we finally agreed on UV low-pass filters defined in BT rec.601 for 4:2:2 subsampled chroma but it cause UV signals ringing as hell'. It was designed to allow many generations YUV4:2:2<->RGB transcodings in the production chain without great chroma sharpness losses. I not remember the exact document link - will try to search one more time some later.

tormento
11th March 2025, 15:16
The killer feature to add would be CUDA support, such as NekoPanda started. I just dream of that.

And I think I will keep on dreaming. :)

pinterf
11th March 2025, 15:42
AviSynth is a framework that provides the necessary ecosystem for creating a filter chain that can keep data in GPU memory across filters, eliminating the need to transfer data back and forth between the CPU and GPU. Dreaming about a CUDA-core AviSynth is pointless without plugins, unless one is satisfied with a CUDA-accelerated Version() clip.

There are other ways to achieve this if authors write their own plugins and follow their own rules.

By the way, even Nekopanda didn't rewrite everything. They specifically rewrote filters to support only 8-bit, others only YV12, and MvTools with a block size of 8x8.

DTL
11th March 2025, 16:58
I did some simulation with
'standard bicubic subsampled chroma 4:2:2 ColorBars' names _b
and
'max possible bandwidth subsampled chroma 4:2:2 ColorBars" names _s

With different upconversions to 4:4:4 and 4x sinc-based displaying resizing (LanczosResize)

https://i.postimg.cc/Bbc55sGf/image-2025-03-11-184839773.png

Script:

Function Convert422To444dp(clip c)
{
uc=UToY(c)
vc=VToY(c)
uc=UserDefined2Resize(uc,src_left=0.001,uc.width, uc.height, b=115, c=9)
vc=UserDefined2Resize(vc,src_left=0.001,vc.width, vc.height, b=115, c=9)
uc=SincLin2Resize(uc, src_left=0, uc.width*2, uc.height, taps=16)
vc=SincLin2Resize(vc, src_left=0, vc.width*2, vc.height, taps=16)
yuv444=CombinePlanes(c, uc, vc, planes="YUV", source_planes="YYY", pixel_type="YUV444P8")
return yuv444
}

Function Convert422To444sp(clip c)
{
return ConvertToYUV444(c, chromaresample="userdefined2", param1=115, param2=9)
}

ColorBarsHD(2048,150)
UserDefined2Resize(width/8, height, b=120, c=13) # YUV 4:4:4 cond

bt601_chroma_b=ConvertToYUV422(chromaresample="bicubic") # AVS_bicubic 42x chroma - half band uncond
bt601_chroma_s=ConvertToYUV422(chromaresample="sinclin2") # close_bt 601 42x chroma - half band uncond

#single pass 2x upsize no anti-Gibbs
sp_noag_bic_b=ConvertToYUV444(bt601_chroma_b).Subtitle("sp_noag_bic_b")
sp_noag_bic_s=ConvertToYUV444(bt601_chroma_s).SubTitle("sp_noag_bic_s")

#single pass 2x upsize + use anti-Gibbs kernel
sp_ag_b=Convert422To444sp(bt601_chroma_b).Subtitle("sp_ag_b")
sp_ag_s=Convert422To444sp(bt601_chroma_s).Subtitle("sp_ag_s")

#dual pass
dp_ag_b=Convert422To444dp(bt601_chroma_b).Subtitle("dp_ag_b")
dp_ag_s=Convert422To444dp(bt601_chroma_s).Subtitle("dp_ag_s")

#last=StackVertical(sp_noag_bic,sp_noag, sp_ag, dp_ag)
last = StackVertical(sp_noag_bic_b, sp_noag_bic_s, sp_ag_b, sp_ag_s, dp_ag_b, dp_ag_s)

LanczosResize(width*4, height, taps=16)

ConvertToRGB24(matrix="PC.601")


The worst case ringing is when standard bicubic-based upsampler meet highest possible bandwidth subsampled chroma (possible from some sources). But if source produced with AVS-like ConvertTo422 with bicubic downsampled chroma it works good enough (AVS resizers are good complement each other like bicubic for downsize and upsize).

The single pass chroma upconverting with anti-ring kernel do not shows significant difference in ringing over pre-filtered chroma it is original frequency domain + second pass sinc-based flat upsampler (dual-pass chroma processing). Also the dark shadows in colour transients looks a bit smaller in single pass processing. So prefiltered chroma way may be left for special use cases (if it may benefit with some current user's source) and may be done in scripting.

pinterf
11th March 2025, 18:17
Avisynth+ 3.7.3 r4241
https://github.com/pinterf/AviSynthPlus/releases/tag/v3.7.3.4241

https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/changelist374.html
https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/resize.html
https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/animate.html

Last week changes
20250311 3.7.3 r4241
--------------------
- Animate: Custom function option
- Animate: more precise granularity for integer interpolation, allow 64 bit input
- Animate: add proper rounding for integer interpolation
- Resizers: add "force" integer parameter to force the resizing process even if Avisynth decided it's not needed
- GaussResize: add "b" and "s" parameters See :doc:`Resize Filters <corefilters/resize>`.

20250309 3.7.3 r4217
--------------------
Expr: implement tanf in JisASM

Benchmark script

BlankClip(1000,1280,720,pixel_type="Y8")
# swipes the range between -Pi to +Pi
s = "sxr 2 * 1 - 3.14159254 * 1 * tan 10 * 128 +"
# swipes the range between -5Pi to +5Pi
# s = "sxr 2 * 1 - 3.14159254 * 5 * tan 1 0 * 128 +"
a= Expr(s, optSSE2 = false, optAVX2=false, OptVectorC=False)
b= Expr(s, optSSE2 = false, optAVX2=false)
c= Expr(s, optSSE2 = True, optAVX2=false)
d= Expr(s, optSSE2 = True, optAVX2=True)

a # or b or c or d

Results:

MSVC Intel ICX LLVM
SinglePixel C : 48 66 [fps]
Vector friendly C: 122 175
JitASM SSE : 345 (same for both)
JitASM AVX : 727 (same for both)


20250306 3.7.3 r4612
--------------------
Expr: Rewrite the C (non-Intel-JIT) path to support vectorization, if the compiler is capable.

I created this for non-Intel platforms where the (Intel SSE2-AVX2) JIT compiler does not work.

Even if the compiler is not very advanced (MSVC khhhhmm..) this approach is faster because it
has less overhead when interpreting the instruction flow. It processes 16, 8, 4, and 1 floats
when handling the horizontal line, taking the largest chunks it can then finishing the rest
with the smaller ones.

Benchmarks (x64 bit). For comparison, I also provide the JIT results.

Script (optSSE2 = false disables JIT):

# Mandelbrot
ColorBarsHD()
a="X dup * Y dup * - A + T^ X Y 2 * * B + 2 min Y^ T 2 min X^ "
b=a+a
c=b+b
blankclip(width=960,height=640,length=1600,pixel_type="YUV420P8")
Expr("sxr 3 * 2 - -1.2947627 - 1.01 frameno ^ / -1.2947627 + A@ X^ syr 2 * 1 - 0.4399695 "
\ + "- 1.01 frameno ^ / 0.4399695 + B@ Y^ "+c+c+c+c+c+b+a+"X dup * Y dup * + 4 < 0 255 ?",
\ "128", "128",optSSE2 = false, optAVX2=false) # optVectorC=true default

MSVC: Microsoft VC, actual VS2022 version.
Intel: Intel C++ Compiler 2025 - LLVM based, aka ICX.

"Base" means the instruction set is not specified: SSE2 is the minimum for x64.

Compiler/Settings VectSize FPS
-------------------------------------- ---------- -----
MSVC debug 1 0.27
Intel (base + optional AVX2 paths) 1 1.01 (! Mixed instruction set support, slow)
MSVC Base 1 1.71 VectorSize=1, not optimal :)
MSVC old single variable C: - 2.82
Intel old single variable C: - 2.90
MSVC Base 16 4.47 (initial Proof of Concept version)
MSVC AVX2 16 4.59 (initial PoC version)
MSVC Base 16 5.94
MSVC AVX2 16 6.04
Intel Base 16 6.29 (initial PoC version)
Intel AVX2 optional AVX512 -Qax:AVX512 16 12.60 (! Mixed instruction set support, slow)
Intel Base 16 14.70
Intel AVX2 16 19.20
Intel AVX512 16 20.10
MSVC JIT SSE2 2x4 59.00 (dual lanes, XMM regs)
MSVC JIT AVX2 2x8 128.00 (dual lanes,YMM regs)

In this test, where dual processor optimization was enabled, Intel performed poorly (though
it still achieved twice the speed of MSVC). It seems that dynamically dispatching code fragments
to different instruction sets incurs significant overhead.

Conclusion:

We should better avoid builds mixed-code sets.
Since AVX2 has been generally supported for at least ten years, creating a non-mixed
AVX2-only compilation is a reasonable enhancement.

Looking at the numbers, achieving one-third the speed of the old SSE2 JIT, which we considered
fast, is quite impressive. Even x86/x64 users can benefit from this speedup. If the Expr contains
specific trigonometric functions (tan, asin, acos, atan) that have no JIT implementation, then
Avisynth cannot use JIT and falls back to the C implementation.

Expr has now a new debug parameter: bool optVectorC (default true) which C code to run if non-JIT is used.

DTL
11th March 2025, 19:43
Now you can also update Notes to the Blur() - https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/blur.html

"If you need a larger radius Gaussian blur,..."

GaussResize(width, height, force=3, p=0.1, s=0)

It looks github web do not allow to add comments on lines or at least full .rst file. https://github.com/pinterf/AviSynthPlus/blob/master/distrib/docs/english/source/avisynthdoc/corefilters/resize.rst?plain=1#L438

Current: Force the resizing process even if the dimensions remain unchanged and ``src_width`` or ``src_top``
are zero. Useful to intentionally prevent sudden visual differences that might occur if resizing
is unexpectedly skipped.

* 0 - return unchanged if no resize needed
* 1 - force H - Horizontal resizing phase
* 2 - force V - Vertical resizing phase

Better text: Force the resizing or convolution with resize kernel (filtering) process even if the dimensions remain unchanged and ``src_width`` or ``src_top``
are zero. Useful to intentionally prevent sudden visual differences that might occur if resizing
is unexpectedly skipped or if convolution only (filtering) without resize is required.

* 0 - return unchanged if no resize needed
* 1 - force H - Horizontal resizing or convolution (filtering) phase
* 2 - force V - Vertical resizing or convolution (filtering) phase

For GaussResize p :
"original equation is s = sqrt(-ln(0.01)/(param*ln(b))"

p-param passed to GaussResize is internally scaled by 0.1 (old AVS arguments were integers only ?). So from user's view original equation is s = sqrt(-ln(0.01)/((p-param * 0.1)*ln(b))

Also in "as s = sqrt(4.6 / ((param * 0.1) * log(b)))" - log(b) in C-library is log based e-number (natural). So for less messy description may be better to write as 's = sqrt(4.6 / ((p * 0.1) * ln(b)))' . Where ln(b) is more universal math equation for natural logarithm. And 'p' and 'b' are directly entered by user params values.

For GaussResize b :
b: Controls the blurring. Valid range: 1.5 to 3.5.

Better text:
b: Controls the blurring. Valid range: 1.5 to 3.5. Filter kernel is b^(-p*0.1*(x^2)) . Default b is 2.0 to be compatible with pre-3.7.4 use cases. If high precision Gauss kernel is required (for example for filtering applications) it is recommended to use the base of the natural logarithm 2.71828.