Archive for March 2008
explanation of previous
Let’s start with sox. It can tell you various things about a file like this:
afroid-laptop% sox file.mp3 -e stat Samples read: 19139400 Length (seconds): 217.000000 Scaled by: 2147483647.0 Maximum amplitude: 0.999969 Minimum amplitude: -1.000000 Midline amplitude: -0.000015 Mean norm: 0.157586 Mean amplitude: -0.000860 RMS amplitude: 0.223554 Maximum delta: 1.243805 Minimum delta: 0.000000 Mean delta: 0.086869 RMS delta: 0.123678 Rough frequency: 3883 Volume adjustment: 1.000 afroid-laptop%
It takes a while to compute all these things, but I wasn’t able to ask for only the Length field. This output goes to the standard error, 2>&1 should be used. After I select the line starting with Length and cut the number itself using the format of that line.
afroid-laptop% sox dose-1.mp3 -e stat 2>&1 | grep ^Length | cut -d':' -f2
217.000000
afroid-laptop%
Now here comes some dc scripting which isn’t that straightforward. Here we go:
afroid-laptop% sox dose-1.ogg -e stat 2>&1 | grep ^Length | cut -d':' -f2 | sed
-e 's/$/ d [1+]si 300 ~ 0 <i sp sf lf lp ~ 0 <i sl 0 [d ll + d lf >s]ss 0 0 =s f/'
217.000000 d [1+]si 300 ~ 0 <i sp sf lf lp ~ 0 <i sl 0 [d ll + d lf >s]ss 0 0 =s f
afroid-laptop%
As a first step, the number 217 here is pushed to the stack and duplicated with command d. Let me use 1635 here to make more sense. The command f is for displaying the stack itself you work with. I use tabs to separate commands and stack content in following snippets. Just start dc and type the things below to experiment. So we start with something like this:
1635
f
1635
d
f
1635
1635
With [ and ], you can place strings to the stack, moreover, by saving those strings to registers, you can use them to execute as dc scripts. Here I save my increment script into register i.
[1+]
f
1+
1635
1635
si
f
1635
1635
Later on, there’s a division with remainder and if the remainder is not zero, then one is added to the result of division. The intent here is to split that mp3 to at most 5 minutes long slices. Feel free to try the followings with numbers dividable with 300 and note that 1 is not added.
300
f
300
1635
1635
~
f
135
5
1635
0
f
0
135
5
1635
<i
f
6
1635
At the next step I store the result into register p for “how many Parts required”, and the number below that in the stack into register f for “Full length”. After I load them back to the stack to determine the length of one slice.
sp sf lf lp
f
6
1635
Now compute the length of a slice with the same division technique as before and store it to register l for “Length” and load a 0 to the stack to start the loop (discussed later).
~ 0 <i f
273
sl f
0
f
0
In the loop, the following steps are performed: double the value on the top and load the Length, add them. At this point you have the next slice’s start time. Later I check whether I’m ready (if the starting time is greater than the Full length) and repeat loop if necessary. Note that I save this script to the same register as I use in the loop itself.
[d ll + d lf >s] ss 0 0 =s f
1638
1365
1092
819
546
273
0
So you have the timings in reverse order, therefore the command tac later on within the pipe. I delete the first line, because it’s greater than the Full length, use tac and a list of start timings is ready. For example, for a longer file it looks like this:
afroid-laptop% sox file2.mp3 -e stat 2>&1 | grep ^Length | cut -d':' -f2 | sed -e 's/$/ d [1+]si 300 ~ 0 <i sp sf lf lp ~ 0 <i sl 0 [d ll + d lf >s]ss 0 0 =s f/' | dc | sed -e '1d' | tac 0 181 afroid-laptop% sox file2.mp3 -e stat 2>&1 | grep ^Length Length (seconds): 361.116735 afroid-laptop%
Secont part will be the subject of an upcoming post ; )
split mp3 files again
afroid-laptop% cat filesplitter.sh #!/usr/bin/zsh FILE=$1; sox "$FILE" -e stat 2>&1 | grep ^Length | cut -d':' -f2 | sed -e 's/$/ d [1+]si 300 ~ 0 <i sp sf lf lp ~ 0 <i sl 0 [d ll + d lf >s]ss 0 0 =s f/' | dc | sed -e '1d' | tac | ( echo TITLE \"x\"; echo PERFORMER\"x\"; echo FILE \"$FILE\ " MP3; x=1; while read i; do echo \ TRACK $x AUDIO; echo \ \ TITLE \"x$x\"; echo \ \ PERFORMER \"x\"; echo \ \ INDEX 01 `echo $i "60 ~ sn p" | dc`:`echo $i "60 ~ p" | dc`:0; (( x = x + 1)) ; done ) | sed -e 's/"x\([0-9]\)"/"x0\1"/' | sed -e 's/\ \([0-9]\):/ 0\1:/' | sed -e 's/:\([0-9]\):/:0\1:/' | sed -e 's/:\([0-9]\)$ /:0\1/' | sed -e 's/TRACK\ \([0-9]\) /TRACK 0\1 /' > /tmp/splitter.cue && mp3spl t -c /tmp/splitter.cue $FILE -o @t afroid-laptop%
one of my favourite quotes
Ted: “I have to go the bathroom.”
Harry: “Just go down your leg Ted.”
Ted: “Really, you can urinate in these?”
Harry: “You can, the question is, would you want to.”
Sphere (1998)