Including some fiddly maths examples and:
Speed up slow lecture videos.
Roundabout technique to watch a video at normal pitch but increased speed on Media Player Classic.
Code: Select all
;jeeswg's SoX (Sound eXchange) tutorial
;note: 12 semitones in an octave (7 whites notes, 5 black notes)
;speed n (change pitch, change duration) (make n times faster) ('Chipmunk effect')
;pitch n (change pitch, preserve duration) (make higher by n/100 semitones)
;pitch 100*n (change pitch, preserve duration) (make higher by n semitones)
;tempo n (preserve pitch, change duration) (make n times slower)
;note: to do 'speed' based on semitones see below
;note: to do 'pitch' based on faster/slower see below
vEffect1 := "" ;convert (no parameter)
vEffect2 := "trim 01:00 00:15" ;(start at point, get seconds after it) (e.g. 1:00 to 1:15)
vEffect3 := "reverse"
vEffect4 := "speed 2" ;faster (+ pitch higher)
vEffect5 := "speed 0.5" ;slower (+ pitch lower)
vEffect6 := "tempo 2" ;slower (+ preserve pitch)
vEffect7 := "tempo 0.5" ;slower (+ preserve pitch)
vEffect8 := "pitch 100" ;higher (+ preserve duration) (by 1 semitone) (e.g. C to C#)
vEffect9 := "pitch -100" ;lower (+ preserve duration) (by 1 semitone) (e.g. C# to C)
vEffect10 := "pitch 1200" ;higher (+ preserve duration) (by 1 octave)
vEffect11 := "pitch -1200" ;lower (+ preserve duration) (by 1 octave)
vEffect12 := "pitch 50" ;higher (+ preserve duration) (by 1/2 semitone)
vEffect13 := "pitch -50" ;lower (+ preserve duration) (by 1/2 semitone)
vEffect14 := "speed " 2**(1/12) ;higher (+ faster) (by 1 semitone)
vEffect15 := "speed " 2**(-1/12) ;lower (+ slower) (by 1 semitone)
vEffect16 := "speed " 2**(12/12) ;higher (+ faster) (by 1 octave)
vEffect17 := "speed " 2**(-12/12) ;lower (+ slower) (by 1 octave)
vEffect18 := "speed " 2**(0.5/12) ;higher (+ faster) (by 1/2 semitone)
vEffect19 := "speed " 2**(-0.5/12) ;lower (+ slower) (by 1/2 semitone)
vEffect20 := "pitch -702" ;lower (+ preserve duration) (by 7.02 semitones)
;vPathSox = %A_Desktop%\sox.exe
;vPath = %A_Desktop%\MyAudio.mp3
vDir2 = %A_Desktop%\z SoX
vCharClass := "[" Chr(1) "-" Chr(31) "\\/:*?""<>|]"
SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
if FileExist(vPathSox) && FileExist(vPath)
{
FileCreateDir, % vDir2
Run, % vDir2
Loop, 20
{
vEffect := vEffect%A_Index%
vEffectX := Trim(RegExReplace(vEffect, vCharClass, " "))
vPathNew := vDir2 "\" Format("{:02}", A_Index) RTrim(" " vEffectX) "." vExt
;MsgBox, "%vPathSox%" "%vPath%" "%vPathNew%" %vEffect%
if !FileExist(vPathNew)
RunWait, "%vPathSox%" "%vPath%" "%vPathNew%" %vEffect%,, Hide
}
}
MsgBox, % "done"
return
;==================================================
;DO 'SPEED' BASED ON SEMITONES
;speed n (change pitch, change duration) (make n times faster) ('Chipmunk effect')
;USAGE EXAMPLE:
;Shifting a song by half a semitone.
;Some songs, if you try and play along on the piano,
;appear not to match up with the notes, but fall in-between notes.
;If you adjust these songs by half a semitone,
;you should be able to play along.
vSemitones := 0.5
vEffect1 := "speed " 2**(vSemitones/12) ;higher (+ faster) (by n semitones)
vEffect2 := "speed " 2**(-vSemitones/12) ;lower (+ slower) (by n semitones)
RunWait, "%vPathSox%" "%vPath%" "%vPathNew1%" %vEffect1%,, Hide
RunWait, "%vPathSox%" "%vPath%" "%vPathNew2%" %vEffect2%,, Hide
;to make it higher by n semitones: 2^(n/12)
;to make it lower by n semitones: 2^(-n/12)
;e.g. 1/2 semitone
;2^(1/24) = 1.029302 ;24th root of 2
;2^(-1/24) = 0.971532 ;1/(24th root of 2)
;e.g. 1 semitone
;2^(1/12) = 1.059463 ;12th root of 2
;2^(-1/12) = 0.943874 ;1/(12th root of 2)
;==================================================
;DO 'PITCH' BASED ON FASTER/SLOWER
;pitch n (change pitch, preserve duration) (make higher by n/100 semitones)
;pitch 100*n (change pitch, preserve duration) (make higher by n semitones)
;note 2 ways for calculating vEffect2 that give the same answer
vMultiplier := 1.5
vEffect1 := "pitch " Round(1200 * Log(vMultiplier) / Log(2)) ;higher (+ preserve duration) (by multiplier) (e.g. 1.5 times higher)
vEffect2 := "pitch " Round(1200 * Log(1/vMultiplier) / Log(2)) ;lower (+ preserve duration) (by 1/multiplier) (e.g. 1.5 times lower, i.e. 0.667 times higher)
;vEffect2 := "pitch " -1200*Round(Log(vMultiplier)/Log(2)) ;lower (+ preserve duration) (by 1/multiplier) (e.g. 1.5 times lower, i.e. 0.667 times higher)
RunWait, "%vPathSox%" "%vPath%" "%vPathNew1%" %vEffect1%,, Hide
RunWait, "%vPathSox%" "%vPath%" "%vPathNew2%" %vEffect2%,, Hide
;mathematical explanation:
;desired pitch required n for 'pitch n'
;0.25p -2400
;0.5p -1200
;p 0
;2p 1200
;4p 2400
;rewritten:
;desired pitch required n for 'pitch n' parameter
;(2^-2)p (-2)1200
;(2^-1)p (-1)1200
;(2^-0)p (0)1200
;(2^1)p (1)1200
;(2^2)p (2)1200
;in general:
;(2^x)p 1200x
;We know to double the pitch we need 'pitch 1200'.
;To multiply the pitch by m, we need 'pitch n',
;where m=2^x, and n=1200x.
;Since, m = 2^x
;so, x = log_2 m = log m / log 2
;so, n = 1200x = 1200(log m / log 2)
;this gives code: 1200 * Log(vMultiplier) / Log(2)
;we use Round because the parameter expects an integer:
;so, Round(1200 * Log(vMultiplier) / Log(2))
;==================================================
;DO 'PITCH' BASED ON FASTER/SLOWER
;pitch n (change pitch, preserve duration) (make higher by n/100 semitones)
;pitch 100*n (change pitch, preserve duration) (make higher by n semitones)
;USAGE EXAMPLE:
;Speed up slow lecture videos.
;Roundabout technique to watch a video at normal pitch but increased speed on Media Player Classic.
;In MPC, you can watch a video at increased speed but you get the Chipmunk effect.
;In MPC, you can watch a video while listening to a different audio file (via a playlist).
;Using FFmpeg, you can extract the audio from a video file.
;So extract the audio, lower the pitch (preserve the duration),
;create a playlist which links the video and the new audio,
;and then when you play it at a specific increased speed,
;it will be at normal pitch but increased speed, 'quick talking'.
;E.g. if we want to play the video 1.5 times faster,
;we make the audio 1.5 times lower i.e. 0.667 times higher,
;so that when the Chipmunk effect occurs, the pitch will be normal.
vMultiplier := (1/1.5) ;will give 'pitch -702'
vEffect := "pitch " Round(1200 * Log(vMultiplier) / Log(2))
;MsgBox, % vEffect
RunWait, "%vPathSox%" "%vPath%" "%vPathNew%" %vEffect%,, Hide
;do 'speed 1.5' on this new file to hear what it will sound like
;to sum up the procedure:
;original wave (pitch: p, duration: d)
;new wave (pitch: (1/1.5)p=(2/3)p, duration: d)
;wave when played at 1.5x by MPC (pitch: p, duration: (1/1.5)d=(2/3)d)
;example text for a mpcpl file (Media Player Classic playlist):
;MPCPLAYLIST
;1,type,0
;1,filename,%vPathVideo%
;1,filename,%vPathAlternativeAudio%
;==================================================
Code: Select all
q:: ;SoX get file details
vPath = %A_Desktop%\MyAudio.mp3
vPathNew := "-n" ;null (i.e. no output file)
;vEffect := "stat"
vEffect := "stats" ;stat/stats give different information
vTarget = "%vPathSox%" "%vPath%" "%vPathNew%" %vEffect%
;vOutput := JEE_RunGetStdOut(vTarget)
vOutput := JEE_RunGetStdErr(vTarget)
Clipboard := vOutput
MsgBox, % vOutput
return
;==================================================
;JEE_RunWaitGetStdOut
JEE_RunGetStdOut(vTarget, vSize:="")
{
DetectHiddenWindows, On
vComSpec := A_ComSpec ? A_ComSpec : ComSpec
Run, % vComSpec,, Hide, vPID
WinWait, ahk_pid %vPID%
DllCall("kernel32\AttachConsole", UInt,vPID)
oShell := ComObjCreate("WScript.Shell")
oExec := oShell.Exec(vTarget)
vStdOut := ""
if !(vSize = "")
VarSetCapacity(vStdOut, vSize)
while !oExec.StdOut.AtEndOfStream
vStdOut := oExec.StdOut.ReadAll()
DllCall("kernel32\FreeConsole")
Process, Close, % vPID
return vStdOut
}
;==================================================
;JEE_RunWaitGetStdErr
JEE_RunGetStdErr(vTarget, vSize:="")
{
DetectHiddenWindows, On
vComSpec := A_ComSpec ? A_ComSpec : ComSpec
Run, % vComSpec,, Hide, vPID
WinWait, ahk_pid %vPID%
DllCall("kernel32\AttachConsole", UInt,vPID)
oShell := ComObjCreate("WScript.Shell")
oExec := oShell.Exec(vTarget)
vStdErr := ""
if !(vSize = "")
VarSetCapacity(vStdErr, vSize)
while !oExec.StdErr.AtEndOfStream
vStdErr := oExec.StdErr.ReadAll()
DllCall("kernel32\FreeConsole")
Process, Close, % vPID
return vStdErr
}
;==================================================