ripdad Posted July 5, 2010 Share Posted July 5, 2010 (edited) An attempt at a mp3 trimmer in AutoIt.If anyone knows a better way .. please, be my guest.expandcollapse popup#cs AutoIt Version 3.3.6 _Mp3_TrimFrames v.1.80 by ripdad Released: July 04, 2010 Updated: July 12, 2010 - Modes: $nMode 1 = Trim beginning $nMode 2 = Trim end - Accuracy without offset: +/- 2 Seconds - Notes: VBR not supported Tags other than ID3v1 and ID3v2 not supported #ce ; Example $mp3File = FileOpenDialog("Select File", @ScriptDir, "Select Mp3 File (*.mp3)", 1) If Not $mp3File Then Exit _Mp3_TrimFrames($mp3File, 1, 60); <-- Number of seconds to trim If @error <> 1 Then MsgBox(16, '_Mp3_TrimFrames', 'Trim Failed ' & @error) Exit Func _Mp3_TrimFrames($sFile, $nMode, $nSeconds = 0, $offset = 0); <-- Offset can be (+ or -) 1 or 2 seconds If Not FileExists($sFile) Then Return SetError(-1) If Not ($nMode == 1 Or $nMode == 2) Then Return SetError(-2); Invalid Mode If $nSeconds < 1 Then Return SetError(-3); Must Be a Positive Number ; Local $lcArray = _GetMP3Info($sFile); <-- Thanks to Lazycat If $lcArray = '' Then Return SetError(-4); Frame Not Found If $lcArray[1] = 1 Then Return SetError(-5); VBR Not Supported Local $fo = FileOpen($sFile, 16) If $fo = -1 Then Return SetError(-6); Failed to Open File Local $fr = FileRead($fo) FileClose($fo) ; Local $ss = StringSplit(StringReplace($fr, $lcArray[2], '|' & $lcArray[2]), '|'); Load Array Local $String, $nTrim = Round(($ss[0] / $lcArray[3]) * ($nSeconds + $offset)) If $ss[0] < 200 Then Return SetError(-7); Invalid Frame Count (Probably Corrupt Header) If $ss[0] < $nTrim Then Return SetError(-8); Trim Number Exceeds Total Frames ; If $nMode = 1 Then; Omit Beginning Frames $String = $ss[1]; Add First Frame For $i = $nTrim To $ss[0] $String &= $ss[$i] Next EndIf ; If $nMode = 2 Then; Omit Ending Frames For $i = 1 To $ss[0] - $nTrim $String &= $ss[$i] Next $String &= $ss[$ss[0]]; Add Last Frame EndIf ; Local $tName = StringTrimLeft($sFile, StringInStr($sFile, '\', 1, -1)); Get FileName Local $sPath = StringTrimRight($sFile, StringLen($tName)); Get Path $fo = FileOpen($sPath & 'Trimmed-' & $tName, 18) If $fo = -1 Then Return SetError(-9) If FileWrite($fo, $String) Then FileClose($fo); New file written - Original file stays intact ; ; Check trimmed file if written properly If StringLeft(FileRead($sPath & 'Trimmed-' & $tName), 2) = '0x' Then FileDelete($sPath & 'Trimmed-' & $tName) Return SetError(-10) EndIf Return SetError(1); Success EndFunc ; ; ;=============================================================================== ; ; Description: Retrieve MP3 (MP2, MPA) basic information ; Parameter(s): File name ; Requirement(s): None ; Return Value(s): On Success - array with data: ; 0 - MPEG version ; 1 - Layer ; 2 - Bitrate ; 3 - Frequency ; 4 - Channel Mode ; 5 - Duration ; 6 - Frames ; 7 - CRC protected ; 8 - Copyrighted ; 9 - Original ; On Failure empty string and sets @ERROR: ; 1 - Info not found ; Author(s): YDY (Lazycat) <mpc@nm.ru> ; Version: 1.2.00 ; Date: 30.12.2004 ; Note(s): None ; ;=============================================================================== Func _GetMP3Info($file) Local $data[10], $offset = 1, $isValid = 0, $isVBR = 0 Local $aVersion = StringSplit("MPEG 2.5|Undefined|MPEG 2.5|MPEG 1", "|") Local $aLayer = StringSplit("Undefined|Layer III|Layer II|Layer I", "|") Local $sBitrate = "" Local $sFrequency = "" Local $aChanMode = StringSplit("Stereo|Joint stereo|Dual channel|Mono", "|") Local $aFlags = StringSplit("No|Yes", "|") Local $head, $HeadID, $nVer, $nLay If _FileReadAtOffsetHEX($file, 1, 3) = "494433" Then ; ID3v2 tag found $offset = _HEXToSSInt(_FileReadAtOffsetHEX($file, 7, 4)) + 10 ; End of ID3v2 tag EndIf For $ic = $offset To 4096 + $offset $marker = _FileReadAtOffsetHEX($file, $ic, 2) $marker = StringLeft($marker, 3) If StringInStr("FFF, FFE", $marker) Then ; Assume that is frame start $head = _HexToBin(_FileReadAtOffsetHEX($file, $ic, 4)) $nVer = _GetRBits($head, 19, 2) $nLay = _GetRBits($head, 17, 2) If ($nVer <> 1) And ($nLay <> 0) Then If _FileReadAtOffsetHEX($file, $ic + 36, 4) = "58696E67" Then $isVBR = 1 ; Is this a right way?.. $isValid = 1 ExitLoop EndIf EndIf Next If Not $isValid Then SetError(1) ; Frame not found (not mp3 data?) Return ("") EndIf Select Case $nVer = 3 $sFrequency = "44100|48000|32000|Undefined" Case $nVer = 2 $sFrequency = "22050|24000|16000|Undefined" Case $nVer = 0 $sFrequency = "11025|12000|8000|Undefined" EndSelect Local $aFrequency = StringSplit($sFrequency, "|") $data[3] = _GetData($aFrequency, _GetRBits($head, 10, 2)) Local $pad = 0, $bitrate, $framesize, $frames, $length, $fps If _GetRBits($head, 9, 1) Then $pad = 1 If $isVBR Then $data[2] = "Variable" Else Select Case $nVer = 3 And $nLay = 3 $sBitrate = "Free|32|64|96|128|160|192|224|256|288|320|352|384|416|448|Undefined" Case $nVer = 3 And $nLay = 2 $sBitrate = "Free|32|48|56|64|80|96|112|128|160|192|224|256|320|384|Undefined" Case $nVer = 3 And $nLay = 1 $sBitrate = "Free|32|40|48|56|64|80|96|112|128|160|192|224|256|320|Undefined" Case $nVer = 2 And $nLay = 3 $sBitrate = "Free|32|48|56|64|80|96|112|128|144|160|176|192|224|256|Undefined" Case ($nVer = 2 And $nLay = 2) Or ($nVer = 2 And $nLay = 1) $sBitrate = "Free|8|16|24|32|40|48|56|64|80|96|112|128|144|160|Undefined" EndSelect Local $aBitrate = StringSplit($sBitrate, "|") $data[2] = _GetData($aBitrate, _GetRBits($head, 12, 4)) $bitrate = 1000 * $data[2] If $nLay = 3 Then $framesize = (((12 * $bitrate) / $data[3]) + $pad) * 4 $fps = $data[3] / 384 Else $framesize = ((144 * $bitrate) / $data[3]) + $pad $fps = $data[3] / 1152 EndIf $frames = FileGetSize($file) / $framesize $length = $frames / $fps EndIf Return StringSplit($isVBR & '|' & StringLeft(_BinToHex($head), 5) & '|' & $length, "|"); <- This line added by ripdad $data[0] = _GetData($aVersion, $nVer) $data[1] = _GetData($aLayer, $nLay) $data[4] = _GetData($aChanMode, _GetRBits($head, 6, 2)) $data[5] = StringFormat("%d:%02d", Int($length / 60), $length - Int($length / 60) * 60) $data[6] = Int($frames) $data[7] = _GetData($aFlags, Not _GetRBits($head, 16, 1)) ; CRC $data[8] = _GetData($aFlags, _GetRBits($head, 3, 1)) ; Private $data[9] = _GetData($aFlags, _GetRBits($head, 2, 1)) ; Original ;Return ($data) EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Support functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func _GetRBits($str, $pos, $size) Local $ic, $res = 0, $bStr = StringMid($str, 33 - $pos - $size, $size) For $ic = 0 To $size - 1 If StringMid($bStr, $size - $ic, 1) == "1" Then $res = $res + 2 ^ $ic Next Return ($res) EndFunc Func _GetData(ByRef $array, $val) If $val > UBound($array) - 1 Then Return ("Undefined") Return ($array[$val + 1]) EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Common functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func _HEXToSSInt($sHexStr) Local $iCnt, $iLen, $sTempStr = "", $iReturn = 0 For $iCnt = 1 To StringLen($sHexStr) Step 2 $sTempStr = $sTempStr & StringTrimLeft(_HexToBin(StringMid($sHexStr, $iCnt, 2)), 1) Next $iLen = StringLen($sTempStr) For $iCnt = 0 To $iLen - 1 $iReturn = $iReturn + Number(StringMid($sTempStr, $iLen - $iCnt, 1)) * 2 ^ $iCnt Next Return ($iReturn) EndFunc Func _HexToBin($str) Local $res = "", $i While StringLen($str) > 0 $val = Dec(StringRight($str, 1)) $str = StringTrimRight($str, 1) For $i = 1 To 4 $res = String(Mod($val, 2)) & $res $val = Int($val / 2) Next WEnd Return ($res) EndFunc Func _FileReadAtOffsetHEX($file, $offset, $bytes) Local $tfile = FileOpen($file, 0) Local $tstr = "", $i FileRead($tfile, $offset - 1) For $i = $offset To $offset + $bytes - 1 $tstr = $tstr & Hex(Asc(FileRead($tfile, 1)), 2) Next FileClose($tfile) Return ($tstr) EndFunc ; ; Author: joeyb1275 - Modified by ripdad Func _BinToHex($BinString) Local $Rev, $Hex = '' If Not IsInt(StringLen($BinString) / 4) Then $Num = ((StringLen($BinString) / 4) - Int(StringLen($BinString) / 4)) * 4 For $i = 1 To 4 - $Num Step 1 $BinString = '0' & $BinString Next EndIf For $i = 4 To StringLen($BinString) Step 4 $Bin = StringLeft(StringRight($BinString, $i), 4) Switch $Bin Case '0000' $Hex &= '|0' Case '0001' $Hex &= '|1' Case '0010' $Hex &= '|2' Case '0011' $Hex &= '|3' Case '0100' $Hex &= '|4' Case '0101' $Hex &= '|5' Case '0110' $Hex &= '|6' Case '0111' $Hex &= '|7' Case '1000' $Hex &= '|8' Case '1001' $Hex &= '|9' Case '1010' $Hex &= '|A' Case '1011' $Hex &= '|B' Case '1100' $Hex &= '|C' Case '1101' $Hex &= '|D' Case '1110' $Hex &= '|E' Case '1111' $Hex &= '|F' Case Else SetError(-1) EndSwitch Next If @error Then Return -1 $Rev = StringSplit(StringTrimLeft($Hex, 1), '|') $Hex = '' For $i = $Rev[0] To 1 Step -1 $Hex &= $Rev[$i] Next Return $Hex EndFunc ;Update: July 08, 2010 - Found a solution for the frame recognition limitation. Added a fileopen dialog.Update: July 12, 2010 - A few minor improvements. Also, I'm done with this. Off to other projects ... Edited July 13, 2010 by ripdad "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward Link to comment Share on other sites More sharing options...
ripdad Posted July 7, 2010 Author Share Posted July 7, 2010 - Update - Converted frames to seconds - plus a few other changes "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward Link to comment Share on other sites More sharing options...
chorao157 Posted July 7, 2010 Share Posted July 7, 2010 Trim Failed? wtf? Link to comment Share on other sites More sharing options...
JohnOne Posted July 8, 2010 Share Posted July 8, 2010 Trim Failed? wtf?Perhaps you should expand on your post.How does this help the OP in any way what so ever, to debug his code?In fact you shouldnt even bother replying to this without relevant info about your findings. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
ripdad Posted July 8, 2010 Author Share Posted July 8, 2010 Trim Failed? wtf?There's 11 error codes in the script.Which one is it?Also, you can find out what happened just by looking at the SetError line. "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now