View Full Version : AviSynth+ thread Vol.2
hello_hello
28th March 2025, 14:34
According to Compare() the output of A and B are not identical, so I assume the placement argument is being honoured, but in both cases the chroma placement in frame properties after resizing is 3 (YV12 source). Likewise when there's no chroma location in frame properties, no chroma location is written.
propSet("_ChromaLocation", 3)
A = GaussResize(width/2, height/2)
B = GaussResize(width/2, height/2, placement="bottom")
It'd be nice if one day the resizers could also have a placementOut argument too :)
hello_hello
28th March 2025, 14:35
pinterf,
I don't know if you saw my post a couple of pages back, but is there a way to force the VarExist argument to only accept a variable as a string, even if the variable itself is a string? For consistency the following should output something like "invalid arguments to VarExist", but instead it returns false:
X = "Y"
VarExist(X)
This would return "invalid arguments to VarExist" as expected:
X = 4
VarExist(X)
Similarly, the defined() function probably shouldn't return true for a string.
X = undefined()
defined("X")
Cheers.
One last question.... is there a reason why the subtitle function has to require a value for the LSP argument in order to output multiple lines? I know it's always been that way, but is there a reason why this shouldn't just output multiple lines?
Subtitle("X\nY\nZ")
Gavino
28th March 2025, 18:43
For consistency the following should output something like "invalid arguments to VarExist", but instead it returns false:
X = "Y"
VarExist(X)
I think you are getting confused between variable names and variable values.
VarExist(X) will pass the value of X, namely the string "Y", into the function.
Now, the argument passed to VarExist() is expected to be a string whose value is interpreted as a name, and it will check if a variable of that name exists.
So the output of false is correct (assuming there is no variable Y).
Similarly, the defined() function probably shouldn't return true for a string.
X = undefined()
defined("X")
On the other hand, defined() tests whether the actual value passed in is not equal to undefined(), so this is also correct.
(The variable X is not used here.)
jpsdr
28th March 2025, 19:33
I forgot the edges... Thanks for the answers.
hello_hello
28th March 2025, 21:06
I think you are getting confused between variable names and variable values.
VarExist(X) will pass the value of X, namely the string "Y", into the function.
I do understand the way it works, but to my way of thinking, ideally this would return true if X exists and false if it doesn't, and VarExist would never output an "I don't know what X means" error.
VarExist(X)
Maybe the variable has to be specified as a string for technical reasons, and I assume it'd be impractical to change it at this stage anyway.
StainlessS
28th March 2025, 21:18
HH, Well, if X dont exist, then error would be produced even before VarExist() would be called.
[when the arguement to VarExist is being evaluated by the script parser].
VarExist(), needs to know the name of the variable to see if it exists, not the value of an existing variable,
ie VarExist("Pi") not VarExist(3.1415926)
{
VarExist() scans the variable name table looking for the variable name entry, if it finds it then it exists, if not then it dont exist.
The Local name table is scanned first and if not found then the Global name table. <Local vars hide Global vars>
}
An existing variable can be Undefined [exists but not set to anything], but a non existing variable is not even Undefined, it dont exist at all.
An existing variable can have a type eg Undefined, Clip, String, Float, Int etc, and also value if the type is not Undefined.
EDIT: Inside a script function, an optional arg always exists (is declared as an optional arg to the function),
but if the arg is not provided by the calling code, then it is undefined.
Inside a script function, can use Defined(OptionalArgName) to test if was supplied by script function caller [and was not supplied as eg OptionalArgName=undefined].
Inside a script function, the Default() function eg OptionalArgName = Default(OptionalArgName,OptionalArgDefaultValue) could be implemented like
OptionalArgName = defined(OptionalArgName) ? OptionalArgName : OptionalArgDefaultValue
but external to a script function you would need to also test if a variable exists before can test if defined [unless you know for sure that it exists].
jpsdr
5th April 2025, 20:27
Hi.
I have an issue when i try to build soundtouch.
I have Visual Studio 2019 Update 9.26 installed with clang-llvm built option, but i don't install LLVM provided with VS, instead, i install the last LLVM version provided on the github.
When i want to build with LLVM, in the general settings i choose "LLVM-clang" instead of "Visual Studio".
It always worked with everything i tried on until now (x265, avisynth, DirectShow Source, any of my projects).
But when i tried with soundtouch, it builds with "Visual Studio", but when switched to "LLVM-clang", i have the following error (i've translated some parts):
2>------ Start of generation : Project : SoundTouch, Configuration : Release x64 ------
2>Building Custom Rule C:/PRG/Visual_2010/soundtouch/CMakeLists.txt
2>In file included from <built-in>:488:
2><command line>(6,9): error : macro name must be an identifier
2><command line>(7,9): error : macro name must be an identifier
2>Generation of project "SoundTouch.vcxproj" ended -- FAIL.
Same for soundstretch.
Does someone know by any chance how to fix this :confused:
StvG
6th April 2025, 15:43
Hi.
I have an issue when i try to build soundtouch.
I have Visual Studio 2019 Update 9.26 installed with clang-llvm built option, but i don't install LLVM provided with VS, instead, i install the last LLVM version provided on the github.
When i want to build with LLVM, in the general settings i choose "LLVM-clang" instead of "Visual Studio".
It always worked with everything i tried on until now (x265, avisynth, DirectShow Source, any of my projects).
But when i tried with soundtouch, it builds with "Visual Studio", but when switched to "LLVM-clang", i have the following error (i've translated some parts):
2>------ Start of generation : Project : SoundTouch, Configuration : Release x64 ------
2>Building Custom Rule C:/PRG/Visual_2010/soundtouch/CMakeLists.txt
2>In file included from <built-in>:488:
2><command line>(6,9): error : macro name must be an identifier
2><command line>(7,9): error : macro name must be an identifier
2>Generation of project "SoundTouch.vcxproj" ended -- FAIL.
Same for soundstretch.
Does someone know by any chance how to fix this :confused:
What's your cmake command line?
jpsdr
7th April 2025, 17:29
Hello.
My cmake command is:
@cd .\soundtouch\Build\x86_Broadwell
G:\CMakex64\bin\cmake -G "Visual Studio 16" -A Win32 ../../../../../Visual_2010/soundtouch -DCMAKE_INSTALL_PREFIX="C:\PRG\Visual_2019\AviSynth\Soundtouch\Install\x86_Broadwell" -DCMAKE_CXX_FLAGS_RELEASE="/sdl- /MP /O2 /Ob2 /Oi /Ot /Oy /GT /GL /GF /GS- /Gy /Qpar /arch:AVX2 /MD"
@cd ..\x64_Broadwell
G:\CMakex64\bin\cmake -G "Visual Studio 16" -A x64 ../../../../../Visual_2010/soundtouch -DCMAKE_INSTALL_PREFIX="C:\PRG\Visual_2019\AviSynth\Soundtouch\Install\x64_Broadwell" -DCMAKE_CXX_FLAGS_RELEASE="/sdl- /MP /O2 /Ob2 /Oi /Ot /Oy /GT /GL /GF /GS- /Gy /Qpar /arch:AVX2 /MD"
pause
qyot27
7th April 2025, 18:02
-G "Visual Studio 16 2019" -T LLVM-clang -A x64 and see what errors CMake spits out directly.
jpsdr
7th April 2025, 22:09
It fails saying it can't find the llvm-clang tools.
They are installed and they're working when using from VS, otherwise i would never been able to release all my LLVM builds... :D
(Except with soundtouch...).
StvG
7th April 2025, 22:49
The toolset probably should be -T llvm instead of -T LLVM-clang.
Also you can try with your original command without the -DCMAKE_CXX_FLAGS_RELEASE="... part.
jpsdr
8th April 2025, 19:56
Tried with "llvm", "clang-cl", "llvm-clang-cl", nothing works, always the message saying it can't find the tools.
StvG
9th April 2025, 15:12
Did you try:
@cd ..\x64_Broadwell
G:\CMakex64\bin\cmake -G "Visual Studio 16" -A x64 ../../../../../Visual_2010/soundtouch -DCMAKE_INSTALL_PREFIX="C:\PRG\Visual_2019\AviSynth\Soundtouch\Install\x64_Broadwell"
Btw you're running this command from "x64 Native tools...." not from simple cmd, right?
jpsdr
9th April 2025, 17:50
The full command which creates the solution, i double-click on the .bat file, so it's the same as running from cmd.
When the .bat file is finished and the solution created, i start Visual Studio, open the solution and finish the configuration/settings i can't do with the CMake/bat file.
And then i build the solution.
But, for the command with "-T", i've also do the same.
I'll try running it from "x64 Native tools...".
EDIT:
No change running from "x64 Native tools...", still saying it can't find the tools.
The only error message i have for now when building with llvm is the one provided post #3307... :(
wonkey_monkey
11th April 2025, 12:44
I just had another thought about my inter-filter communication idea which I outlined here (and further up): https://forum.doom9.org/showthread.php?p=2013635
It could also be useful if filters could access their "depth", e.g. so two filters could work out whether they were neighbouring in the chain. It could allow them to avoid unnecessary conversions, for example if you called two filters that knew about each other on an 8-bit clip in succession, the first filter could produce 32-bit float output and leave the downconversion for the second filter (but only if there are no intervening filters that don't understand such negotiations), which would reduce rounding errors. It could similarly help GPU filters decide when writing back to the CPU can (or can't) be avoided.
But maybe such things are best left for the user to make explicit in the script...
StvG
12th April 2025, 01:13
EDIT:
No change running from "x64 Native tools...", still saying it can't find the tools.
The only error message i have for now when building with llvm is the one provided post #3307... :(
I again ask - did you try:
@cd ..\x64_Broadwell
G:\CMakex64\bin\cmake -G "Visual Studio 16" -A x64 ../../../../../Visual_2010/soundtouch -DCMAKE_INSTALL_PREFIX="C:\PRG\Visual_2019\AviSynth\Soundtouch\Install\x64_Broadwell"
Then open the solution file, change to clang and try to build.
Your error suggests that some of the options isn't recognized by clang.
Try with default options, if this works, change option by option to see what's the culprit.
qyot27
12th April 2025, 03:17
I was able to replicate the problem from the command line directly with CMake a few days ago. Unpack the upstream LLVM somewhere, use https://github.com/zufuliu/llvm-utils to install the extra toolsets into VS2019, set the LLVMInstallDir environment variable to the bin directory where it was installed (only necessary for the latest release because there currently isn't an installer for 20.1.2, just 20.1.1), and invoke CMake using -G "Visual Studio 16 2019" -A x64 -T LLVM_v142.
Configuration completes successfully, msbuild (cmake --build . - the value of --config doesn't matter) fails. Unfortunately, the error message is exactly the same as above. The closest results from searching come from old questions on Stack Overflow that point toward it being a problem in the source code, like this one: https://stackoverflow.com/questions/44989366/macro-names-must-be-identifiers
But since the error message itself doesn't say anything about the actual piece of code that triggers the issue or in which source file, you're left guessing.
jpsdr
12th April 2025, 11:14
@StvG
I'm using the same exact options on others CMake stuff (avisynth, x265), and everything works fine.
Anyway, i tried exactly what you've asked, both directly or from "Native tools", the same error message.
@qyot27
I thought it was a CMake stuff file error, but according what you said, it may be something in the code, Visual Studio accept, but llvm less permissive don't ?
I never suspect that, but it's somehow a start... It would be indeed better as you said if the file with the problem was identified... :D
EDIT:
I tried to activate all the warnings in VS, but it didn't allow me to find anything (the fact i didn't see anything doesn't meen there is nothing... ;)).
StvG
12th April 2025, 12:14
I was able to replicate the problem from the command line directly with CMake a few days ago. Unpack the upstream LLVM somewhere, use https://github.com/zufuliu/llvm-utils to install the extra toolsets into VS2019, set the LLVMInstallDir environment variable to the bin directory where it was installed (only necessary for the latest release because there currently isn't an installer for 20.1.2, just 20.1.1), and invoke CMake using -G "Visual Studio 16 2019" -A x64 -T LLVM_v142.
Configuration completes successfully, msbuild (cmake --build . - the value of --config doesn't matter) fails. Unfortunately, the error message is exactly the same as above. The closest results from searching come from old questions on Stack Overflow that point toward it being a problem in the source code, like this one: https://stackoverflow.com/questions/44989366/macro-names-must-be-identifiers
But since the error message itself doesn't say anything about the actual piece of code that triggers the issue or in which source file, you're left guessing.
May be both of you (you and @jpsdr) should (since you're using not using VS 2022) to try older llvm versions because I don't have any issues with VS 2022.
Edit: I reproduced it. I had removed this line https://codeberg.org/soundtouch/soundtouch/src/commit/d994965fbbcf0f6ceeed0e72516968130c2912f0/CMakeLists.txt#L10. Removing the line - no issues.
jpsdr
12th April 2025, 13:52
Big :thanks:
Now i can build the .lib, and build the avs plugin with llvm. Because of course, building with llvm but using the .lib created with msvc didn't work.
What surprised me, in a good way, is that the .lib provided by Devil SDK worked with both msvc and llvm.
StvG
12th April 2025, 15:17
Because of course, building with llvm but using the .lib created with msvc didn't work.
Remove "/GL" when building with msvc and you will not have issues to use this lib when building avs with clang-cl.
jpsdr
13th April 2025, 10:18
:thanks: again... ;)
I think the "best" maybe is to be able to build everything with llvm (or the same toolchain for another compiler), but this is good to know.
And this probably answer the fact that i can use the Devil lib with llvm.
qyot27
21st April 2025, 13:55
AviSynth+ 3.7.5 has been released. (https://github.com/AviSynth/AviSynthPlus/releases/tag/v3.7.5) There were some things that required a hotfix (particularly on non-x86 platforms), so the list of changes from 3.7.4->3.7.5 is pretty small.
CMakeLists.txt: if CMAKE_BUILD_TYPE isn't set, use Release
Update build.yml, retire unsupported 20.04, add 24.04
Fix an llvm syntax warning.
rstdoc: update change log
Bump to IF v11.1: Fix AVS_Value 64 bit data member declaration for 64 bit non Intel (X86_X64) systems.
rstdoc: open 3.7.5 change log, add Raspberry pi stuff to posix.
Fix gcc compilation warning
Fix: resizer crash for non-intel (e.g. aarch64), regression in 3.7.4
Fix #434: YtoUV crash, regression since 61d2c9a
Add pkgconf->cmake detection fallback message for SoundTouch
avisynth+_arm64.iss: assorted fixups
plugins/CMakeLists.txt: fix VDubFilter build check
Remove upx.exe from the source tree
wonkey_monkey
21st April 2025, 17:27
:thanks:
amayra
22nd April 2025, 20:30
Why does AVS+ use a file compressor like UPX anyway ?
qyot27
23rd April 2025, 02:54
AviSynth 2.5/2.6 were UPX-packed, and simply out of inertia some of my early builds of AviSynth+ were as well. But I stopped doing that literally 10 years ago (https://forum.doom9.org/showthread.php?p=1719797#post1719797), and the UPX-packed DevIL.dll that was stored in the source tree was changed to an unpacked one in 2020 because it was a hassle to remember to unpack it before building the installer (and of course, the vendored binaries/libraries don't exist in the source tree now anyway).
tormento
23rd April 2025, 04:16
Why does AVS+ use a file compressor like UPX anyway ?
You can anyway unpack them.
pinterf
23rd April 2025, 08:43
Thanks, qyot27.
Recently, I spent about ten times more time on a topic than I was originally inteded to, but it's an interesting one. Since qyot27 released an aarch64 Windows version of Avisynth+ (Arm64, specifically Arm64-v8 or v8.4a?), I thought I'd add Neon intrinsic support. (Think of Arm Neon as similar to SSE2 or AVX2 on Intel.)
I read the Arm documentation, and the intrinsics are logical and easy to understand, so it wouldn't take long to convert existing Avisynth code to Neon. Since this seemed straightforward, I decided to do it using real Neon intrinsics instead of the "header" method, which translates existing Intel SIMD to more or less usable Arm SIMD code.
To test on Arm, I need a cross compiler and a hardware and an OS.
I have an i7-11700 with plenty of processing power and RAM, so I tried installing Win11 under QEMU. Unfortunately, the how-to guides on the Internet were made before Win11 24H2, which closed the infamous TPM2.0 registry cheat method of installation. I went back to a previous Win11 23H2, which I successfully installed under QEMU. However, it was ridiculously slow - remember, this is real emulation - so slow that I couldn't even start a command prompt. By the time the start menu or search box appeared, a timeout occurred, and the menu collapsed back. :) I both had a system and not.
Fortunately, my sons bought a Raspberry Pi 5. One is using it for growing grapefruit seeds and monitoring soil humidity :), while the other is engaged in web development, so I borrowed his Pi5 for my Avisynth needs. Yes, real aarch64 hardware, no emulation, and with quite usable compilation speed. I successfully built ffmpeg and Avisynth 3.7.4 and started some tests.
Soon, some configuration issues were discovered in the build process, which were fixed and clarified in 3.7.5 in the build environment (See qyot27's changes, fixing default Release optimization when e.g. Ninja was used).
First, I decided to make our resampler code in Avisynth - the C version -more compiler-friendly (and finish some optimization tasks that were postponed in the 3.7.4 release). Vectorizing friendly C code means that even from well-written C, a good compiler would generate very quick SIMD instructions. This is what I've been doing in past weeks: modify, test, benchmark. First on Windows, then on Raspberry Pi 5 Arm64.
Now I can say that MSVC is not capable of any optimization on integer values (e.g., 8-16 bit pixel values) from C code. I tried to help MSVC by writing code that would assist it, but in vain. After a week, I reached the point where I don't want to fight anymore; I cannot win the battle against the compiler's limitations and ignorance.
What works in MSVC's own C++ compiler:
What is already written in direct Intel SIMD code.
- 32-bit float arrays. Maybe. Such operations would be realized and compiled into SIMD code.
- Use MSVC when you need to support ancient OSs.
Conclusion: I'd ban Windows MSVC Microsoft compiler builds for today's processors in use cases where we process integer data and no handcrafted SIMD code is not available.
What to use instead? MSVC + clang-cl or LLVM is perfectly fine. Also, Intel ICX, which is LLVM-based as well. gcc on non-Windows is fine as well.
For Intel/AMD64 processor code, LLVM wins over GCC (as of 2025) by seeing the code it generates (Godbolt Compiler Explorer is a great tool!). The GCC compiler is good, but it's not on LLVM's level. LLVM detects and utilizes many more tricks than any of the others, which surprised me.
And now, some benchmarks.
Horizontal resapling code compiler (Win64, SSE2, etc means the max processor level, the compiler can utilize), 8, 10 and 16 bit.
ClangCl: what VS2022 supports out of box
Intel: Intel C++ Compiler 2025 (LLVM 19, I think)
Figures are in FPS(bit depth)
417(8) 463 (10) 360(16) from C, MSVC SSE2 3.7.4
597(8) 631(10) 651(16) from C, Intel SSE4.2 3.7.4
1183(8) 1193(10) 889(16) from C, Intel AVX2 3.7.4
91(8) 83(10) 56(16) from C, MSVC SSE2 3.7.6
477(8) 468(10) 292(16) from C, ClangCl SSE2 3.7.6
429(8) 468(10) 1327(16)(!) from C, Intel SSE2 3.7.6
1734(8) 2545(10) 1580(16) from C, Intel SSE4.2 3.7.6
2173(8) 2620(10) 1804(16) from C, Intel AVX2 3.7.6
3800(8) from SIMD, MSVC AVX2
2870(8) from SIMD, Intel C++ 2025, SSSE3
4370(8) from SIMD, Intel C++ 2025, AVX2
The figures show:
- The C code can be written so as a good compiler can turn it easily to SIMD code.
- MSVC own compiler: no comment
- When the compiler can utilize a more modern processor instruction set (like we build it for "native" arch), speed benefits a lot.
DTL
23rd April 2025, 20:53
It is also good to test with different frame sizes (relative to typical CPU cache size of about 2..20 MBytes ?) and multiplied to threads number as we have frame-based multithreading in current AVS+. Like with 3 different frame size:
1. Very small - buffer size much less of 2 MBytes.
2. Medium - buffer size is about 2..8 MBytes.
3. Big - buffer size is significantly more of 2..8 MBytes.
Also as current resizer is dual-1D it is good to test H+V changing of frame size (like 2x width and 2x height). Big enough number of tests may be required.
Most benefit of the 'good from-C' compiler expected on poorly SIMD-optimized parts of software as we have less and less human resources for SIMD optimizing and expected AI compilers may still helps somehow.
wonkey_monkey
24th April 2025, 12:23
What (if anything) is considered the correct way to ask a user for a colourspace as a filter parameter? Expect a string and convert with ColorSpaceNameToPixelType (or it's C++ equivalent)?
Could/should pixel type numbers be exposed as script function constants?
PS Has something happened to AVSMap recently? I was trying to compile my program after installing 3.7.5 and it was giving me unresolved external errors (I think, might have something different, but it was definitely linking-related), but a rebuild seem to fix it.
qyot27
25th April 2025, 03:40
Getting the macOS builds ready for 3.7.4 stalled so long (as a side effect of my access to an Intel version of macOS not working too well this time around, and waffling about where to draw the cutoff for the minimum OS version) that 3.7.5 ended up getting released first. It's probably just as well, since that ARM64 resizer issue that got fixed in 3.7.5 probably also affected macOS.
But I just fixed that issue by uploading the macOS build for 3.7.5. Unlike previous installers for macOS, this time, we have a Universal Binary, so there aren't separate installers for Intel vs. Apple Silicon. The minimum OS version is also set to macOS 13 Ventura, as that is the oldest version still supported by Apple. While it does limit the range of Intel Macs that can be installed to, there is always OpenCore-Legacy-Patcher or you could still build the binaries yourself (and given the differences introduced in 10.15 Catalina, if you're using anything older than that, you'd probably be better served by building it yourself). Unless something drastic has regressed lately, it's still possible to build AviSynth+ for Tiger (10.4) and Leopard (10.5) on PowerPC if you have the patience to let Tigerbrew compile much newer versions of the build tools (CMake, GCC, etc.), so...
Also, between having to disable Gatekeeper to run stuff that isn't code-signed on Apple Silicon (unless, like I mentioned above, you built it yourself) and the shift toward using RPATH shenanigans, the optimal long-term solution for native macOS support for AviSynth+ as well as client applications that use it will be for a package to get added to MacPorts and Homebrew, as they can deal with that weirdness without the user necessarily having to worry about it.
PoeBear
30th April 2025, 08:36
Is there a world where the comment and the backslash system could co-exist, similar to the "bug report"/non-working example from the documentation (https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/syntax/syntax_the_full_grammar.html)?
ColorBars
ShowFrameNumber
Trim(0,9) # select some frames \
+ Trim(20,29)
I often do similar backslash uses when working with multiple Trims, often from multiple sources. Sometimes it's nice to throw in a comment on each Trim to remind myself why its switching sources. Currently, if I really need a comment, I have to section the Trims it into different clips, then merge them, eg:
ColorBars
ShowFrameNumber
scene1=last.Trim(0,9) #main color footage
scene2=last.Trim(20,21).Grayscale() #black and white scene, remote chroma
scene3=last.Trim(20,29) #back to main color footage
scene1+scene2+scene3
which can get tedious if there's a lot of clips. A long project with multiple sources can get into the many dozens. The more clips, the more chance to get confused by all the Trims and why they exist lol. Would love some 3rd type of comment that is lower precedence than the backslash. It would keep scripts shorter/cleaner, and help when working in the middle of the footage, eg inserting a new Trim without renaming each of the following clips
wonkey_monkey
30th April 2025, 10:25
Is there a world where the comment and the backslash system could co-exist, similar to the "bug report"/non-working example from the documentation (https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/syntax/syntax_the_full_grammar.html)?
Can I interest you in ShebangMod (https://forum.doom9.org/showthread.php?p=1967744) and the associated ScriptMonkey plugin? Because I couldn't interest anyone else :D You can put comments wherever you like and you might not even need backslashes. I can't remember if it allows chaining to cross lines but I can look into adding that.
The current version is forked from AviSynth 3.7.2 but I can compile it again, or you can apply the small changes yourself to the latest source code.
Gavino
30th April 2025, 17:56
Is there a world where the comment and the backslash system could co-exist, similar to the "bug report"/non-working example from the documentation (https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/syntax/syntax_the_full_grammar.html)?
Yes, just use the alternative comment form /* ... */, so the non-working example becomes the working:
ColorBars
ShowFrameNumber
Trim(0,9) /* select some frames */ \
+ Trim(20,29)
qyot27
30th April 2025, 19:09
Even though Gavino beat me to it, I have another point to make:
Is there a world where the comment and the backslash system could co-exist, similar to the "bug report"/non-working example from the documentation (https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/syntax/syntax_the_full_grammar.html)?
I often do similar backslash uses when working with multiple Trims, often from multiple sources. Sometimes it's nice to throw in a comment on each Trim to remind myself why its switching sources. Currently, if I really need a comment, I have to section the Trims it into different clips, then merge them, eg:
which can get tedious if there's a lot of clips. A long project with multiple sources can get into the many dozens. The more clips, the more chance to get confused by all the Trims and why they exist lol. Would love some 3rd type of comment that is lower precedence than the backslash. It would keep scripts shorter/cleaner, and help when working in the middle of the footage, eg inserting a new Trim without renaming each of the following clips
# isn't the only comment type in AviSynth. C-style comments /* */ are also valid (as well as [* *] for nested comments), and do work in the above example, and in other contexts¹. Essentially, # works like C++-style // comments, and the issue to me seems less about the backslash than it is about how implicit last works when using the splice shorthand syntax. The way others got around it (as per the examples in the Github issue and the old forum posts) was by putting the backslash at the start of the second line, rather than at the end of the first.
¹Like commenting out a line when initializing an array variable that spans multiple lines. # fails entirely for this, you have to use /**/, and don't include the backslash in the comment.
The bug report the documentation mentions seems to have originated here:
https://github.com/AviSynth/AviSynthPlus/issues/6
which links back to
https://forum.doom9.org/showthread.php?p=1651141#post1651141
and
https://forum.doom9.org/showpost.php?p=1653525&postcount=293
The more concerning thing that I can see here is that there is something clearly wrong about the Trim operation in that example:
ColorBars
ShowFrameNumber
Trim(0,9) # select some frames \
+ Trim(20,29)
As copied directly from the documentation, this produces 1 frame.
avs2yuv -raw test.avs -o /dev/null
Warning: output will not contain any headers!
You will have to point resolution, framerate and format (and duration) manually to your reading software.
Avs2YUV 0.30
Script file: test.avs
Resolution: 640x480
Frames per sec: 30000/1001 (29.970)
Total frames: 1
Progress Frames FPS Elapsed Remain
[ 0.0%] 0/1 0.00 0:00:00 0:00:00
Started: Wed Apr 30 13:13:52 2025
Finished: Wed Apr 30 13:13:52 2025
Elapsed: 0:00:00
while
ColorBars
ShowFrameNumber
Trim(0,9) /* select some frames */ \
+ Trim(20,29)
produces 20, as the Trim commands would imply:
$ avs2yuv -raw test.avs -o /dev/null
Warning: output will not contain any headers!
You will have to point resolution, framerate and format (and duration) manually to your reading software.
Avs2YUV 0.30
Script file: test.avs
Resolution: 640x480
Frames per sec: 30000/1001 (29.970)
Total frames: 20
Progress Frames FPS Elapsed Remain
[ 95.0%] 19/20 1900.00 0:00:00 0:00:00
Started: Wed Apr 30 13:15:41 2025
Finished: Wed Apr 30 13:15:41 2025
Elapsed: 0:00:00
The implicit last is being set to *something*, and the Trim(20,29) command is appending to it, but it's all getting trashed down to a single frame if the backslash before the splice is commented out by a #. The documentation says that it's not returning [0..9,20..29], which is correct, but it's also not returning either one of [0..9] or [20..29] (or [20..29] appended to...whatever last was set to).
Secondarily, and going back to the point I made above about the arrays, is there any reason why the multi-line syntax needs to work the way it does when enclosed by any of the grouping syntax elements?
It's been a while, but I don't recall whether the {} in the function syntax require backslashes to allow lines to be spanned, because function definitions work more like C than typical script, and you'd only need the multi-line spanning in a case where the command inside the function would normally need it, but not the function as a whole.
And again, if you're initializing an array, I don't see why we'd need backslashes between the [] if it's just counting elements between those two characters. Is there some alternate use of these things that means that usage is ambiguous and multi-line span with backslash *needs* to still apply to them?
wonkey_monkey
30th April 2025, 21:26
Implicit last in this case is, I think, Trim(0,9). I would guess that "+" is inventing its own 0-frame clip for the LHS (based on the RHS?), since that is empty, then trim(20,29) acts on implicit last ("Trim(0,9)") - but since implicit last doesn't have frames 20-29, it just returns the last frame of it, which is frame 9.
Edit: actually it probably makes more sense that the "+" is just nulling itself in parsing: [null] + x => x
qyot27
30th April 2025, 22:20
Edit: actually it probably makes more sense that the "+" is just nulling itself in parsing: [null] + x => x
That does seem to be exactly what it's doing, which is leading to Trim(20,29) returning frame 9 instead. I don't think that's* expected behavior, but I could be wrong.
*Trimming a frame range that doesn't exist, I mean. -1 obviously has a special meaning, but a positive range that lies outside the valid already-trimmed range? Or was this the same thing that people complained about last time because it was an anti-feature they relied on?
So I guess here's a different question: within the parser, are comments removed first (as a sort of dead code elimination, the way a compiler would do it) before being executed? And if it does, and you comment a line, is the line blanked, or is it removed? Meaning: the newline is collapsed so that when you comment out line 2, does line 3 become line 2 or does it stay line 3 and line 2 still exists but empty? Practical experience seems to point toward the latter, since you can't comment out a line in the middle of a multi-line array initializer, even though most people would think it should collapse and be treated as if the line was deleted entirely.
wonkey_monkey
30th April 2025, 23:53
Well you can't do this:
ColorBars(\
width = 1024,\
/* asduhsd */
height = 1280)
or
ColorBars(\
width = 1024,\
# asduhsd
height = 1280)
So it seems it doesn't remove newlines near comments.
I would say AviSynth syntax is a tad outdated, hence my efforts to get around its limitations with ShebangMod. Just changing it outright would be too disruptive, especially when you've got things like ScriptClip to take into account, but an opt-in with a special header line seems like a good way to go (e.g. "#!AviSynth4"). Perhaps one simple modernisation could be "If you encounter a parsing error due to a newline, remove the newline and try again"?
Though that wouldn't help in the + Trim case above...
In Javascript you can do:
x = 6
+4
alert(x)
and it will alert "10". So maybe that works the opposite way - if you get a parsing error, assume an end of statement and try again. You can also force and end of statement with ";" of course, so:
x = 6;
+4
alert(x)
comes back as "6".
Gavino
1st May 2025, 09:53
That does seem to be exactly what it's doing, which is leading to Trim(20,29) returning frame 9 instead. I don't think that's* expected behavior, but I could be wrong.
*Trimming a frame range that doesn't exist, I mean. -1 obviously has a special meaning, but a positive range that lies outside the valid already-trimmed range? Or was this the same thing that people complained about last time because it was an anti-feature they relied on?
So I guess here's a different question: within the parser, are comments removed first (as a sort of dead code elimination, the way a compiler would do it) before being executed? And if it does, and you comment a line, is the line blanked, or is it removed? Meaning: the newline is collapsed so that when you comment out line 2, does line 3 become line 2 or does it stay line 3 and line 2 still exists but empty? Practical experience seems to point toward the latter, since you can't comment out a line in the middle of a multi-line array initializer, even though most people would think it should collapse and be treated as if the line was deleted entirely.
Yes, a unary '+' is simply treated as a null-op (even when applied to a clip, which doesn't make much sense).
And Trim clamps its frame arguments to the frame range of the source clip, so +Trim(20,29) applied to a 10-frame clip becomes, in effect, Trim(9,9).
Commenting out an entire line does not make the line disappear, since the new line at its end is not part of the comment!
(unless of course it's inside a block comment that has not yet been closed and thus extends onto the next line...)
3.7.5 release again missed from first post. Also 3.7.4 dated of 2024 instead of 2025.
tebasuna51
3rd May 2025, 11:09
3.7.5 release again missed from first post. Also 3.7.4 dated of 2024 instead of 2025.
Modified first post (owner pinterf not qyot27), now Current link go always to the last version.
pinterf
10th May 2025, 15:23
Modified first post (owner pinterf not qyot27), now Current link go always to the last version.
Thanks. I forgot about it. Sometimes I completely disconnect from forums, or else they just suck me in, leaving less time for my actual tasks (this time also Avisynth-related).
By the way, looking at the download counts, the Windows ARM version has more downloads than the XP-specific one. I suppose this is just out of curiosity, since plugin support is quite limited, to say the least.
FranceBB
10th May 2025, 18:50
looking at the download counts, the Windows ARM version has more downloads than the XP-specific one. I suppose this is just out of curiosity, since plugin support is quite limited, to say the least.
Speaking of the XP specific version, the installer is installing the "wrong" ImageSeq.dll in plugins+ and DevIL.dll in system32 instead of the XP specific ones. After swapping them with the ones from the "files only" option under the "legacy" subfolder everything worked perfectly again. :)
About ARM, Windows on ARM has very limited adoption but the laptops are definitely out there. A friend of mine tried it. It's definitely faster than running the x86 version translated on the fly to ARM, but the problem with the ARM version of Avisynth is that you can't have the ARM frameserver run natively and the x86 incompatible plugins run via the translation layer, rather everything has to be ARM (running natively) or x86 (running via the translation layer). You can't mix and match, which is a bummer. By the way, my use case for ARM was different as I was trying to see if I could save some bucks on AWS by running c6g.2xlarge instances (8c/8th 16GB of RAM) powered by a Graviton 2 ARM host instead of using the c6i.2xlarge instances (8c/8th 16GB of RAM) powered by an Intel Xeon 8375C x86_64 host.
$0.3648 (x86) - $0.2918 (ARM) = $0.073 per hour which corresponds to a 20% saving / reduction.
So, if the ARM version manages not not be 20% slower in encoding it will save some pennies on my Avisynth farm.
qyot27
11th May 2025, 00:53
Speaking of the XP specific version, the installer is installing the "wrong" ImageSeq.dll in plugins+ and DevIL.dll in system32 instead of the XP specific ones.
There is no DevIL.dll in the xp installer.
Clearly one of the libraries in the DevIL dependency chain has issues even when you use -T v141_xp to build all of them.
but the problem with the ARM version of Avisynth is that you can't have the ARM frameserver run natively and the x86 incompatible plugins run via the translation layer, rather everything has to be ARM (running natively) or x86 (running via the translation layer). You can't mix and match, which is a bummer.
ARM64X support isn't quite ready (https://github.com/mstorsjo/llvm-mingw/issues/475) in the toolchain. Even when support for ARM64X (aka ARM64EC) lands, I think it's fairly obvious there's a different 800lb. gorilla to contend with there and why you still wouldn't be able to mix and match architectures, with a handful of possible exceptions.
Not to mention whether it applies to a library loading other libraries (like AviSynth+ and its relation to its plugins) vs. an application loading a library (like FFmpeg loading the AviSynth+ core) is something I don't think I've seen a definitive answer to. What I remember of the tests I attempted is that it didn't work in either case, but that was sometime between July-October of last year.
While testing different SIMD versions of processing functions some feature of SetMaxCPU() found with VirtualDub: It does not switch CPU type if 'reload (F2)' script. To really switch CPU type and SIMD functions, full VirtualDub process restart is required.
I do not not know how it works with other editors with avisynth.dll loading like AVSpmod.
Test script:
SetMaxCPU("something")
version
Info()
pinterf reply is normal feature of Windows .dlls loading (and current implementation in AVS+ ?) - https://github.com/AviSynth/AviSynthPlus/pull/440#issuecomment-2868872022
Selur
18th May 2025, 07:49
As a side note: It really is annoying that sometimes default plugins are in plugins/plugins+/plugins64/plugins64+ when using files_only.
(I ended up loading those plugins manually from a separate folder, to not having to check where the plugins are located on the release.)
=> I'm fine, but not to confuse others, maybe just stick with 'plugins' and that's it.
Maybe a function that accepts a file name only and looks in the two folders of the matching bitness on its own?
tormento
18th May 2025, 16:15
Is there any good samaritan to build AVS+ version of DFTTest2 (https://github.com/AmusementClub/vs-dfttest2)?
I've asked WolframRhodium who kindly refused.
Wouldn't be so bad to have a GPU accelerated version of DFTTest.
@pinterf? @anyone?
Thanks for any effort.
qyot27
18th May 2025, 20:14
As a side note: It really is annoying that sometimes default plugins are in plugins/plugins+/plugins64/plugins64+ when using files_only.
(I ended up loading those plugins manually from a separate folder, to not having to check where the plugins are located on the release.)
=> I'm fine, but not to confuse others, maybe just stick with 'plugins' and that's it.
I had to go back and check old releases, because I had no idea what this was referring to.
Only 3.5.0 deviates from the norm concerning the plugins[+|64|64+] naming, and given this post (https://forum.doom9.org/showthread.php?p=1902703#post1902703) from shortly after release, it appears that I hadn't prepared a filesonly package for 3.5.0, so it was added after the fact, presumably by pinterf. GitHub seems to have done something to the file timestamps for anything before mid-December 2021, so I can't see exactly when in relation to the release that the 3.5.0 filesonly was uploaded.
All of the other release filesonly archives follow the same pattern, because I just copy the contents of the Output/ directories MSVC creates directly into an AviSynthPlus_VERSION_DATE-filesonly directory, under the relevant build architecture (x64, x64-xp, x86, x86-xp). There have been a couple of times the architecture name differed (3.4.0 used 'amd64' and 'i686', 3.7.0 used a slightly more verbose 'x86-64|-32[_xp]'), but that was it.
arm64 test builds were present in the packages for 3.7.0, 3.7.1, and 3.7.2, but was skipped in 3.7.3, IIRC because it was languishing with virtually zero discussion around it (logical, because it was *only* in the filesonly package and did not have an installer).
arm64 returned in 3.7.4 and 3.7.5 once we actually did introduce an installer, but - as I've mentioned in other posts - part of that mainlining of the WinARM installer was changing how we build for that platform, so the arm64 directory on 3.7.4 and 3.7.5 is laid out completely differently from the earlier test builds.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.