• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

Fun with vinyl measurements

OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
DIN 45 453 ATOC9MLii Azimuth set by Ortofon test record,maybe not so much tilt I think
1713208856764.png


Merolemez Crosstalk track
1713209022669.png


Not sure what angle this gives..
1713210159779.png
 

DSJR

Major Contributor
Joined
Jan 27, 2020
Messages
3,416
Likes
4,573
Location
Suffolk Coastal, UK
DIN 45 453 ATOC9MLii Azimuth set by Ortofon test record,maybe not so much tilt I think
View attachment 363973

Merolemez Crosstalk track
View attachment 363974

Not sure what angle this gives..
View attachment 363975
What's with the add-on between carttidge and headshell? Nylon screws? and where's the finger lift SME carefully designed? The cartridge has azimuth issues according to the pic as viewed from the front...

Seriuously, if you won't listen to me, please condsider using the screws and nuts (with washers) AT supplied and bolt the thing directly to the headshell SME. No point whatsoever in coupling/decoupling the pickup from an SME V which is one of ther better arms in resonance terms and the OC9's do have nice solid bodies for direct mounting ;)
 

Icewater_7

Member
Joined
May 18, 2023
Messages
51
Likes
11
Location
El Dorado Hills, CA
What's with the add-on between carttidge and headshell? Nylon screws? and where's the finger lift SME carefully designed? The cartridge has azimuth issues according to the pic as viewed from the front...

Seriuously, if you won't listen to me, please condsider using the screws and nuts (with washers) AT supplied and bolt the thing directly to the headshell SME. No point whatsoever in coupling/decoupling the pickup from an SME V which is one of ther better arms in resonance terms and the OC9's do have nice solid bodies for direct mounting ;)
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
@DSJR Everything you see is for a good reason:

What you see is Wally Fulcrum . Not a decoupler. I use it since the SME V has no Azimuth adjustments. Azimuth needs correction on most cartridges.

SME lift is not used to minimize weight since the resonance of the cartridge/arm becomes a bit low with it included.

I cannot use the AT screws since they are too short with the Wally fulcrum. The nylon screws are the lightest option. Plots from CA TRS-1007 shows that the arm and cartridge are solid with minimal resonances
 

DSJR

Major Contributor
Joined
Jan 27, 2020
Messages
3,416
Likes
4,573
Location
Suffolk Coastal, UK
@DSJR Everything you see is for a good reason:

What you see is Wally Fulcrum . Not a decoupler. I use it since the SME V has no Azimuth adjustments. Azimuth needs correction on most cartridges.

I SME lift not used to minimize weight since the resonance of the cartridge/arm becomes a bit low with it included.

I cannot use the AT screws since they are too short with the Wally fulcrum. The nylon screws are the lightest option. Plots from CA TRS-1007 shows that the arm and cartridge are solid with minimal resonances
I'm calling this another answer to an inaudible problem based on my experiences of old. The mass of decent screws is as nothing with an AT moving coil in an SME V and the azimuth as pictured above is way off if you check the reflection on the mirrir/plate the stylus is sitting on...

Vinyl is such a compromised thing at the cutting stage let alone pressing and playing, I'd seriously suggest setting the cartridge up as intended. Either that or ditch the solidly made SME and return to say, a 309 or M2 -9 which should allow the azimuth adjustment you feel is so important (heck, we can't hear 20dB separation that easily let alone 30dB+ the AT offers). The SME IV and V was all about getting it right in manufacture and making the entire thing as one-piece as possible, but at the time I was a fan of the 309 which worked so well.

Sorry, I was setting these things up and listening, tweaking and so on for most of my working life and can't help it, knowing what I believe I learned while doing it. Record weights are another thing which mainly cause increased main bearing wear and they're used for fashion as 'everyone else in the vinyl club' uses them so it becaomes a convention and habit..

Just trying to get you a better sound and performance from the arm and cartridge you've chosen. Add-ons like this *for components at this level* really aren't necessary as AT do seem to make their MC's pretty consistently :)
 
Last edited:
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
I would like a SM V with detachable head shell, they exist. And vinyl not very accurate, Apart from that I do not agree to disregard azimuth . The parallax error is not good to judge the stylus bottom, look at the headshell gap instead. Let us leave it at that.
 
Last edited:

Thomas_A

Major Contributor
Forum Donor
Joined
Jun 20, 2019
Messages
3,469
Likes
2,467
Location
Sweden
I'm calling this another answer to an inaudible problem based on my experiences of old. The mass of decent screws is as nothing with an AT moving coil in an SME V and the azimuth as pictured above is way off if you check the reflection on the mirrir/plate the stylus is sitting on...

Vinyl is such a compromised thing at the cutting stage let alone pressing and playing, I'd seriously suggest setting the cartridge up as intended. Either that or ditch the solidly made SME and return to say, a 309 or M2 -9 which should allow the azimuth adjustment you feel is so important (heck, we can't hear 20dB separation that easily let alone 30dB+ the AT offers). The SME IV and V was all about getting it right in manufacture and making the entire thing as one-piece as possible, but at the time I was a fan of the 309 which worked so well.

Sorry, I was setting these things up and listening, tweaking and so on for most of my working life and can't help it, knowing what I believe I learned while doing it. Record weights are another thing which mainly cause increased main bearing wear and they're used for fashion as 'everyone else in the vinyl club' uses them so it becaomes a convention and habit..

Just trying to get you a better sound and performance from the arm and cartridge you've chosen. Add-ons like this *for components at this level* really aren't necessary as AT do seem to make their MC's pretty consistently :)
Most adjustments of cartridge engine vs groove walls are within a few degrees. Cartridges are individuals. Crosstalk is a form of distortion/noise-problem depending if signals are correlated or uncorrelated. Therefore, low and even crosstalk is a good thing even if it means tilting the cartridge body.
 

DSJR

Major Contributor
Joined
Jan 27, 2020
Messages
3,416
Likes
4,573
Location
Suffolk Coastal, UK
Most adjustments of cartridge engine vs groove walls are within a few degrees. Cartridges are individuals. Crosstalk is a form of distortion/noise-problem depending if signals are correlated or uncorrelated. Therefore, low and even crosstalk is a good thing even if it means tilting the cartridge body.
But this is a VERY expensive SME V tonearm where much design care was made forty odd years back to get the headshell level and the arm pipe as rigid as possible. I remember Rega RB arms of old sometimes had slight errors in the head part due to paint ant not being skimmed flat (Michell used to do a huge 'engineering finish-off' on the headshell mounting surface and so on in their techno-arm and Rega simply make and finish them better than ever today) . The AT OC9 is a long established range of MC cartridges, now a range sharing a basically common solid body and mount but with a range of cantilever-stylus assemblies and again, I'd respectfully suggest good consistency these days with internals and also the diamond setting, which I admit used to be a huge variable in other makes some decades back..

I'm just trying to suggest to get the variables down as much as possible here - and again point to the pic posted above which shows the cartridge is well tilted off judging by its reflection - Why spend such a huge amount new or used on an exalted tonearm and destroy the firm coupling in the headshell which can and does introduce resonances not there before - why tonearms with 'SME Style headshells all had resonances in the lower midrange due to the coupling which 'one piece' or bonded-style arms became the fashion in Europe at least. Got to say I'm surprised if this sample did need to be tilted off this way to get a symmetrical separation figure. My Decca Microscanner had great *perceived* imaging with good left to right differentiation, but all Deccas measure very poorly in this aspect, around 20dB at best I recall - the AT is over 10dB better I believe in the important midrange.

I forget now (with apologies) how anal vinyl enthusiasts can be. I shan't say more, but the dealer/setter-upper in me couldn't let it lie without saying something. the OP is of course, quite entitled to do what the heck they like, but it does seem somewhat nonsensical to me to compromise the cartridge to tonearm coupling this way - my apologies again.
 

JP

Major Contributor
Joined
Jul 4, 2018
Messages
2,296
Likes
2,476
Location
Brookfield, CT
I'd respectfully suggest good consistency these days with internals and also the diamond setting, which I admit used to be a huge variable in other makes some decades back..

It still is.
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
Here is the SME V with Wally fulcrum on the standard test record. No signs of degraded arm performance here


Some other day I can post a 5-500Hz arm resonance sweep, it shows possibly some more irregularities…
1713279368122.png

High resolution 0.18Hz by Rightmark app
Vertical low freq sweep
1713279512363.png



Lateral Low frequency sweep
1713279828258.png



Another turntable arm and cartridge, seem like the record that has blips at 16,50Hz and 160 Hz, not cart/tonearm.. NOW I REMEMBER the blips are the frequency markers in the track. The second turntable/arm clearly has a resonance at 81hz..
Not same recording EQ used so it is sloped differently
1713288932085.png



I wonder whaf is causing the 80Hz resonance on the light straight arm, could it be cured?
 

Attachments

  • 1713280377966.png
    1713280377966.png
    51.3 KB · Views: 15
  • 1713286911446.png
    1713286911446.png
    141.2 KB · Views: 13
Last edited:

Thomas_A

Major Contributor
Forum Donor
Joined
Jun 20, 2019
Messages
3,469
Likes
2,467
Location
Sweden
But this is a VERY expensive SME V tonearm where much design care was made forty odd years back to get the headshell level and the arm pipe as rigid as possible. I remember Rega RB arms of old sometimes had slight errors in the head part due to paint ant not being skimmed flat (Michell used to do a huge 'engineering finish-off' on the headshell mounting surface and so on in their techno-arm and Rega simply make and finish them better than ever today) . The AT OC9 is a long established range of MC cartridges, now a range sharing a basically common solid body and mount but with a range of cantilever-stylus assemblies and again, I'd respectfully suggest good consistency these days with internals and also the diamond setting, which I admit used to be a huge variable in other makes some decades back..

I'm just trying to suggest to get the variables down as much as possible here - and again point to the pic posted above which shows the cartridge is well tilted off judging by its reflection - Why spend such a huge amount new or used on an exalted tonearm and destroy the firm coupling in the headshell which can and does introduce resonances not there before - why tonearms with 'SME Style headshells all had resonances in the lower midrange due to the coupling which 'one piece' or bonded-style arms became the fashion in Europe at least. Got to say I'm surprised if this sample did need to be tilted off this way to get a symmetrical separation figure. My Decca Microscanner had great *perceived* imaging with good left to right differentiation, but all Deccas measure very poorly in this aspect, around 20dB at best I recall - the AT is over 10dB better I believe in the important midrange.

I forget now (with apologies) how anal vinyl enthusiasts can be. I shan't say more, but the dealer/setter-upper in me couldn't let it lie without saying something. the OP is of course, quite entitled to do what the heck they like, but it does seem somewhat nonsensical to me to compromise the cartridge to tonearm coupling this way - my apologies again.
The SME is certainly a good arm. On the other side of the spectrum I have the delicate 4g Moerch UP-4 arm and a Shure V15Vx body, which is fitted with an extra shim of plastic (because the cartridge body and head shell is not really made for each other). None of the arms show any visible sign of resonances that are significant enough to colour the sound audibly. There are other examples in the cartridge thread where you can see notches in the frequency response that probably is related to arm resonances (usually in the 100-400 Hz range). The key here is to have an arm where resonances are kept in control (arm design, thickness, tube form, damping etc)

When it comes to cartridge, the mass of a typical cartridge is 5-10 g, while the effective tip mass is in the range of 0.2-0.4 mg of most cartridges produced today. Given a mass of 6 g cartridge and 0.2 mg effective tip mass you have a 30 000-fold higher mass of the cartridge body itself. Adding the arm of typical 10g effective mass as a unit with the cartridge gives you 16 g of effective mass, giving a 80 000-fold higher mass (2.7-fold increase). Also, the cartridge body itself is probably constructed in a way to counteract resonances, at least what is claimed by many manufacturers.

When it comes to coupling a surface to another, the best is to have two complete flat surfaces bolted together. This is used in probe-based ultrasound sonication to transfer high-frequency sound to the probe. This is however very high energy transfer that is not really the same as the vibrating stylus. The first isolating occurs in the stylus damper and then further of the mass and construction of the cartridge body. If anything, an exchangeable stylus of MM cartridges should make use of bolting to secure the stylus assembly to the body. Such exist today e.g. the MP-500 and also the former Linn K18, but there is actually no indication that it would improve distortion figures compared to a regular stylus that is just pressed into the body.

Taken together, I don't think the high-pressure bolting using flat surfaces is needed for arm-cartridge interface in vinyl playback. Good arm engineering and perhaps also a good construction of the cartridge body to avoid high-Q resonances and good fit of stylus assembly to the body is all what is needed.
 

DSJR

Major Contributor
Joined
Jan 27, 2020
Messages
3,416
Likes
4,573
Location
Suffolk Coastal, UK
The SME is certainly a good arm. On the other side of the spectrum I have the delicate 4g Moerch UP-4 arm and a Shure V15Vx body, which is fitted with an extra shim of plastic (because the cartridge body and head shell is not really made for each other). None of the arms show any visible sign of resonances that are significant enough to colour the sound audibly. There are other examples in the cartridge thread where you can see notches in the frequency response that probably is related to arm resonances (usually in the 100-400 Hz range). The key here is to have an arm where resonances are kept in control (arm design, thickness, tube form, damping etc)

When it comes to cartridge, the mass of a typical cartridge is 5-10 g, while the effective tip mass is in the range of 0.2-0.4 mg of most cartridges produced today. Given a mass of 6 g cartridge and 0.2 mg effective tip mass you have a 30 000-fold higher mass of the cartridge body itself. Adding the arm of typical 10g effective mass as a unit with the cartridge gives you 16 g of effective mass, giving a 80 000-fold higher mass (2.7-fold increase). Also, the cartridge body itself is probably constructed in a way to counteract resonances, at least what is claimed by many manufacturers.

When it comes to coupling a surface to another, the best is to have two complete flat surfaces bolted together. This is used in probe-based ultrasound sonication to transfer high-frequency sound to the probe. This is however very high energy transfer that is not really the same as the vibrating stylus. The first isolating occurs in the stylus damper and then further of the mass and construction of the cartridge body. If anything, an exchangeable stylus of MM cartridges should make use of bolting to secure the stylus assembly to the body. Such exist today e.g. the MP-500 and also the former Linn K18, but there is actually no indication that it would improve distortion figures compared to a regular stylus that is just pressed into the body.

Taken together, I don't think the high-pressure bolting using flat surfaces is needed for arm-cartridge interface in vinyl playback. Good arm engineering and perhaps also a good construction of the cartridge body to avoid high-Q resonances and good fit of stylus assembly to the body is all what is needed.
Many in my MM stash are 'microphonic' through the speakers when the arm is handled (it's admittedly a lively type so I have to choose some pickups carefully). The MC's I have here don't excite the arm at all fortunately. Biggest regret with the deck I use mainly (when I feel like playing a record) is the V15VMR I once used and on which the cantilever fractured after an accident. I believe it may be possible to splice it back together but it won't be cheap although I'd like to see if it can be done.

Some pickups with removable styli benefitted certainly in my experience by having a firmly fitting stylus assembly. Not sure the K18 really benefitted to be honest as the stylus assembly fitted in firmly vertically and not fore-aft, but it made for a conversation piece didn't it? Mk2 versions were good as I remember but many mk1's spontaneously collapsed for some reason.
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
Has anyone tried this Azimuth Script . I got it to run but have difficulty understanding how to analyse the file.. see post 37
@Echo OFF
SETLOCAL EnableDelayedExpansion
SETLOCAL ENABLEEXTENSIONS
TITLE Devinyl

:: Description: Vinyl Magic: vinyl subsonic filter, equipment corrections, and more

:: Usage: devinyl.cmd input-filename.wav (speedup factor)
:: (or no file name to process "input.wav"
:: output file name will have -processed.wav at end)

:: Author: Harby - stevehoffman.tv forums
:: Free for non-commercial hobbyist use
:: commercial azimuth use and future features (turntable setups, restoration..) TBD

:: ---- SETTINGS BELOW MUST BE CUSTOMIZED to your wants and needs ----

:SETTINGS

:: Adjust signal imbalance of phono pre and ADC electric path, dB. Negative: turn up left side
:: (this...if you can't send a low-level test signal into phono-in, mono it with y cables, and adjust your knobbies)
SET inchannelbalance=0.20

:: Signature/Profile-based noise reduction? (yes/no) 1st pass, for electrical noise/hum
:: (Must put 2+ seconds of "electric" silence at the start of file)
SET usenoisereduction=no
:: Noise reduction amount (of 0 to 1); heavy-handed even at 0.1, increase at your own peril:
SET NRstrength=0.9
SET NRseconds=2

:: Signature/Profile-based noise reduction? (yes/no) - 2st pass, mid-side, for vinyl noise
:: Must put more "surface noise" silence at the start of file -- after first silence segment
SET midsideNR=no
SET NR2strength=0.5
:: Seconds is the total number of seconds added AFTER the first segment of electric noise
SET NR2seconds=2


:: Magical cartridge azimuth correction in degrees (0 to disable and skip)
:: (use negative degrees if electrical alignment is twisted counter-clockwise looking from front)
SET azimuthsettingindegrees=0.9

:: Crosstalk specification of cartridge in minus dB, eg -29, or as discovered from analysis
:: (More crosstalk correction can also be used as a widening effect)
:: (disabled at 0 or positive numbers)
SET crosstalkdb=-32.0
:: If cartrige crosstalk is inverted/out-of-phase and actually over-widens the stereo? (yes/no)
SET iscrosstalkinverted=yes

:: If one calibrated channel still quieter after azimuth & crosstalk correction (total dB change). Negative: turn up left side
:: (this would be your cartridge's electrical channel imbalance)
SET channelbalance=-0.19

:: Subsonic resonance cutoff frequency, Hz (extremely sharp cut below, little effect above)
:: (0 to disable and skip)
SET sub=22
:: use 10th order Butterworth filter instead of even sharper sinc function?
SET butterworth=no
:: frequency of milder side-channel vertical rumble reduction
SET sidesub=70

:: Speed correction for reduced-speed disc transfers (using your normal RIAA preamp)
:: Set to 1.35 for 45 played at 33, etc (1.0 to skip)
:: Command line option will override
SET speedup=1.00
REM speedup=1.23496
:: the speedup performs resampling at 192kHz+; if you don't want your new high-resolution, set lower:
:: (use standard sample rates like 44.1 48 88.2 96 192)
SET speedupdownsample=96


SET usemidsideprocessing=yes
:: (if not set to yes, all mid-side magic including noise reduction is skipped)

:: Side-channel bass correction, in positive dB; 5 will restore width from a 150Hz 1st order highpass used in mastering
SET sidebassboostdb=1.3


:: Adjust output file to peak level, set to -dB. A positive integer to disable
SET normalizeto=2

:: Internal settings; set verbose to 3 to see all sox output, but will disable future clip detection
SET verbose=2
SET buffer=131072
SET progressbar=yes
SET processinggainreduction=6
SET disablecleanuptempfiles=no

:: This function instead takes a SHORT audio input file (like a test LP channel separation track) and
:: repeatedly steps it through a range of azimuth corrections, so you can analyze compiled output
SET forceazimuthanalysis=yes
:: Center position (degrees)
SET center=0
:: Width on each side of center (degrees) (if negative, stepping goes from + to - (cw to CCW), maybe confusing)
SET fromcenter=5
:: (if number of steps below is even, you don't get center point)
SET steps=41

:: similar, but doesn't do trigonometry, just an internal table from -5 to 5 degrees
:: this version is not filtered for automated analysis
SET forcereferencesteps=no


:SETTINGSDONE

:: PROGRAM STARTS HERE

IF /i "%forceazimuthanalysis%"=="yes" GOTO :findazimuth
IF /i "%~1"=="findazimuth" GOTO :findazimuth
IF /i "%2"=="findazimuth" GOTO :findazimuth %1

IF /i "%forcereferencesteps%"=="yes" GOTO :referencesteps
IF /i "%~1"=="referencesteps" GOTO :referencesteps
IF /i "%2"=="referencesteps" GOTO :referencesteps %1


CALL :setup %1 %2 %3 %4 %5
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :makeinput
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeinput subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :balancechannels %inchannelbalance%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to channel balance subroutine errors & CALL :cleanup & EXIT /B 1)

IF /I "%usenoisereduction%"=="yes" (CALL :noisereduction %NRstrength%) ELSE (ECHO STATUS: Skipping noise reduction)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to noisereduction errors & CALL :cleanup & EXIT /B 1)

CALL :azimuthcorrection %azimuthsettingindegrees%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to azimuthcorrection subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :crosstalk %iscrosstalkinverted% %crosstalkdb%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to crosstalk errors & CALL :cleanup & EXIT /B 1)

CALL :balancechannels %channelbalance%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to channel balance subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :subsonic %sub%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeinput subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :speedup %speedup%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to speedup errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :midside) ELSE (ECHO STATUS: Skipping all mid-side processing)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to midside function errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :midchannel)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to midchannel errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :sidechannel)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to sidechannel errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :unmidside)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to unmidside errors & CALL :cleanup & EXIT /B 1)

CALL :makeoutput %outfile%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeoutput errors & CALL :cleanup & EXIT /B 1)

PAUSE

CALL :cleanup
IF NOT %ERRORLEVEL%==0 (echo ..cleanup function had an error & EXIT /B 1)

EXIT /B 0


==== SUBROUTINES ====
:setup

:: TODO: search path and also install location for sox, set full location (and replace every call with variable)

sox --version >NUL 2>NUL
IF %ERRORLEVEL%==9009 (CALL :nosox)
sox --version >NUL 2>NUL
IF NOT %ERRORLEVEL%==0 (ECHO === SOX.EXE problem! SOX.EXE IS STILL MISSING OR ERRORS OUT & exit /b %ERRORLEVEL%)

rem echo parameters f1 2: %~f1 %2
rem echo parameters per1: %1


IF '%1'=='' GOTO :defaultfile
:: use full input file paths and temp directory
SET inpath=%~dp1
SET filebase=%~n1
SET fileext=%~x1
SET tempdir=%temp%\
SET outfile="%inpath%%filebase%-processed.wav"
GOTO :donesettingfiles

:defaultfile
:: default to no paths and default file name
SET inpath=
SET filebase=devinyl
SET fileext=.wav
SET tempdir=%temp%\
SET outfile="output-devinyl.wav"

:donesettingfiles

rem ECHO inpath---%inpath%
rem ECHO filebase---%filebase%
rem ECHO fileext---%fileext%
rem ECHO outfile---%outfile%

SET infile="%inpath%%filebase%%fileext%"
IF '%1'=='' SET infile="input.wav"
rem ECHO --- infile: %infile%

IF NOT "%2"=="" (SET speedup=%2)

IF NOT EXIST %infile% (GOTO :nofile & EXIT /B 1)

IF EXIST %outfile% DEL %outfile% & IF EXIST %outfile% (set DELERROR=1 & GOTO :cantdel)

set temp1file="%tempdir%%filebase%-temp1.wav"
IF EXIST %temp1file% DEL %temp1file% & IF EXIST %temp1file% (set DELERROR=1 & GOTO :cantdel)

set temp2file="%tempdir%%filebase%-temp2.wav"
IF EXIST %temp2file% DEL %temp2file% & IF EXIST %temp2file% (set DELERROR=1 & GOTO :cantdel)

set midfile="%tempdir%%filebase%-midtemp.wav"
IF EXIST %midfile% DEL %midfile% & IF EXIST %midfile% (set DELERROR=1 & GOTO :cantdel)

set sidefile="%tempdir%%filebase%-sidetemp.wav"
IF EXIST %sidefile% DEL %sidefile% & IF EXIST %sidefile% (set DELERROR=1 & GOTO :cantdel)

set noiseprofile="%tempdir%%filebase%-noiseprofile.wav"
IF EXIST %noiseprofile% DEL %noiseprofile% & IF EXIST %noiseprofile% (set DELERROR=1 & GOTO :cantdel)

IF "%DELERROR%"=="1" (EXIT /B 1)

call :subsetup
IF NOT %ERRORLEVEL%==0 (ECHO ERROR returned by subsetup & exit /b 1)

:setupdone
EXIT /B 0

:subsetup
:: subroutines need these, along with a temp1file input/output file defined

IF EXIST %tempdir%Math.vbs DEL %tempdir%Math.vbs >NUL
echo Wscript.echo Round(eval(WScript.Arguments(0)),15) >%tempdir%Math.vbs
echo WScript.Quit 2 >>%tempdir%Math.vbs
echo ' quit 2 shouldn't be reached if there is an error above it >>%tempdir%Math.vbs

set Result=ERROR
Call:Math round((%sub%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sub=%Result%

Call:Math round((%sidesub%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sidesub=%Result%

Call:Math round((%sidebassboostdb%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sidebassboostdb=%Result%

Call:Math round((%crosstalkdb%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set crosstalkdb=%Result%

Call:Math round((%channelbalance%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set channelbalance=%Result%

Call:Math round((%speedup%), 8)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set speedup=%Result%

Call:Math round((%normalizeto%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set normalizeto=%Result%

IF /I "%progressbar%"=="yes" SET progress=-S

:butterworth 10th order
SET ch1q=0.5062 & SET ch2q=0.5612 & SET ch3q=0.7071 & SET ch4q=1.1013 & SET ch5q=3.1970
SET ch1f=%sub% & SET ch2f=%sub% & SET ch3f=%sub% & SET ch4f=%sub% & SET ch5f=%sub%
:subsetupdone
EXIT /B 0


:makeinput
ECHO === Start: processing input ======================
:: MUST CALL THIS FUNCTION FIRST TO READ INPUT FILENAME to first temp file
sox --multi-threaded --buffer=%buffer% -V1 %progress% %infile% -b 32 %temp1file% ^
gain -%processinggainreduction% ^
pad 2 2
:makeinputdone
IF NOT EXIST %temp1file% (ECHO fail creating work from input file & EXIT /B 1)
EXIT /B 0



:subsonic
IF NOT "%1"=="" SET sub=%1
IF "%ch1q%"=="" call :subsetup
IF "%2"=="" SET butterworth=no
IF %sub% EQU 0 GOTO :subsonicdone
ECHO === Stage start: subsonic resonance filter ======================
IF /I "%butterworth%"=="no" (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
sinc -L %sub% -n 32767 ^
reverse ^
sinc -L %sub% -n 32767 ^
reverse
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: subsonic filter %sub% Hz & EXIT /B 1)
) ELSE (
:: sox command for 10th order
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
reverse ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
reverse
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: subsonic filter %sub% Hz & EXIT /B 1)
)
:subsonicdone
IF NOT EXIST %temp1file% (ECHO subsonic fail creating output & EXIT /B 1)
EXIT /B 0



:azimuthcorrection
:: input: (degrees in 360, range -45 to 45) (mute)
:: input: setup variables
:: input file: temp1file output file: temp1file

SET azimuthindegrees=%1
SET azmuted=no
IF /I "%2"=="mute" SET azmuted=mute

SET Result=ERROR
Call:Math round((%azimuthindegrees%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthindegrees=%Result%

Call:Math int(round((abs(%azimuthindegrees%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 225000 (ECHO ERROR: Azimuth correction at %azimuthindegrees% is impossible & EXIT /B 1)

IF NOT "%azmuted%"=="mute" ECHO === Stage start: azimuth correction ======================
call :getazimuth %azimuthindegrees% %azmuted%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees & EXIT /B %ERRORLEVEL%)

Call:Math Int(abs(%azimuthOppdB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in azimuth: checking db levels oppdb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthOppdB% dB Opp & EXIT /B 1)

Call:Math Int(abs(%azimuthSamedB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth checking db levels samedb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthSamedB% dB & EXIT /B 1)

if "%isazimuthclockwise%"=="yes" (
:cwazimuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2i%azimuthOppdB%, 2p,2p%azimuthSamedB%,1p%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: clockwise azimuth & EXIT /B 1)
) ELSE (
:ccwazumuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2p%azimuthOppdB%, 2p,2p%azimuthSamedB%,1i%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: counterclockwise azimuth & EXIT /B 1)
)
:azimuthcorrectiondone

IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (ECHO azimuth fail moving output & EXIT /B 1)
IF NOT EXIST %temp1file% (ECHO ERROR: azimuth correction fail creating output & EXIT /B 1)

IF NOT "%azmuted%"=="mute" echo Applied %azimuthdeg% degrees correction:
IF NOT "%azmuted%"=="mute" echo Same: %azimuthSamedB% dB Opposite: %azimuthOppdB% dB Clockwise: %isazimuthclockwise%
EXIT /B 0




:azimuthcorrectionspread
:: input: (degrees in 360, range -45 to 45) (mute)
:: input: setup variables
:: input file: temp1file output file: temp1file

SET azimuthindegrees=%1
SET azimuthspread=%2
SET azmuted=no
IF /I "%3"=="mute" SET azmuted=mute

SET Result=ERROR
Call:Math round((%azimuthindegrees%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthindegrees=%Result%

Call:Math int(round((abs(%azimuthindegrees%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 225000 (ECHO ERROR: Azimuth correction at %azimuthindegrees% is impossible & EXIT /B 1)


SET Result=ERROR
Call:Math round((%azimuthspread%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthspread=%Result%

Call:Math int(round((abs(%azimuthspread%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 125000 (ECHO ERROR: Azimuth spread correction at %azimuthspread% is impossible & EXIT /B 1)


IF NOT "%azmuted%"=="mute" ECHO === Stage start: azimuth correction ======================
call :getazimuthspread %azimuthindegrees% %azimuthspread% %azmuted%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees & EXIT /B %ERRORLEVEL%)

Call:Math Int(abs(%azimuthOppdB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in azimuth: checking db levels oppdb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthOppdB% dB Opp & EXIT /B 1)

Call:Math Int(abs(%azimuthSamedB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth checking db levels samedb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthSamedB% dB & EXIT /B 1)

if "%isazimuthclockwise%"=="yes" (
:cwazimuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2i%azimuthOppdB%, 2p,2p%azimuthSamedB%,1p%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: clockwise azimuth & EXIT /B 1)
) ELSE (
:ccwazumuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2p%azimuthOppdB%, 2p,2p%azimuthSamedB%,1i%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: counterclockwise azimuth & EXIT /B 1)
)
:azimuthcorrectiondone

IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (ECHO azimuth fail moving output & EXIT /B 1)
IF NOT EXIST %temp1file% (ECHO ERROR: azimuth correction fail creating output & EXIT /B 1)

IF NOT "%azmuted%"=="mute" echo Applied %azimuthdeg% degrees correction:
IF NOT "%azmuted%"=="mute" echo Same: %azimuthSamedB% dB Opposite: %azimuthOppdB% dB Clockwise: %isazimuthclockwise%
EXIT /B 0



:getazimuthspread
:: input parameter: degrees (360)
:: output variables: azimuthSamedB and azimuthOppdB
IF "%1"=="" (ECHO I need to know how many degrees as input parameter & EXIT /B 1)
SET azimuthdeg=%1
SET azspread=%2
SET azmuted=no
IF /I "%3"=="mute" set azmuted=mute
SET LINazimuthOppdB=0
SET LINazimuthSamedB=0
SET RINazimuthOppdB=0
SET RINazimuthSamedB=0

SET Result=ERROR
Call:Math Int(abs(%azimuthdeg% * 10000))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth bounds check & EXIT /B 1)
IF %Result% GTR 450000 (ECHO == ERROR: Insane azimuth value == & EXIT /B 1)

set Result=ERROR
Call:Math round((Atn(1) / 45), 15)
IF %Result%==ERROR (ECHO ERROR: Math function call in getazimuth calculate rad/deg & EXIT /B 1)
set toradians=%Result%

Call:Math (%azimuthdeg%-%azspread%) * %toradians%
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth input degrees to radians & EXIT /B 1)
SET inputrad=%Result%

Call:Math abs(%azimuthdeg% * %toradians%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth absolute value in radians & EXIT /B 1)
SET azimuthrad=%Result%

IF "%inputrad%"=="%azimuthrad%" (set isazimuthclockwise=yes) ELSE (set isazimuthclockwise=no)

Call:Math (1 / Cos(%azimuthrad%)) - 1.0
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth cos of radians & EXIT /B 1)
SET samex=%Result%

CALL :todb %samex%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine with %samex% & EXIT /B 1)
SET azimuthSamedB=%dbvalue%

Call:Math Tan(%azimuthrad%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth tan of radians & EXIT /B 1)
SET oppx=%Result%

CALL :todb %oppx%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine 2 with %oppx% & EXIT /B 1)
SET azimuthOppdB=%dbvalue%

:getazimuthspreaddone
IF %azimuthOppdB%==0 EXIT /B 1
IF %azimuthSamedB%==0 EXIT /B 1
EXIT /B 0




:getazimuth
:: input parameter: degrees (360)
:: output variables: azimuthSamedB and azimuthOppdB
IF "%1"=="" (ECHO I need to know how many degrees as input parameter & EXIT /B 1)
SET azimuthdeg=%1
SET azmuted=no
IF /I "%2"=="mute" set azmuted=mute
SET azimuthOppdB=0
SET azimuthSamedB=0

SET Result=ERROR
Call:Math Int(abs(%azimuthdeg% * 10000))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth bounds check & EXIT /B 1)
IF %Result% GTR 450000 (ECHO == ERROR: Insane azimuth value == & EXIT /B 1)

set Result=ERROR
Call:Math round((Atn(1) / 45), 15)
IF %Result%==ERROR (ECHO ERROR: Math function call in getazimuth calculate rad/deg & EXIT /B 1)
set toradians=%Result%

Call:Math %azimuthdeg% * %toradians%
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth input degrees to radians & EXIT /B 1)
SET inputrad=%Result%

Call:Math abs(%azimuthdeg% * %toradians%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth absolute value in radians & EXIT /B 1)
SET azimuthrad=%Result%

IF "%inputrad%"=="%azimuthrad%" (set isazimuthclockwise=yes) ELSE (set isazimuthclockwise=no)

Call:Math (1 / Cos(%azimuthrad%)) - 1.0
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth cos of radians & EXIT /B 1)
SET samex=%Result%

CALL :todb %samex%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine with %samex% & EXIT /B 1)
SET azimuthSamedB=%dbvalue%

Call:Math Tan(%azimuthrad%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth tan of radians & EXIT /B 1)
SET oppx=%Result%

CALL :todb %oppx%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine 2 with %oppx% & EXIT /B 1)
SET azimuthOppdB=%dbvalue%

:getazimuthdone
IF %azimuthOppdB%==0 EXIT /B 1
IF %azimuthSamedB%==0 EXIT /B 1
EXIT /B 0



:todb
IF "%1"=="" (ECHO todb function requires input volume (1.00 = 0dB) & EXIT /B 1)
SET inputvolume=%1
SET dbvalue=borktest

SET Result=ERROR
Call:Math %inputvolume%
IF %Result%==ERROR (ECHO ERROR: Math function call fail in todb function check1 & EXIT /B 1)
IF %Result% EQU 0 (set dbvalue=-400.000 & goto :todbdone)

set Result=ERROR
Call:Math (Log(%inputvolume%) / Log (10.0)) * 20.0
IF "%Result%"=="ERROR" (ECHO ERROR: Math function log call failed in todb & EXIT /B 1)
set dbvalue=%Result%

:todbdone
if %dbvalue%==borktest EXIT /B 1
EXIT /B 0



:balancechannels
IF "%1"=="" (ECHO balancechannels function requires an input parameter in dB & EXIT /B 1)
:: Negative: turn up left side (we actually turn down other side)

SET Result=ERROR
Call:Math round((%1), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs & EXIT /B 1)
SET channeladjust=%Result%

SET Result=ERROR
Call:Math round((abs(%1)), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs & EXIT /B 1)
set perchanneladjust=%Result%
IF %channeladjust%==%perchanneladjust% SET cutleft=0 ELSE SET cutleft=1

Call:Math round((%perchanneladjust% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs check no change & EXIT /B 1)
IF %Result% EQU 0 (ECHO STATUS: Skipping channel balance for correction %perchanneladjust% dB & EXIT /B 0)

IF "%cutleft%"=="1" (
REM turn down left side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p-%perchanneladjust% 2p
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: balancechannels positive level %channeladjust% adjustment & EXIT /B 1)
) ELSE (
REM turn down right side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p 2p-%perchanneladjust%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: balancechannels negative level %channeladjust% adjustment & EXIT /B 1)
)

:balancechannelsdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (EXIT /B 1)
EXIT /B 0



:crosstalk
SET inverted=%1
SET crosslevel=%2

set Result=ERROR
Call:Math round((%crosslevel% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
if %Result% GEQ 0 GOTO :crosstalkdone

:: todo - actually mix an equalized version of crosstalk back in
:: todo - check input db

ECHO === Stage start: crosstalk correction==============================
IF /I "%inverted%"=="no" (
:normalcrosstalk
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p,2i%crosslevel%, 2p,1i%crosslevel%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: normal crosstalk & EXIT /B 1)
) ELSE (
:inversecrosstalk
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p,2p%crosslevel%, 2p,1p%crosslevel%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: inverse crosstalk & EXIT /B 1)
)
:crosstalkdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL) ELSE (EXIT /B 1)
EXIT /B 0



:noisereduction
IF NOT %1=="" SET %NRstrength%=%1

set Result=ERROR
Call:Math round((%NRstrength% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in noise reduction setup & EXIT /B 1)
IF %Result% LSS 1 GOTO :noisereductiondone
IF %Result% GEQ 10000 (ECHO ERROR: Noise reduction NRStrength: %NRstrength% is invalid & EXIT /B 1)

ECHO === Stage start: noise reduction ==================================

sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% -n ^
trim 0 %NRseconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo noise reduction profile & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% %progress% -V%verbose% %temp1file% %temp2file% ^
noisered %noiseprofile% %NRstrength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo noise reduction processing & EXIT /B 1)

:noisereductiondone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0




:speedup
IF NOT "%1"=="" SET speedup=%1

:: A setting of 1.0000 = no speedup
set Result=ERROR
Call:Math round((%speedup% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in speedup while validating input & EXIT /B 1)
set speedupcheck=%Result%
IF %speedupcheck% EQU 10000 (GOTO :speedupdone)
IF %speedupcheck% LSS 1000 (ECHO ERROR speed: %speedup%, I'm not letting you slow down by more than 10x & EXIT /B 1)
IF %speedupcheck% GTR 100000 (ECHO ERROR speed:%speedup%, I'm not letting you speed up by more than 10x & EXIT /B 1)

ECHO === Stage start: speed correction==================================

sox --multi-threaded --buffer=%buffer% -V3 %progress% %temp1file% %temp2file% ^
rate -b 75 192k ^
biquad 1.0000000000 -1.9312626096 0.9313724325 1.0000000000 -0.8796912298 -0.1023703458 ^
speed %speedup% ^
rate -b 75 192k ^
biquad 1.0000000000 -0.8796912298 -0.1023703458 1.0000000000 -1.9312626096 0.9313724325 ^
rate %speedupdownsample%k
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: speedup and RIAA re-EQ & EXIT /B 1)

:speedupdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0



:midside
ECHO === Stage start: convert stereo to mid-side =======================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p-6.0206,2p-6.0206 1p-6.0206,2i-6.0206
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo to mid-side & EXIT /B 1)
:midsidedone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0



:midchannel
ECHO === Stage start: process mid channel ==============================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %midfile% ^
remix 1
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mix midside to mid & EXIT /B 1)

:midnoisereduction
rem IF /I NOT "%usenoisereduction%"=="yes" GOTO :midchanneldone
IF /I NOT "%midsideNR%"=="yes" GOTO :midchanneldone
ECHO === Stage start: mid-channel noise reduction =====================

sox --multi-threaded --buffer=%buffer% -V%verbose% %midfile% -n ^
trim %NRseconds% %NR2seconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mid noise reduction profiling & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %midfile% %temp2file% ^
noisered %noiseprofile% %NR2strength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mid noise reduction processing & EXIT /B 1)

:midchanneldone
IF EXIST %temp2file% (DEL %midfile% & move %temp2file% %midfile%) >NUL
EXIT /B 0



:sidechannel
:sideeq
ECHO === Stage start: process side channel =============================
rem ## To restore a 150Hz side-channel bass cut, possibly used in mastering, we equalize
rem ## then more highpass subsonic to reduce vertical modulation rumble

IF %sidesub% NEQ 0 (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %sidefile% ^
remix 2 ^
highpass %sidesub% .5412 highpass %sidesub% 1.3065 ^
reverse ^
highpass %sidesub% .5412 highpass %sidesub% 1.3065 ^
equalizer 80 0.65q %sidebassboostdb% ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel bass boost and rumble filter & EXIT /B 1)
) ELSE (
ECHO skipping side-channel rumble filter at setting %sidesub% Hz
IF %sidebassboostdb%==0 GOTO :sideeqdone
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %sidefile% ^
remix 2 ^
equalizer 80 0.65q %sidebassboostdb%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel bass boost without rumble filter & EXIT /B 1)
)
:sideeqdone

:sidenoisereduction
rem IF /I NOT "%usenoisereduction%"=="yes" GOTO :sidenoisereductiondone
IF NOT "%midsideNR%"=="yes" GOTO :sidenoisereductiondone

ECHO === Stage start: side-channel noise reduction ====================

sox --multi-threaded --buffer=%buffer% -V%verbose% %sidefile% -n ^
trim 0 %NRseconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel noise reduction profiling & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %sidefile% %temp2file% ^
noisered %noiseprofile% %NRstrength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel noise reduction processing & EXIT /B 1)
:sidenoisereductiondone

:sidechanneldone
IF EXIST %noiseprofile% (DEL %noiseprofile%)
IF EXIST %temp2file% (DEL %sidefile% & move %temp2file% %sidefile%)
EXIT /B 0


:unmidside
ECHO === Stage start: mid-side to stereo ===============================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% --combine merge %midfile% %sidefile% %temp1file% ^
remix -m 1,2 1,2i
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: combine mid and side to stereo & EXIT /B 1)
EXIT /B 0


:makeoutput
IF NOT EXIST %temp1file% (ECHO ERROR: Expected input file %temp1file% doesn't exist & EXIT /B 1)

SET outname=%1
IF '%outname%'=='' SET outname=%outfile%

ECHO === Stage start: creating output file ============================

SET Result=ERROR
Call:Math int(%normalizeto% * 1000000)
IF %Result%==ERROR (ECHO ERROR: Math function call fail in todb function check1 & EXIT /B 1)
:: greater than 0 db setting disables normalization
IF %Result% GTR 0 (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% --comment="" -b 24 %outname% ^
silence 1 2 0 ^
reverse ^
silence 1 2 0 ^
reverse ^
gain %processinggainreduction%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: increase gain back to input & EXIT /B 1)
) ELSE (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% --norm=%normalizeto% %temp1file% --comment="" -b 24 %outname% ^
gain %processinggainreduction%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: final normalization & EXIT /B 1)
)

:makeoutputdone
IF NOT EXIST %outname% (ECHO ERROR: creating output file %outfile% & EXIT /B 1) ELSE ( ECHO ==== DONE: Created %outname% ==== )
EXIT /B 0


:cleanup
rem IF /i NOT "%disablecleanuptempfiles%"=="no" GOTO :cleanupdone
DEL %midfile% 2> NUL
DEL %sidefile% 2> NUL
DEL %temp1file% 2> NUL
DEL %temp2file% 2> NUL
DEL %noiseprofile% 2> NUL
DEL %tempdir%Math.vbs 2> NUL
:cleanupdone
EXIT /B 0






:findazimuth
ECHO -- Generating stepped output

set sub=300
SET rmslist=
SET degreelist=

CALL :setup %1
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

SET filteredfile=%noiseprofile%
SET rancount=1

sox --multi-threaded --buffer=%buffer% -V1 %progress% %infile% -b 24 %filteredfile% ^
pad 0.5 0.5 ^
gain -10 ^
rate -b 75 24k ^
sinc -L %sub% -n 32767 ^
highpass 2000 ^
reverse ^
sinc -L %sub% -n 32767 ^
highpass 2000 ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: findazimuth notch filtering & EXIT /B 1)


:testloop

SET /A "incs=steps-1"
DEL "%tempdir%%filebase%-iter*.wav" 2>NUL
FOR /L %%a in (0,1,%incs%) do (call :insideloopsub %%a)
ECHO/
sox --multi-threaded --buffer=%buffer% -V2 --combine concatenate "%tempdir%%filebase%-iter*.wav" --comment="" %temp1file%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: trying to merge & EXIT /B 1)
DEL "%tempdir%%filebase%-iter*.wav" 2>NUL
ECHO/
CALL :makeoutput "%inpath%%filebase%-stereosteps.wav"
CALL :midside
CALL :makeoutput "%inpath%%filebase%-midsidesteps.wav"
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling makeoutput & EXIT /B 1)

echo ----------------------------------------
ECHO #: Degree MID+SIDERMS MIDRMS SIDE RMS

for /l %%n in (1,1,%steps%) do (
echo !resulttable[%%n]!
)

call :cleanup
ECHO/
ECHO -- Done. Analyze these files for phase and pan to find best correction:
ECHO -- "%inpath%%filebase%-stereosteps.wav";
ECHO -- "%inpath%%filebase%-midsidesteps.wav"
ECHO (%steps% steps are centered on %center% degrees, %fromcenter% degrees on each size)
pause

exit /b


:insideloopsub
set inparm=%1
IF 1%inparm% LSS 100 SET inparm=0%inparm%

SET Result=ERROR

Call:Math round( ( (%center% - %fromcenter%) + (%1 * 2 *%fromcenter% / ( %incs% ))) , 4) + 0.00001
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
SET degrees=%Result%

copy %filteredfile% %temp1file% >NUL 2>NUL
call :rmsgrabber %degrees%

sox %filteredfile% %tempdir%gaptemp.wav synth 2 sine 10 gain -120
sox --buffer=%buffer% -V2 %temp1file% "%tempdir%%filebase%-iter%inparm%.wav"

IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling rmsgrabber: insideloopsub & EXIT /B 1)


if NOT !rancount! EQU 1 (
SET "degreelist=%degreelist% %aztestvalue%"
SET "midlist=%midlist% %midrms%"
SET "sidelist=%sidelist% %siderms%"
SET "avglist=%avglist% %avgrms%"
SET "samelist=%samelist% %azimuthSamedB%"
SET "opplist=%opplist% %azimuthOppdB%"
) ELSE (
SET "degreelist=%aztestvalue%"
SET "midlist=%midrms%"
SET "sidelist=%siderms%"
SET "avglist=%avgrms%"
SET "samelist=%azimuthSamedB%"
SET "opplist=%azimuthOppdB%"
)

IF 1%rancount% LSS 100 (
SET resulttable[%rancount%]=0%rancount%: %aztestvalue%: %avgrms% -- %midrms% -- %siderms%
) ELSE (
SET resulttable[%rancount%]=%rancount%: %aztestvalue%: %avgrms% -- %midrms% -- %siderms%
)

SET /A "rancount=rancount+1"
GOTO :eof
exit /b 0



:rmsgrabber
:: input argument: degrees of azimuth
:: input file: %temp1file%
:: output: sets midrms siderms avgrms

:getactual
IF "%1"=="" (echo get mid-side RMS function needs input in degrees & EXIT /B 1)
set aztestvalue=%1
call :azimuthcorrection %aztestvalue% mute
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling azimuthcorrection 1 & EXIT /B 1)

:: azimuth-adjusted signal to mid
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %midfile% ^
remix 1p,2p
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: midside rms 1 & EXIT /B 1)

:: corrected signal to side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %sidefile% ^
remix 1p,2i
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: midside rms 2 & EXIT /B 1)

:: EXTRACT STDERR OUTPUT OF SoX ============
sox -V1 %midfile% -n stat -s 1 2> %tempdir%soxstat.log
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: makestats & EXIT /B 1)
for /f "tokens=*" %%i in ('FINDSTR RMS %tempdir%soxstat.log ^| FINDSTR amplitude') do ( set RMSline=%%i )
for /f "tokens=3 delims= " %%i IN ("%RMSline%") do (set midrms=%%i)
del %tempdir%soxstat.log

sox -V1 %sidefile% -n stat -s 1 2>%tempdir%soxstat.log
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: makestats rms amplitude 2 & EXIT /B 1)
for /f "tokens=*" %%i in ('FINDSTR RMS %tempdir%soxstat.log ^| FINDSTR amplitude') do ( set RMSline=%%i )
for /f "tokens=3 delims= " %%i IN ("%RMSline%") do (set siderms=%%i)
del %tempdir%soxstat.log

set Result=ERROR
Call:Math (%midrms% + %siderms%)/2
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set avgrms=%Result%

Call:Math round((%midrms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set midrms=%Result%
Call:Math round((%siderms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set siderms=%Result%
Call:Math round((%avgrms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set avgrms=%Result%
Call:Math round((%aztestvalue%), 2)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set aztestvalue=%Result%
Call:Math int((abs(%aztestvalue%) - %aztestvalue%)*10000)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=+%aztestvalue%
Call:Math ((%aztestvalue% - int(%aztestvalue%))*10)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=%aztestvalue%.0
Call:Math %aztestvalue% * 10 - int( %aztestvalue% * 10 )
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=%aztestvalue%0

rem echo degrees mr+sr m s
rem echo %aztestvalue% %avgrms%,%midrms%,%siderms%
echo | set /p=%aztestvalue%,

:rmsgrabberdone
exit /b
:findazimuthdone



:referencesteps
ECHO --- Azimuth-correcting your input file x 21 steps... ---
set sub=30
CALL :setup %1
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

SET filteredfile=%temp1file%

sox -S --multi-threaded --buffer=%buffer% -V1 %progress% %infile% %filteredfile% ^
rate -b 75 -L 48k ^
gain -%processinggainreduction% ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
lowpass 20000 ^
reverse ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
lowpass 20000 ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps notch filtering & EXIT /B 1)
DEL %tempdir%%filebase%steps*.wav 2>NUL
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps01.wav ^
remix 1p,1p-48.36,2p-21.16 2p,2p-48.36,1i-21.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps02.wav ^
remix 1p,1p-50.19,2p-22.08 2p,2p-50.19,1i-22.08 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps03.wav ^
remix 1p,1p-52.25,2p-23.11 2p,2p-52.25,1i-23.11 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps04.wav ^
remix 1p,1p-54.57,2p-24.27 2p,2p-54.57,1i-24.27 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps05.wav ^
remix 1p,1p-57.25,2p-25.61 2p,2p-57.25,1i-25.61 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps06.wav ^
remix 1p,1p-60.42,2p-27.20 2p,2p-60.42,1i-27.20 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps07.wav ^
remix 1p,1p-64.30,2p-29.14 2p,2p-64.30,1i-29.14 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps08.wav ^
remix 1p,1p-69.30,2p-31.64 2p,2p-69.30,1i-31.64 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps09.wav ^
remix 1p,1p-76.34,2p-35.16 2p,2p-76.34,1i-35.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps10.wav ^
remix 1p,1p-88.39,2p-41.18 2p,2p-88.39,1i-41.18 pad .5 2

sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps11.wav ^
pad .5 2
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps12.wav ^
remix 1p,1p-88.39,2i-41.18 2p,2p-88.39,1p-41.18 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps13.wav ^
remix 1p,1p-76.34,2i-35.16 2p,2p-76.34,1p-35.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps14.wav ^
remix 1p,1p-69.30,2i-31.64 2p,2p-69.30,1p-31.64 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps15.wav ^
remix 1p,1p-64.30,2i-29.14 2p,2p-64.30,1p-29.14 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps16.wav ^
remix 1p,1p-60.42,2i-27.20 2p,2p-60.42,1p-27.20 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps17.wav ^
remix 1p,1p-57.25,2i-25.61 2p,2p-57.25,1p-25.61 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps18.wav ^
remix 1p,1p-54.57,2i-24.27 2p,2p-54.57,1p-24.27 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps19.wav ^
remix 1p,1p-52.25,2i-23.11 2p,2p-52.25,1p-23.11 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps20.wav ^
remix 1p,1p-50.19,2i-22.08 2p,2p-50.19,1p-22.08 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps21.wav ^
remix 1p,1p-48.36,2i-21.16 2p,2p-48.36,1p-21.16 pad .5 .5

sox -V%verbose% --multi-threaded --guard --combine concatenate ^
%tempdir%%filebase%steps*.wav ^
--comment="" "%inpath%%filebase%-referencesteps-stereo.wav"
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps recombinging steps & EXIT /B 1)

sox -V%verbose% "%inpath%%filebase%-referencesteps-stereo.wav" "%inpath%%filebase%-referencesteps-midside.wav" ^
remix 1p-6.0206,2p-6.0206 1p-6.0206,2i-6.0206
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps making midside version of steps & EXIT /B 1)

:cleanupsteps
DEL %tempdir%%filebase%steps*.wav
CALL :cleanup
:referencestepsstepsdone
ECHO/
ECHO -- Done. Analyze these files for phase and pan to find best correction:
ECHO -- "%inpath%%filebase%-referencesteps-stereo.wav";
ECHO -- "%inpath%%filebase%-referencesteps-midside.wav"
ECHO (range of steps is -5 degrees ccw to +5 degrees clockwise)
pause

exit /B 0
goto :eof


:Math
REM echo VB command: "%*"
set Result=ERROR
for /f %%a in ('cscript /nologo %tempdir%Math.vbs "%*"') do set "Result=%%a"
exit /b %matherror%


:deviation
CALL :stddevfile
echo VB command: -- %* --
set Result=ERROR
for /f %%a in ('cscript /nologo %tempdir%Stddev.vbs "%*"') do set "Result=%%a"
exit /b %matherror%


:stddevfile
IF EXIST %tempdir%Stddev.vbs DEL %tempdir%Stddev.vbs >NUL
ECHO arData = Split(WScript.Arguments(0),",") >%tempdir%Stddev.vbs
echo Wscript.echo "hello" & StandardDeviation(arData),15 >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Wscript.echo StandardDeviation(arData) >>%tempdir%Stddev.vbs
ECHO WScript.Quit 1 >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Function StandardDeviation(arData) >>%tempdir%Stddev.vbs
ECHO StandardDeviation = 0 >>%tempdir%Stddev.vbs
ECHO If IsArray(arData) Then >>%tempdir%Stddev.vbs
ECHO Difference = 0 >>%tempdir%Stddev.vbs
ECHO Temp = 0 >>%tempdir%Stddev.vbs
ECHO Average = GetAverage(arData) >>%tempdir%Stddev.vbs
ECHO Amount = UBound(arData) >>%tempdir%Stddev.vbs
ECHO For i = 0 To Amount >>%tempdir%Stddev.vbs
ECHO Difference = ((arData(I) - Average) ^^ 2) >>%tempdir%Stddev.vbs
ECHO Temp = Temp + Difference >>%tempdir%Stddev.vbs
ECHO Difference = 0 >>%tempdir%Stddev.vbs
ECHO Next >>%tempdir%Stddev.vbs
ECHO StandardDeviation = Sqr(Temp / (Amount)) >>%tempdir%Stddev.vbs
ECHO End If >>%tempdir%Stddev.vbs
ECHO End Function >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Function GetAverage(arData) >>%tempdir%Stddev.vbs
ECHO GetAverage = 0 >>%tempdir%Stddev.vbs
ECHO If IsArray(arData) Then >>%tempdir%Stddev.vbs
ECHO total = UBound(arData) >>%tempdir%Stddev.vbs
ECHO For i = 0 To total >>%tempdir%Stddev.vbs
ECHO GetAverage = GetAverage + arData(i) >>%tempdir%Stddev.vbs
ECHO Next >>%tempdir%Stddev.vbs
ECHO GetAverage = GetAverage / (total + 1) >>%tempdir%Stddev.vbs
ECHO End If >>%tempdir%Stddev.vbs
ECHO End Function >>%tempdir%Stddev.vbs
EXIT /B 0



:nosox
echo/
echo ======== SoX.exe audio processor not found - What do you want to do? =========
echo/
echo [1] - EXIT: I'll download it myself from Sourceforge (and put sox.exe file in path)
echo [2] - Download sox.exe from author's site to work directory and continue (easy if working)
echo [xx] - Download and expand zip from Sourceforce to local directory and continue (needs PS 5)
echo [xx] - Just download installer from Sourceforce (so I can run it manually and move sox.exe)
echo/
choice /C 12 /N /M "Your choice: "
echo/

if errorlevel 4 goto :getinstalleronly
if errorlevel 3 goto :zipdownload
if errorlevel 2 goto :authordownload
EXIT /B 4

:authordownload

powershell -Command "Invoke-WebRequest http://hotnova.com/sox.exe -OutFile %cd%\sox.exe"
IF NOT EXIST sox.exe (echo Sorry, didn't work. & goto :nosox)
echo Got it!!
sox --version
IF NOT %ERRORLEVEL%==0 (echo Something's wrong with the downloaded file, sorry & goto :nosox)
EXIT /B 0

:nosoxdone
EXIT /B 0


:nofile
echo ==== There is no %infile% input file found! ====
echo (Reminder: With spaces in file names, surrounding quotes are needed)
pause
exit /b 9
:nofiledone


:cantdel
echo ==== %outfile% output or temp files exist and can't be deleted - do you have one open?? ====
pause
exit /b 7
 

Icewater_7

Member
Joined
May 18, 2023
Messages
51
Likes
11
Location
El Dorado Hills, CA
Has anyone tried this Azimuth Script . I got it to run but have difficulty understanding how to analyse the file.. see post 37
@Echo OFF
SETLOCAL EnableDelayedExpansion
SETLOCAL ENABLEEXTENSIONS
TITLE Devinyl

:: Description: Vinyl Magic: vinyl subsonic filter, equipment corrections, and more

:: Usage: devinyl.cmd input-filename.wav (speedup factor)
:: (or no file name to process "input.wav"
:: output file name will have -processed.wav at end)

:: Author: Harby - stevehoffman.tv forums
:: Free for non-commercial hobbyist use
:: commercial azimuth use and future features (turntable setups, restoration..) TBD

:: ---- SETTINGS BELOW MUST BE CUSTOMIZED to your wants and needs ----

:SETTINGS

:: Adjust signal imbalance of phono pre and ADC electric path, dB. Negative: turn up left side
:: (this...if you can't send a low-level test signal into phono-in, mono it with y cables, and adjust your knobbies)
SET inchannelbalance=0.20

:: Signature/Profile-based noise reduction? (yes/no) 1st pass, for electrical noise/hum
:: (Must put 2+ seconds of "electric" silence at the start of file)
SET usenoisereduction=no
:: Noise reduction amount (of 0 to 1); heavy-handed even at 0.1, increase at your own peril:
SET NRstrength=0.9
SET NRseconds=2

:: Signature/Profile-based noise reduction? (yes/no) - 2st pass, mid-side, for vinyl noise
:: Must put more "surface noise" silence at the start of file -- after first silence segment
SET midsideNR=no
SET NR2strength=0.5
:: Seconds is the total number of seconds added AFTER the first segment of electric noise
SET NR2seconds=2


:: Magical cartridge azimuth correction in degrees (0 to disable and skip)
:: (use negative degrees if electrical alignment is twisted counter-clockwise looking from front)
SET azimuthsettingindegrees=0.9

:: Crosstalk specification of cartridge in minus dB, eg -29, or as discovered from analysis
:: (More crosstalk correction can also be used as a widening effect)
:: (disabled at 0 or positive numbers)
SET crosstalkdb=-32.0
:: If cartrige crosstalk is inverted/out-of-phase and actually over-widens the stereo? (yes/no)
SET iscrosstalkinverted=yes

:: If one calibrated channel still quieter after azimuth & crosstalk correction (total dB change). Negative: turn up left side
:: (this would be your cartridge's electrical channel imbalance)
SET channelbalance=-0.19

:: Subsonic resonance cutoff frequency, Hz (extremely sharp cut below, little effect above)
:: (0 to disable and skip)
SET sub=22
:: use 10th order Butterworth filter instead of even sharper sinc function?
SET butterworth=no
:: frequency of milder side-channel vertical rumble reduction
SET sidesub=70

:: Speed correction for reduced-speed disc transfers (using your normal RIAA preamp)
:: Set to 1.35 for 45 played at 33, etc (1.0 to skip)
:: Command line option will override
SET speedup=1.00
REM speedup=1.23496
:: the speedup performs resampling at 192kHz+; if you don't want your new high-resolution, set lower:
:: (use standard sample rates like 44.1 48 88.2 96 192)
SET speedupdownsample=96


SET usemidsideprocessing=yes
:: (if not set to yes, all mid-side magic including noise reduction is skipped)

:: Side-channel bass correction, in positive dB; 5 will restore width from a 150Hz 1st order highpass used in mastering
SET sidebassboostdb=1.3


:: Adjust output file to peak level, set to -dB. A positive integer to disable
SET normalizeto=2

:: Internal settings; set verbose to 3 to see all sox output, but will disable future clip detection
SET verbose=2
SET buffer=131072
SET progressbar=yes
SET processinggainreduction=6
SET disablecleanuptempfiles=no

:: This function instead takes a SHORT audio input file (like a test LP channel separation track) and
:: repeatedly steps it through a range of azimuth corrections, so you can analyze compiled output
SET forceazimuthanalysis=yes
:: Center position (degrees)
SET center=0
:: Width on each side of center (degrees) (if negative, stepping goes from + to - (cw to CCW), maybe confusing)
SET fromcenter=5
:: (if number of steps below is even, you don't get center point)
SET steps=41

:: similar, but doesn't do trigonometry, just an internal table from -5 to 5 degrees
:: this version is not filtered for automated analysis
SET forcereferencesteps=no


:SETTINGSDONE

:: PROGRAM STARTS HERE

IF /i "%forceazimuthanalysis%"=="yes" GOTO :findazimuth
IF /i "%~1"=="findazimuth" GOTO :findazimuth
IF /i "%2"=="findazimuth" GOTO :findazimuth %1

IF /i "%forcereferencesteps%"=="yes" GOTO :referencesteps
IF /i "%~1"=="referencesteps" GOTO :referencesteps
IF /i "%2"=="referencesteps" GOTO :referencesteps %1


CALL :setup %1 %2 %3 %4 %5
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :makeinput
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeinput subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :balancechannels %inchannelbalance%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to channel balance subroutine errors & CALL :cleanup & EXIT /B 1)

IF /I "%usenoisereduction%"=="yes" (CALL :noisereduction %NRstrength%) ELSE (ECHO STATUS: Skipping noise reduction)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to noisereduction errors & CALL :cleanup & EXIT /B 1)

CALL :azimuthcorrection %azimuthsettingindegrees%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to azimuthcorrection subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :crosstalk %iscrosstalkinverted% %crosstalkdb%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to crosstalk errors & CALL :cleanup & EXIT /B 1)

CALL :balancechannels %channelbalance%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to channel balance subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :subsonic %sub%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeinput subroutine errors & CALL :cleanup & EXIT /B 1)

CALL :speedup %speedup%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to speedup errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :midside) ELSE (ECHO STATUS: Skipping all mid-side processing)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to midside function errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :midchannel)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to midchannel errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :sidechannel)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to sidechannel errors & CALL :cleanup & EXIT /B 1)

IF /I "%usemidsideprocessing%"=="yes" (CALL :unmidside)
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to unmidside errors & CALL :cleanup & EXIT /B 1)

CALL :makeoutput %outfile%
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to makeoutput errors & CALL :cleanup & EXIT /B 1)

PAUSE

CALL :cleanup
IF NOT %ERRORLEVEL%==0 (echo ..cleanup function had an error & EXIT /B 1)

EXIT /B 0


==== SUBROUTINES ====
:setup

:: TODO: search path and also install location for sox, set full location (and replace every call with variable)

sox --version >NUL 2>NUL
IF %ERRORLEVEL%==9009 (CALL :nosox)
sox --version >NUL 2>NUL
IF NOT %ERRORLEVEL%==0 (ECHO === SOX.EXE problem! SOX.EXE IS STILL MISSING OR ERRORS OUT & exit /b %ERRORLEVEL%)

rem echo parameters f1 2: %~f1 %2
rem echo parameters per1: %1


IF '%1'=='' GOTO :defaultfile
:: use full input file paths and temp directory
SET inpath=%~dp1
SET filebase=%~n1
SET fileext=%~x1
SET tempdir=%temp%\
SET outfile="%inpath%%filebase%-processed.wav"
GOTO :donesettingfiles

:defaultfile
:: default to no paths and default file name
SET inpath=
SET filebase=devinyl
SET fileext=.wav
SET tempdir=%temp%\
SET outfile="output-devinyl.wav"

:donesettingfiles

rem ECHO inpath---%inpath%
rem ECHO filebase---%filebase%
rem ECHO fileext---%fileext%
rem ECHO outfile---%outfile%

SET infile="%inpath%%filebase%%fileext%"
IF '%1'=='' SET infile="input.wav"
rem ECHO --- infile: %infile%

IF NOT "%2"=="" (SET speedup=%2)

IF NOT EXIST %infile% (GOTO :nofile & EXIT /B 1)

IF EXIST %outfile% DEL %outfile% & IF EXIST %outfile% (set DELERROR=1 & GOTO :cantdel)

set temp1file="%tempdir%%filebase%-temp1.wav"
IF EXIST %temp1file% DEL %temp1file% & IF EXIST %temp1file% (set DELERROR=1 & GOTO :cantdel)

set temp2file="%tempdir%%filebase%-temp2.wav"
IF EXIST %temp2file% DEL %temp2file% & IF EXIST %temp2file% (set DELERROR=1 & GOTO :cantdel)

set midfile="%tempdir%%filebase%-midtemp.wav"
IF EXIST %midfile% DEL %midfile% & IF EXIST %midfile% (set DELERROR=1 & GOTO :cantdel)

set sidefile="%tempdir%%filebase%-sidetemp.wav"
IF EXIST %sidefile% DEL %sidefile% & IF EXIST %sidefile% (set DELERROR=1 & GOTO :cantdel)

set noiseprofile="%tempdir%%filebase%-noiseprofile.wav"
IF EXIST %noiseprofile% DEL %noiseprofile% & IF EXIST %noiseprofile% (set DELERROR=1 & GOTO :cantdel)

IF "%DELERROR%"=="1" (EXIT /B 1)

call :subsetup
IF NOT %ERRORLEVEL%==0 (ECHO ERROR returned by subsetup & exit /b 1)

:setupdone
EXIT /B 0

:subsetup
:: subroutines need these, along with a temp1file input/output file defined

IF EXIST %tempdir%Math.vbs DEL %tempdir%Math.vbs >NUL
echo Wscript.echo Round(eval(WScript.Arguments(0)),15) >%tempdir%Math.vbs
echo WScript.Quit 2 >>%tempdir%Math.vbs
echo ' quit 2 shouldn't be reached if there is an error above it >>%tempdir%Math.vbs

set Result=ERROR
Call:Math round((%sub%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sub=%Result%

Call:Math round((%sidesub%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sidesub=%Result%

Call:Math round((%sidebassboostdb%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set sidebassboostdb=%Result%

Call:Math round((%crosstalkdb%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set crosstalkdb=%Result%

Call:Math round((%channelbalance%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set channelbalance=%Result%

Call:Math round((%speedup%), 8)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set speedup=%Result%

Call:Math round((%normalizeto%), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
set normalizeto=%Result%

IF /I "%progressbar%"=="yes" SET progress=-S

:butterworth 10th order
SET ch1q=0.5062 & SET ch2q=0.5612 & SET ch3q=0.7071 & SET ch4q=1.1013 & SET ch5q=3.1970
SET ch1f=%sub% & SET ch2f=%sub% & SET ch3f=%sub% & SET ch4f=%sub% & SET ch5f=%sub%
:subsetupdone
EXIT /B 0


:makeinput
ECHO === Start: processing input ======================
:: MUST CALL THIS FUNCTION FIRST TO READ INPUT FILENAME to first temp file
sox --multi-threaded --buffer=%buffer% -V1 %progress% %infile% -b 32 %temp1file% ^
gain -%processinggainreduction% ^
pad 2 2
:makeinputdone
IF NOT EXIST %temp1file% (ECHO fail creating work from input file & EXIT /B 1)
EXIT /B 0



:subsonic
IF NOT "%1"=="" SET sub=%1
IF "%ch1q%"=="" call :subsetup
IF "%2"=="" SET butterworth=no
IF %sub% EQU 0 GOTO :subsonicdone
ECHO === Stage start: subsonic resonance filter ======================
IF /I "%butterworth%"=="no" (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
sinc -L %sub% -n 32767 ^
reverse ^
sinc -L %sub% -n 32767 ^
reverse
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: subsonic filter %sub% Hz & EXIT /B 1)
) ELSE (
:: sox command for 10th order
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
reverse ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
reverse
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: subsonic filter %sub% Hz & EXIT /B 1)
)
:subsonicdone
IF NOT EXIST %temp1file% (ECHO subsonic fail creating output & EXIT /B 1)
EXIT /B 0



:azimuthcorrection
:: input: (degrees in 360, range -45 to 45) (mute)
:: input: setup variables
:: input file: temp1file output file: temp1file

SET azimuthindegrees=%1
SET azmuted=no
IF /I "%2"=="mute" SET azmuted=mute

SET Result=ERROR
Call:Math round((%azimuthindegrees%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthindegrees=%Result%

Call:Math int(round((abs(%azimuthindegrees%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 225000 (ECHO ERROR: Azimuth correction at %azimuthindegrees% is impossible & EXIT /B 1)

IF NOT "%azmuted%"=="mute" ECHO === Stage start: azimuth correction ======================
call :getazimuth %azimuthindegrees% %azmuted%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees & EXIT /B %ERRORLEVEL%)

Call:Math Int(abs(%azimuthOppdB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in azimuth: checking db levels oppdb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthOppdB% dB Opp & EXIT /B 1)

Call:Math Int(abs(%azimuthSamedB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth checking db levels samedb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthSamedB% dB & EXIT /B 1)

if "%isazimuthclockwise%"=="yes" (
:cwazimuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2i%azimuthOppdB%, 2p,2p%azimuthSamedB%,1p%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: clockwise azimuth & EXIT /B 1)
) ELSE (
:ccwazumuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2p%azimuthOppdB%, 2p,2p%azimuthSamedB%,1i%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: counterclockwise azimuth & EXIT /B 1)
)
:azimuthcorrectiondone

IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (ECHO azimuth fail moving output & EXIT /B 1)
IF NOT EXIST %temp1file% (ECHO ERROR: azimuth correction fail creating output & EXIT /B 1)

IF NOT "%azmuted%"=="mute" echo Applied %azimuthdeg% degrees correction:
IF NOT "%azmuted%"=="mute" echo Same: %azimuthSamedB% dB Opposite: %azimuthOppdB% dB Clockwise: %isazimuthclockwise%
EXIT /B 0




:azimuthcorrectionspread
:: input: (degrees in 360, range -45 to 45) (mute)
:: input: setup variables
:: input file: temp1file output file: temp1file

SET azimuthindegrees=%1
SET azimuthspread=%2
SET azmuted=no
IF /I "%3"=="mute" SET azmuted=mute

SET Result=ERROR
Call:Math round((%azimuthindegrees%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthindegrees=%Result%

Call:Math int(round((abs(%azimuthindegrees%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 225000 (ECHO ERROR: Azimuth correction at %azimuthindegrees% is impossible & EXIT /B 1)


SET Result=ERROR
Call:Math round((%azimuthspread%), 14)
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
SET azimuthspread=%Result%

Call:Math int(round((abs(%azimuthspread%) * 5000), 0))
IF %Result%==ERROR ECHO ERROR: Math function call in setup & EXIT /B 1
IF %Result% GTR 125000 (ECHO ERROR: Azimuth spread correction at %azimuthspread% is impossible & EXIT /B 1)


IF NOT "%azmuted%"=="mute" ECHO === Stage start: azimuth correction ======================
call :getazimuthspread %azimuthindegrees% %azimuthspread% %azmuted%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees & EXIT /B %ERRORLEVEL%)

Call:Math Int(abs(%azimuthOppdB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in azimuth: checking db levels oppdb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthOppdB% dB Opp & EXIT /B 1)

Call:Math Int(abs(%azimuthSamedB%))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth checking db levels samedb & EXIT /B 1)
IF %Result% EQU 0 (ECHO ERROR: calling getazimuth with %azimuthindegrees% degrees gave %azimuthSamedB% dB & EXIT /B 1)

if "%isazimuthclockwise%"=="yes" (
:cwazimuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2i%azimuthOppdB%, 2p,2p%azimuthSamedB%,1p%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: clockwise azimuth & EXIT /B 1)
) ELSE (
:ccwazumuth
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p,1p%azimuthSamedB%,2p%azimuthOppdB%, 2p,2p%azimuthSamedB%,1i%azimuthOppdB%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: counterclockwise azimuth & EXIT /B 1)
)
:azimuthcorrectiondone

IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (ECHO azimuth fail moving output & EXIT /B 1)
IF NOT EXIST %temp1file% (ECHO ERROR: azimuth correction fail creating output & EXIT /B 1)

IF NOT "%azmuted%"=="mute" echo Applied %azimuthdeg% degrees correction:
IF NOT "%azmuted%"=="mute" echo Same: %azimuthSamedB% dB Opposite: %azimuthOppdB% dB Clockwise: %isazimuthclockwise%
EXIT /B 0



:getazimuthspread
:: input parameter: degrees (360)
:: output variables: azimuthSamedB and azimuthOppdB
IF "%1"=="" (ECHO I need to know how many degrees as input parameter & EXIT /B 1)
SET azimuthdeg=%1
SET azspread=%2
SET azmuted=no
IF /I "%3"=="mute" set azmuted=mute
SET LINazimuthOppdB=0
SET LINazimuthSamedB=0
SET RINazimuthOppdB=0
SET RINazimuthSamedB=0

SET Result=ERROR
Call:Math Int(abs(%azimuthdeg% * 10000))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth bounds check & EXIT /B 1)
IF %Result% GTR 450000 (ECHO == ERROR: Insane azimuth value == & EXIT /B 1)

set Result=ERROR
Call:Math round((Atn(1) / 45), 15)
IF %Result%==ERROR (ECHO ERROR: Math function call in getazimuth calculate rad/deg & EXIT /B 1)
set toradians=%Result%

Call:Math (%azimuthdeg%-%azspread%) * %toradians%
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth input degrees to radians & EXIT /B 1)
SET inputrad=%Result%

Call:Math abs(%azimuthdeg% * %toradians%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth absolute value in radians & EXIT /B 1)
SET azimuthrad=%Result%

IF "%inputrad%"=="%azimuthrad%" (set isazimuthclockwise=yes) ELSE (set isazimuthclockwise=no)

Call:Math (1 / Cos(%azimuthrad%)) - 1.0
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth cos of radians & EXIT /B 1)
SET samex=%Result%

CALL :todb %samex%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine with %samex% & EXIT /B 1)
SET azimuthSamedB=%dbvalue%

Call:Math Tan(%azimuthrad%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth tan of radians & EXIT /B 1)
SET oppx=%Result%

CALL :todb %oppx%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine 2 with %oppx% & EXIT /B 1)
SET azimuthOppdB=%dbvalue%

:getazimuthspreaddone
IF %azimuthOppdB%==0 EXIT /B 1
IF %azimuthSamedB%==0 EXIT /B 1
EXIT /B 0




:getazimuth
:: input parameter: degrees (360)
:: output variables: azimuthSamedB and azimuthOppdB
IF "%1"=="" (ECHO I need to know how many degrees as input parameter & EXIT /B 1)
SET azimuthdeg=%1
SET azmuted=no
IF /I "%2"=="mute" set azmuted=mute
SET azimuthOppdB=0
SET azimuthSamedB=0

SET Result=ERROR
Call:Math Int(abs(%azimuthdeg% * 10000))
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth bounds check & EXIT /B 1)
IF %Result% GTR 450000 (ECHO == ERROR: Insane azimuth value == & EXIT /B 1)

set Result=ERROR
Call:Math round((Atn(1) / 45), 15)
IF %Result%==ERROR (ECHO ERROR: Math function call in getazimuth calculate rad/deg & EXIT /B 1)
set toradians=%Result%

Call:Math %azimuthdeg% * %toradians%
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth input degrees to radians & EXIT /B 1)
SET inputrad=%Result%

Call:Math abs(%azimuthdeg% * %toradians%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth absolute value in radians & EXIT /B 1)
SET azimuthrad=%Result%

IF "%inputrad%"=="%azimuthrad%" (set isazimuthclockwise=yes) ELSE (set isazimuthclockwise=no)

Call:Math (1 / Cos(%azimuthrad%)) - 1.0
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth cos of radians & EXIT /B 1)
SET samex=%Result%

CALL :todb %samex%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine with %samex% & EXIT /B 1)
SET azimuthSamedB=%dbvalue%

Call:Math Tan(%azimuthrad%)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in getazimuth tan of radians & EXIT /B 1)
SET oppx=%Result%

CALL :todb %oppx%
IF %errorlevel% NEQ 0 (ECHO ERROR: I barfed trying to call todb subroutine 2 with %oppx% & EXIT /B 1)
SET azimuthOppdB=%dbvalue%

:getazimuthdone
IF %azimuthOppdB%==0 EXIT /B 1
IF %azimuthSamedB%==0 EXIT /B 1
EXIT /B 0



:todb
IF "%1"=="" (ECHO todb function requires input volume (1.00 = 0dB) & EXIT /B 1)
SET inputvolume=%1
SET dbvalue=borktest

SET Result=ERROR
Call:Math %inputvolume%
IF %Result%==ERROR (ECHO ERROR: Math function call fail in todb function check1 & EXIT /B 1)
IF %Result% EQU 0 (set dbvalue=-400.000 & goto :todbdone)

set Result=ERROR
Call:Math (Log(%inputvolume%) / Log (10.0)) * 20.0
IF "%Result%"=="ERROR" (ECHO ERROR: Math function log call failed in todb & EXIT /B 1)
set dbvalue=%Result%

:todbdone
if %dbvalue%==borktest EXIT /B 1
EXIT /B 0



:balancechannels
IF "%1"=="" (ECHO balancechannels function requires an input parameter in dB & EXIT /B 1)
:: Negative: turn up left side (we actually turn down other side)

SET Result=ERROR
Call:Math round((%1), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs & EXIT /B 1)
SET channeladjust=%Result%

SET Result=ERROR
Call:Math round((abs(%1)), 4)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs & EXIT /B 1)
set perchanneladjust=%Result%
IF %channeladjust%==%perchanneladjust% SET cutleft=0 ELSE SET cutleft=1

Call:Math round((%perchanneladjust% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call failed in balance channels abs check no change & EXIT /B 1)
IF %Result% EQU 0 (ECHO STATUS: Skipping channel balance for correction %perchanneladjust% dB & EXIT /B 0)

IF "%cutleft%"=="1" (
REM turn down left side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p-%perchanneladjust% 2p
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: balancechannels positive level %channeladjust% adjustment & EXIT /B 1)
) ELSE (
REM turn down right side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p 2p-%perchanneladjust%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: balancechannels negative level %channeladjust% adjustment & EXIT /B 1)
)

:balancechannelsdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL ) ELSE (EXIT /B 1)
EXIT /B 0



:crosstalk
SET inverted=%1
SET crosslevel=%2

set Result=ERROR
Call:Math round((%crosslevel% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in setup & EXIT /B 1)
if %Result% GEQ 0 GOTO :crosstalkdone

:: todo - actually mix an equalized version of crosstalk back in
:: todo - check input db

ECHO === Stage start: crosstalk correction==============================
IF /I "%inverted%"=="no" (
:normalcrosstalk
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p,2i%crosslevel%, 2p,1i%crosslevel%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: normal crosstalk & EXIT /B 1)
) ELSE (
:inversecrosstalk
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %temp2file% ^
remix 1p,2p%crosslevel%, 2p,1p%crosslevel%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: inverse crosstalk & EXIT /B 1)
)
:crosstalkdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file% >NUL) ELSE (EXIT /B 1)
EXIT /B 0



:noisereduction
IF NOT %1=="" SET %NRstrength%=%1

set Result=ERROR
Call:Math round((%NRstrength% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in noise reduction setup & EXIT /B 1)
IF %Result% LSS 1 GOTO :noisereductiondone
IF %Result% GEQ 10000 (ECHO ERROR: Noise reduction NRStrength: %NRstrength% is invalid & EXIT /B 1)

ECHO === Stage start: noise reduction ==================================

sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% -n ^
trim 0 %NRseconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo noise reduction profile & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% %progress% -V%verbose% %temp1file% %temp2file% ^
noisered %noiseprofile% %NRstrength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo noise reduction processing & EXIT /B 1)

:noisereductiondone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0




:speedup
IF NOT "%1"=="" SET speedup=%1

:: A setting of 1.0000 = no speedup
set Result=ERROR
Call:Math round((%speedup% * 10000), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in speedup while validating input & EXIT /B 1)
set speedupcheck=%Result%
IF %speedupcheck% EQU 10000 (GOTO :speedupdone)
IF %speedupcheck% LSS 1000 (ECHO ERROR speed: %speedup%, I'm not letting you slow down by more than 10x & EXIT /B 1)
IF %speedupcheck% GTR 100000 (ECHO ERROR speed:%speedup%, I'm not letting you speed up by more than 10x & EXIT /B 1)

ECHO === Stage start: speed correction==================================

sox --multi-threaded --buffer=%buffer% -V3 %progress% %temp1file% %temp2file% ^
rate -b 75 192k ^
biquad 1.0000000000 -1.9312626096 0.9313724325 1.0000000000 -0.8796912298 -0.1023703458 ^
speed %speedup% ^
rate -b 75 192k ^
biquad 1.0000000000 -0.8796912298 -0.1023703458 1.0000000000 -1.9312626096 0.9313724325 ^
rate %speedupdownsample%k
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: speedup and RIAA re-EQ & EXIT /B 1)

:speedupdone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0



:midside
ECHO === Stage start: convert stereo to mid-side =======================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %temp2file% ^
remix 1p-6.0206,2p-6.0206 1p-6.0206,2i-6.0206
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: stereo to mid-side & EXIT /B 1)
:midsidedone
IF EXIST %temp2file% (DEL %temp1file% & move %temp2file% %temp1file%) >NUL
EXIT /B 0



:midchannel
ECHO === Stage start: process mid channel ==============================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %midfile% ^
remix 1
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mix midside to mid & EXIT /B 1)

:midnoisereduction
rem IF /I NOT "%usenoisereduction%"=="yes" GOTO :midchanneldone
IF /I NOT "%midsideNR%"=="yes" GOTO :midchanneldone
ECHO === Stage start: mid-channel noise reduction =====================

sox --multi-threaded --buffer=%buffer% -V%verbose% %midfile% -n ^
trim %NRseconds% %NR2seconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mid noise reduction profiling & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %midfile% %temp2file% ^
noisered %noiseprofile% %NR2strength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: mid noise reduction processing & EXIT /B 1)

:midchanneldone
IF EXIST %temp2file% (DEL %midfile% & move %temp2file% %midfile%) >NUL
EXIT /B 0



:sidechannel
:sideeq
ECHO === Stage start: process side channel =============================
rem ## To restore a 150Hz side-channel bass cut, possibly used in mastering, we equalize
rem ## then more highpass subsonic to reduce vertical modulation rumble

IF %sidesub% NEQ 0 (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% %sidefile% ^
remix 2 ^
highpass %sidesub% .5412 highpass %sidesub% 1.3065 ^
reverse ^
highpass %sidesub% .5412 highpass %sidesub% 1.3065 ^
equalizer 80 0.65q %sidebassboostdb% ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel bass boost and rumble filter & EXIT /B 1)
) ELSE (
ECHO skipping side-channel rumble filter at setting %sidesub% Hz
IF %sidebassboostdb%==0 GOTO :sideeqdone
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %sidefile% ^
remix 2 ^
equalizer 80 0.65q %sidebassboostdb%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel bass boost without rumble filter & EXIT /B 1)
)
:sideeqdone

:sidenoisereduction
rem IF /I NOT "%usenoisereduction%"=="yes" GOTO :sidenoisereductiondone
IF NOT "%midsideNR%"=="yes" GOTO :sidenoisereductiondone

ECHO === Stage start: side-channel noise reduction ====================

sox --multi-threaded --buffer=%buffer% -V%verbose% %sidefile% -n ^
trim 0 %NRseconds% noiseprof %noiseprofile%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel noise reduction profiling & EXIT /B 1)

sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %sidefile% %temp2file% ^
noisered %noiseprofile% %NRstrength%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: side channel noise reduction processing & EXIT /B 1)
:sidenoisereductiondone

:sidechanneldone
IF EXIST %noiseprofile% (DEL %noiseprofile%)
IF EXIST %temp2file% (DEL %sidefile% & move %temp2file% %sidefile%)
EXIT /B 0


:unmidside
ECHO === Stage start: mid-side to stereo ===============================
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% --combine merge %midfile% %sidefile% %temp1file% ^
remix -m 1,2 1,2i
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: combine mid and side to stereo & EXIT /B 1)
EXIT /B 0


:makeoutput
IF NOT EXIST %temp1file% (ECHO ERROR: Expected input file %temp1file% doesn't exist & EXIT /B 1)

SET outname=%1
IF '%outname%'=='' SET outname=%outfile%

ECHO === Stage start: creating output file ============================

SET Result=ERROR
Call:Math int(%normalizeto% * 1000000)
IF %Result%==ERROR (ECHO ERROR: Math function call fail in todb function check1 & EXIT /B 1)
:: greater than 0 db setting disables normalization
IF %Result% GTR 0 (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% %temp1file% --comment="" -b 24 %outname% ^
silence 1 2 0 ^
reverse ^
silence 1 2 0 ^
reverse ^
gain %processinggainreduction%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: increase gain back to input & EXIT /B 1)
) ELSE (
sox --multi-threaded --buffer=%buffer% -V%verbose% %progress% --norm=%normalizeto% %temp1file% --comment="" -b 24 %outname% ^
gain %processinggainreduction%
IF !%ERRORLEVEL%! NEQ 0 (ECHO ERROR: Sox: final normalization & EXIT /B 1)
)

:makeoutputdone
IF NOT EXIST %outname% (ECHO ERROR: creating output file %outfile% & EXIT /B 1) ELSE ( ECHO ==== DONE: Created %outname% ==== )
EXIT /B 0


:cleanup
rem IF /i NOT "%disablecleanuptempfiles%"=="no" GOTO :cleanupdone
DEL %midfile% 2> NUL
DEL %sidefile% 2> NUL
DEL %temp1file% 2> NUL
DEL %temp2file% 2> NUL
DEL %noiseprofile% 2> NUL
DEL %tempdir%Math.vbs 2> NUL
:cleanupdone
EXIT /B 0






:findazimuth
ECHO -- Generating stepped output

set sub=300
SET rmslist=
SET degreelist=

CALL :setup %1
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

SET filteredfile=%noiseprofile%
SET rancount=1

sox --multi-threaded --buffer=%buffer% -V1 %progress% %infile% -b 24 %filteredfile% ^
pad 0.5 0.5 ^
gain -10 ^
rate -b 75 24k ^
sinc -L %sub% -n 32767 ^
highpass 2000 ^
reverse ^
sinc -L %sub% -n 32767 ^
highpass 2000 ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: findazimuth notch filtering & EXIT /B 1)


:testloop

SET /A "incs=steps-1"
DEL "%tempdir%%filebase%-iter*.wav" 2>NUL
FOR /L %%a in (0,1,%incs%) do (call :insideloopsub %%a)
ECHO/
sox --multi-threaded --buffer=%buffer% -V2 --combine concatenate "%tempdir%%filebase%-iter*.wav" --comment="" %temp1file%
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: trying to merge & EXIT /B 1)
DEL "%tempdir%%filebase%-iter*.wav" 2>NUL
ECHO/
CALL :makeoutput "%inpath%%filebase%-stereosteps.wav"
CALL :midside
CALL :makeoutput "%inpath%%filebase%-midsidesteps.wav"
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling makeoutput & EXIT /B 1)

echo ----------------------------------------
ECHO #: Degree MID+SIDERMS MIDRMS SIDE RMS

for /l %%n in (1,1,%steps%) do (
echo !resulttable[%%n]!
)

call :cleanup
ECHO/
ECHO -- Done. Analyze these files for phase and pan to find best correction:
ECHO -- "%inpath%%filebase%-stereosteps.wav";
ECHO -- "%inpath%%filebase%-midsidesteps.wav"
ECHO (%steps% steps are centered on %center% degrees, %fromcenter% degrees on each size)
pause

exit /b


:insideloopsub
set inparm=%1
IF 1%inparm% LSS 100 SET inparm=0%inparm%

SET Result=ERROR

Call:Math round( ( (%center% - %fromcenter%) + (%1 * 2 *%fromcenter% / ( %incs% ))) , 4) + 0.00001
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
SET degrees=%Result%

copy %filteredfile% %temp1file% >NUL 2>NUL
call :rmsgrabber %degrees%

sox %filteredfile% %tempdir%gaptemp.wav synth 2 sine 10 gain -120
sox --buffer=%buffer% -V2 %temp1file% "%tempdir%%filebase%-iter%inparm%.wav"

IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling rmsgrabber: insideloopsub & EXIT /B 1)


if NOT !rancount! EQU 1 (
SET "degreelist=%degreelist% %aztestvalue%"
SET "midlist=%midlist% %midrms%"
SET "sidelist=%sidelist% %siderms%"
SET "avglist=%avglist% %avgrms%"
SET "samelist=%samelist% %azimuthSamedB%"
SET "opplist=%opplist% %azimuthOppdB%"
) ELSE (
SET "degreelist=%aztestvalue%"
SET "midlist=%midrms%"
SET "sidelist=%siderms%"
SET "avglist=%avgrms%"
SET "samelist=%azimuthSamedB%"
SET "opplist=%azimuthOppdB%"
)

IF 1%rancount% LSS 100 (
SET resulttable[%rancount%]=0%rancount%: %aztestvalue%: %avgrms% -- %midrms% -- %siderms%
) ELSE (
SET resulttable[%rancount%]=%rancount%: %aztestvalue%: %avgrms% -- %midrms% -- %siderms%
)

SET /A "rancount=rancount+1"
GOTO :eof
exit /b 0



:rmsgrabber
:: input argument: degrees of azimuth
:: input file: %temp1file%
:: output: sets midrms siderms avgrms

:getactual
IF "%1"=="" (echo get mid-side RMS function needs input in degrees & EXIT /B 1)
set aztestvalue=%1
call :azimuthcorrection %aztestvalue% mute
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: calling azimuthcorrection 1 & EXIT /B 1)

:: azimuth-adjusted signal to mid
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %midfile% ^
remix 1p,2p
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: midside rms 1 & EXIT /B 1)

:: corrected signal to side
sox --multi-threaded --buffer=%buffer% -V%verbose% %temp1file% %sidefile% ^
remix 1p,2i
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: midside rms 2 & EXIT /B 1)

:: EXTRACT STDERR OUTPUT OF SoX ============
sox -V1 %midfile% -n stat -s 1 2> %tempdir%soxstat.log
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: makestats & EXIT /B 1)
for /f "tokens=*" %%i in ('FINDSTR RMS %tempdir%soxstat.log ^| FINDSTR amplitude') do ( set RMSline=%%i )
for /f "tokens=3 delims= " %%i IN ("%RMSline%") do (set midrms=%%i)
del %tempdir%soxstat.log

sox -V1 %sidefile% -n stat -s 1 2>%tempdir%soxstat.log
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: makestats rms amplitude 2 & EXIT /B 1)
for /f "tokens=*" %%i in ('FINDSTR RMS %tempdir%soxstat.log ^| FINDSTR amplitude') do ( set RMSline=%%i )
for /f "tokens=3 delims= " %%i IN ("%RMSline%") do (set siderms=%%i)
del %tempdir%soxstat.log

set Result=ERROR
Call:Math (%midrms% + %siderms%)/2
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set avgrms=%Result%

Call:Math round((%midrms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set midrms=%Result%
Call:Math round((%siderms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set siderms=%Result%
Call:Math round((%avgrms%), 0)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set avgrms=%Result%
Call:Math round((%aztestvalue%), 2)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
set aztestvalue=%Result%
Call:Math int((abs(%aztestvalue%) - %aztestvalue%)*10000)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=+%aztestvalue%
Call:Math ((%aztestvalue% - int(%aztestvalue%))*10)
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=%aztestvalue%.0
Call:Math %aztestvalue% * 10 - int( %aztestvalue% * 10 )
IF %Result%==ERROR (ECHO ERROR: Math function call in extraction & EXIT /B 1)
IF %Result% EQU 0 SET aztestvalue=%aztestvalue%0

rem echo degrees mr+sr m s
rem echo %aztestvalue% %avgrms%,%midrms%,%siderms%
echo | set /p=%aztestvalue%,

:rmsgrabberdone
exit /b
:findazimuthdone



:referencesteps
ECHO --- Azimuth-correcting your input file x 21 steps... ---
set sub=30
CALL :setup %1
IF NOT %ERRORLEVEL%==0 (echo ..quitting due to setup function subroutine errors & CALL :cleanup & EXIT /B 1)

SET filteredfile=%temp1file%

sox -S --multi-threaded --buffer=%buffer% -V1 %progress% %infile% %filteredfile% ^
rate -b 75 -L 48k ^
gain -%processinggainreduction% ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
lowpass 20000 ^
reverse ^
highpass %ch1f% %ch1q% highpass %ch2f% %ch2q% highpass %ch3f% %ch3q% highpass %ch4f% %ch4q% highpass %ch5f% %ch5q% ^
lowpass 20000 ^
reverse
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps notch filtering & EXIT /B 1)
DEL %tempdir%%filebase%steps*.wav 2>NUL
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps01.wav ^
remix 1p,1p-48.36,2p-21.16 2p,2p-48.36,1i-21.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps02.wav ^
remix 1p,1p-50.19,2p-22.08 2p,2p-50.19,1i-22.08 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps03.wav ^
remix 1p,1p-52.25,2p-23.11 2p,2p-52.25,1i-23.11 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps04.wav ^
remix 1p,1p-54.57,2p-24.27 2p,2p-54.57,1i-24.27 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps05.wav ^
remix 1p,1p-57.25,2p-25.61 2p,2p-57.25,1i-25.61 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps06.wav ^
remix 1p,1p-60.42,2p-27.20 2p,2p-60.42,1i-27.20 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps07.wav ^
remix 1p,1p-64.30,2p-29.14 2p,2p-64.30,1i-29.14 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps08.wav ^
remix 1p,1p-69.30,2p-31.64 2p,2p-69.30,1i-31.64 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps09.wav ^
remix 1p,1p-76.34,2p-35.16 2p,2p-76.34,1i-35.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps10.wav ^
remix 1p,1p-88.39,2p-41.18 2p,2p-88.39,1i-41.18 pad .5 2

sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps11.wav ^
pad .5 2
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps12.wav ^
remix 1p,1p-88.39,2i-41.18 2p,2p-88.39,1p-41.18 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps13.wav ^
remix 1p,1p-76.34,2i-35.16 2p,2p-76.34,1p-35.16 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps14.wav ^
remix 1p,1p-69.30,2i-31.64 2p,2p-69.30,1p-31.64 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps15.wav ^
remix 1p,1p-64.30,2i-29.14 2p,2p-64.30,1p-29.14 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps16.wav ^
remix 1p,1p-60.42,2i-27.20 2p,2p-60.42,1p-27.20 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps17.wav ^
remix 1p,1p-57.25,2i-25.61 2p,2p-57.25,1p-25.61 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps18.wav ^
remix 1p,1p-54.57,2i-24.27 2p,2p-54.57,1p-24.27 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps19.wav ^
remix 1p,1p-52.25,2i-23.11 2p,2p-52.25,1p-23.11 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps20.wav ^
remix 1p,1p-50.19,2i-22.08 2p,2p-50.19,1p-22.08 pad .5 .5
sox --multi-threaded -V%verbose% %filteredfile% -b 16 %tempdir%%filebase%steps21.wav ^
remix 1p,1p-48.36,2i-21.16 2p,2p-48.36,1p-21.16 pad .5 .5

sox -V%verbose% --multi-threaded --guard --combine concatenate ^
%tempdir%%filebase%steps*.wav ^
--comment="" "%inpath%%filebase%-referencesteps-stereo.wav"
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps recombinging steps & EXIT /B 1)

sox -V%verbose% "%inpath%%filebase%-referencesteps-stereo.wav" "%inpath%%filebase%-referencesteps-midside.wav" ^
remix 1p-6.0206,2p-6.0206 1p-6.0206,2i-6.0206
IF %ERRORLEVEL% NEQ 0 (ECHO ERROR: Sox: referencesteps making midside version of steps & EXIT /B 1)

:cleanupsteps
DEL %tempdir%%filebase%steps*.wav
CALL :cleanup
:referencestepsstepsdone
ECHO/
ECHO -- Done. Analyze these files for phase and pan to find best correction:
ECHO -- "%inpath%%filebase%-referencesteps-stereo.wav";
ECHO -- "%inpath%%filebase%-referencesteps-midside.wav"
ECHO (range of steps is -5 degrees ccw to +5 degrees clockwise)
pause

exit /B 0
goto :eof


:Math
REM echo VB command: "%*"
set Result=ERROR
for /f %%a in ('cscript /nologo %tempdir%Math.vbs "%*"') do set "Result=%%a"
exit /b %matherror%


:deviation
CALL :stddevfile
echo VB command: -- %* --
set Result=ERROR
for /f %%a in ('cscript /nologo %tempdir%Stddev.vbs "%*"') do set "Result=%%a"
exit /b %matherror%


:stddevfile
IF EXIST %tempdir%Stddev.vbs DEL %tempdir%Stddev.vbs >NUL
ECHO arData = Split(WScript.Arguments(0),",") >%tempdir%Stddev.vbs
echo Wscript.echo "hello" & StandardDeviation(arData),15 >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Wscript.echo StandardDeviation(arData) >>%tempdir%Stddev.vbs
ECHO WScript.Quit 1 >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Function StandardDeviation(arData) >>%tempdir%Stddev.vbs
ECHO StandardDeviation = 0 >>%tempdir%Stddev.vbs
ECHO If IsArray(arData) Then >>%tempdir%Stddev.vbs
ECHO Difference = 0 >>%tempdir%Stddev.vbs
ECHO Temp = 0 >>%tempdir%Stddev.vbs
ECHO Average = GetAverage(arData) >>%tempdir%Stddev.vbs
ECHO Amount = UBound(arData) >>%tempdir%Stddev.vbs
ECHO For i = 0 To Amount >>%tempdir%Stddev.vbs
ECHO Difference = ((arData(I) - Average) ^^ 2) >>%tempdir%Stddev.vbs
ECHO Temp = Temp + Difference >>%tempdir%Stddev.vbs
ECHO Difference = 0 >>%tempdir%Stddev.vbs
ECHO Next >>%tempdir%Stddev.vbs
ECHO StandardDeviation = Sqr(Temp / (Amount)) >>%tempdir%Stddev.vbs
ECHO End If >>%tempdir%Stddev.vbs
ECHO End Function >>%tempdir%Stddev.vbs
ECHO/ >>%tempdir%Stddev.vbs
ECHO Function GetAverage(arData) >>%tempdir%Stddev.vbs
ECHO GetAverage = 0 >>%tempdir%Stddev.vbs
ECHO If IsArray(arData) Then >>%tempdir%Stddev.vbs
ECHO total = UBound(arData) >>%tempdir%Stddev.vbs
ECHO For i = 0 To total >>%tempdir%Stddev.vbs
ECHO GetAverage = GetAverage + arData(i) >>%tempdir%Stddev.vbs
ECHO Next >>%tempdir%Stddev.vbs
ECHO GetAverage = GetAverage / (total + 1) >>%tempdir%Stddev.vbs
ECHO End If >>%tempdir%Stddev.vbs
ECHO End Function >>%tempdir%Stddev.vbs
EXIT /B 0



:nosox
echo/
echo ======== SoX.exe audio processor not found - What do you want to do? =========
echo/
echo [1] - EXIT: I'll download it myself from Sourceforge (and put sox.exe file in path)
echo [2] - Download sox.exe from author's site to work directory and continue (easy if working)
echo [xx] - Download and expand zip from Sourceforce to local directory and continue (needs PS 5)
echo [xx] - Just download installer from Sourceforce (so I can run it manually and move sox.exe)
echo/
choice /C 12 /N /M "Your choice: "
echo/

if errorlevel 4 goto :getinstalleronly
if errorlevel 3 goto :zipdownload
if errorlevel 2 goto :authordownload
EXIT /B 4

:authordownload

powershell -Command "Invoke-WebRequest http://hotnova.com/sox.exe -OutFile %cd%\sox.exe"
IF NOT EXIST sox.exe (echo Sorry, didn't work. & goto :nosox)
echo Got it!!
sox --version
IF NOT %ERRORLEVEL%==0 (echo Something's wrong with the downloaded file, sorry & goto :nosox)
EXIT /B 0

:nosoxdone
EXIT /B 0


:nofile
echo ==== There is no %infile% input file found! ====
echo (Reminder: With spaces in file names, surrounding quotes are needed)
pause
exit /b 9
:nofiledone


:cantdel
echo ==== %outfile% output or temp files exist and can't be deleted - do you have one open?? ====
pause
exit /b 7
This is the first I have seen anyone suggesting the use of a band pass filter to roll off both above and bellow the 1K test signals. I will go back and remeasure my final azimuth alignment test with an additional brick wall LP filter above 1K and see what happens to the results. I was also testing for equal harmonic distortion and got a null with that too on my final manual tonearm twist, so the LPF may spoil those measurements. My azimuth test setup already was using an Ozone brick wall high pass set at 400Hz. My cartridge is just meets or is very slightly better than its channel balance specs of 0.5 dB. I’m going to use an Ozone plugin that can decouple R from L and apply a ~0.5dB boost on record to the deficient channel to even that out. Saves me doing it during post processing.
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
I did not see a mention of band pass..? Was that in the script?
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
I have done bandapass too , to isolate and compare left and right phase difference when doing crosstalk and HTA investigations. But my concern is that filtering gives phase shift at 1k also, maybe I am wrong ?
 

Icewater_7

Member
Joined
May 18, 2023
Messages
51
Likes
11
Location
El Dorado Hills, CA
I have done bandapass too , to isolate and compare left and right phase difference when doing crosstalk and HTA investigations. But my concern is that filtering gives phase shift at 1k also, maybe I am wrong ?
There are two kinds of digital EQs that are offered by product developers, linear phase EQs and minimal phase EQs. For your measurement example, you might want to find a minimal phase variety. Digital EQs have improved a lot from the first ones when workflows were migrating from analog to digital ones. Modern EQs us oversampling and other tricks to make them perform better. “Linear” Phase” EQs appeal to me technically but they have a flaw in that they can produce “pre ringing” on transients that is definitely a type of distortion. On high frequency transients that pre-ringing is so short that it isn’t audible. Surprisingly, the pre-ringing is very audible at low frequencies. On a hard bass drum whack one can hear a “shoosh” kind of artifact building up before the transient that is clearly audible. You decide which kind of EQ you may wish to use when making digital recordings of your vinyl tracks according to what those recordings are for.
 
OP
Balle Clorin

Balle Clorin

Major Contributor
Joined
Dec 26, 2017
Messages
1,350
Likes
1,223
I filter the files to investigate in Cool Edit Pro. 10-15 years old software.
When playing music I only use the low rumble filter in Puffin. And whatever my Trinnov Amethyst decides to do…I can get new upgraded ADC/DAC cards for it now , but have not bothered..
 
Top Bottom