Skip to content

Commit 980c8ec

Browse files
committed
update shout
1 parent 44ba346 commit 980c8ec

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

erlang/shout/id3_tag_lengths.erl

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
-module(id3_tag_lengths).
2+
3+
-compile(export_all).
4+
5+
-import(lists, [foreach/2, map/2]).
6+
7+
test() ->
8+
Files = lib_files_find:files(".", "*.mp3", true),
9+
map(fun(F) -> file(F) end, Files).
10+
11+
file(F) ->
12+
(catch read_id3_tag(F)).
13+
14+
read_id3_tag(File) ->
15+
case file:open(File, [read, binary, raw]) of
16+
{ok, S} ->
17+
Size = filelib:file_size(File),
18+
Result = analyse(S, Size),
19+
file:close(S),
20+
Result;
21+
_Error ->
22+
error
23+
end.
24+
25+
analyse(S, Size) ->
26+
case (catch analyse1(S, Size)) of
27+
{'EXIT', _Why} ->
28+
io:format("_Why = ~p~n", [_Why]),
29+
error;
30+
StartStop ->
31+
StartStop
32+
end.
33+
34+
analyse1(S, Size) ->
35+
{ok, Bin} = file:pread(S, 0, 10000),
36+
{ok, StartTrust} = mp3_sync:find_sync(Bin, 1),
37+
{Type, StartUntrust} = parse_start_tag(Bin),
38+
Stop = parse_end_tag(S, Size),
39+
if
40+
StartTrust == StartUntrust ->
41+
true;
42+
true ->
43+
io:format("** error in header code: real=~p, type=~p, val=~p~n",
44+
[StartTrust, Type, StartUntrust])
45+
end,
46+
{StartTrust, Stop}.
47+
48+
parse_start_tag(<<$I, $D, $3, 3, 0, _Unsync:1, _Extended:1, _:5, K:32, _/binary>>) ->
49+
Tag = "ID3v2.3.0",
50+
Size = syncsafe2int(K),
51+
{Tag, Size + 10};
52+
parse_start_tag(<<$I, $D, $3, 4, 0, _Unsync:1, _Extended:1, Footer:1,
53+
_:4, K:32, _/binary>>) ->
54+
Tag = "ID3v2.3.0",
55+
Size = syncsafe2int(K),
56+
Size1 = case Footer of
57+
1 -> 10 + Size;
58+
0 -> Size
59+
end,
60+
{Tag, Size1};
61+
parse_start_tag(<<X:10/binary,_/binary>>) ->
62+
io:format("strange start tag~p~n",[X]),
63+
{error, 1}.
64+
65+
parse_end_tag(S, Size) ->
66+
{ok, B2} = file:pread(S, Size-128, 128),
67+
parse_v1_tag(B2, Size).
68+
69+
parse_v1_tag(<<$T,$A,$G,_/binary>>, Size) ->
70+
Size - 128;
71+
parse_v1_tag(_, Size) ->
72+
Size.
73+
74+
syncsafe2int(N) ->
75+
<<_:1,N1:7,_:1,N2:7,_:1,N3:7,_:1,N4:7>> = <<N:32>>,
76+
<<I:32>> = <<0:4,N1:7,N2:7,N3:7,N4:7>>,
77+
I.
78+

erlang/shout/mp3_sync.erl

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
-module(mp3_sync).
2+
3+
-export([find_sync/2]).
4+
5+
find_sync(Bin, N) ->
6+
case is_header(N, Bin) of
7+
{ok, Len1, _} ->
8+
case is_header(N + Len1, Bin) of
9+
{ok, Len2, _} ->
10+
case is_header(N + Len1 + Len2, Bin) of
11+
{ok, _, _} ->
12+
{ok, N};
13+
error ->
14+
find_sync(Bin, N+1)
15+
end;
16+
error ->
17+
find_sync(Bin, N+1)
18+
end;
19+
error ->
20+
find_sync(Bin, N+1)
21+
end.
22+
23+
24+
is_header(N, Bin) ->
25+
unpack_header(get_word(N, Bin)).
26+
27+
get_word(N, Bin) ->
28+
{_,<<C:4/binary,_/binary>>} = split_binary(Bin, N),
29+
C.
30+
31+
unpack_header(X) ->
32+
try decode_header(X)
33+
catch
34+
_:_ -> error
35+
end.
36+
37+
decode_header(<<2#11111111111:11,B:2,C:2,_D:1,E:4,F:2,G:1,Bits:9>>) ->
38+
Vsn = case B of
39+
0 -> {2,5};
40+
1 -> exit(badVsn);
41+
2 -> 2;
42+
3 -> 1
43+
end,
44+
Layer = case C of
45+
0 -> exit(badLayer);
46+
1 -> 3;
47+
2 -> 2;
48+
3 -> 1
49+
end,
50+
%% Protection = D,
51+
BitRate = bitrate(Vsn, Layer, E) * 1000,
52+
SampleRate = samplerate(Vsn, F),
53+
Padding = G,
54+
FrameLength = framelength(Layer, BitRate, SampleRate, Padding),
55+
if
56+
FrameLength < 21 ->
57+
exit(frameSize);
58+
true ->
59+
{ok, FrameLength, {Layer,BitRate,SampleRate,Vsn,Bits}}
60+
end;
61+
decode_header(_) ->
62+
exit(badHeader).
63+
64+
65+
bitrate(_,_,15) -> exit(1);
66+
bitrate(1,1,E) ->
67+
element(E+1, {free,32,64,96,128,160,192,224,256,288,
68+
320,352,384,416,448});
69+
bitrate(1,2,E) ->
70+
element(E+1, {free,32,48,56,64,80,96,112,128,160,
71+
192,224,256,320,384});
72+
bitrate(1,3,E) ->
73+
element(E+1, {free,32,40,48,56,64,80,96,112,128,160,192,
74+
224,256,320});
75+
bitrate(2,1,E) ->
76+
element(E+1, {free,32,48,56,64,80,96,112,128,144,160,
77+
176,192,224,256});
78+
bitrate(2,2,E) ->
79+
element(E+1, {free,8,16,24,32,40,48,56,64,80,96,112,
80+
128,144,160});
81+
bitrate(2,3,E) -> bitrate(2,2,E);
82+
bitrate({2,5}, L, E) -> bitrate(2, L, E).
83+
84+
%% samplerate Vsn F
85+
samplerate(1, 0) -> 44100;
86+
samplerate(1, 1) -> 48000;
87+
samplerate(1, 2) -> 32000;
88+
samplerate(2, 0) -> 22050;
89+
samplerate(2, 1) -> 24000;
90+
samplerate(2, 2) -> 16000;
91+
samplerate({2,5}, 0) -> 11025;
92+
samplerate({2,5}, 1) -> 12000;
93+
samplerate({2,5}, 2) -> 8000.
94+
95+
framelength(1, BitRate, SampleRate, Padding) ->
96+
((12*BitRate div SampleRate) + Padding) * 4;
97+
framelength(_, BitRate, SampleRate, Padding) ->
98+
(144 * BitRate div SampleRate) + Padding.

0 commit comments

Comments
 (0)