1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
(*
Copyright 2003 Savonet team
This file is part of OCaml-Vorbis.
OCaml-Vorbis is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
OCaml-Vorbis is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OCaml-Vorbis; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)
(**
An ogg to wav converter using OCaml-Vorbis.
@author Samuel Mimram
*)
(* $Id: ogg2wav.ml 3734 2007-05-22 11:49:18Z metamorph68 $ *)
let bufsize = 16 * 1024
let src = ref ""
let dst = ref ""
open Unix
let output_int chan n =
output_char chan (char_of_int ((n lsr 0) land 0xff));
output_char chan (char_of_int ((n lsr 8) land 0xff));
output_char chan (char_of_int ((n lsr 16) land 0xff));
output_char chan (char_of_int ((n lsr 24) land 0xff))
let output_short chan n =
output_char chan (char_of_int ((n lsr 0) land 0xff));
output_char chan (char_of_int ((n lsr 8) land 0xff))
let progress_bar =
let spin = ref 0 in
(
fun title pos tot ->
let nbeq = 40 in
let n = min (100. *. (float_of_int pos) /. (float_of_int tot)) 100. in
let e = int_of_float (n /. 100. *. (float_of_int nbeq)) in
Printf.printf "\r%s %6.2f%% [" title n;
for i = 1 to e do Printf.printf "=" done;
if e != nbeq then Printf.printf ">";
for i = e + 2 to nbeq do Printf.printf " " done;
Printf.printf "] ";
incr spin;
if !spin > 4 then spin := 1;
Printf.printf "%c%!"
(
if n = 100. then ' '
else
match !spin with
| 1 -> '|'
| 2 -> '/'
| 3 -> '-'
| 4 -> '\\'
| _ -> failwith "this did not happen"
)
)
let usage = "usage: ogg2wav [options] source destination"
let _ =
Arg.parse
[]
(
let pnum = ref (-1) in
(fun s -> incr pnum; match !pnum with
| 0 -> src := s
| 1 -> dst := s
| _ -> Printf.eprintf "Error: too many arguments\n"; exit 1
)
) usage;
if !src = "" || !dst = "" then
(
Printf.printf "%s\n" usage;
exit 1
);
let infos = Vorbis.get_info !src in
let vdr, cmt = Vorbis.get_comments !src in
Printf.printf "Input file characteristics: vorbis codec v%d, %d channel(s), %d Hz, %f s\n" infos.Vorbis.vorbis_version infos.Vorbis.audio_channels infos.Vorbis.audio_sample_rate infos.Vorbis.duration;
Printf.printf "* vendor: %s\n" vdr;
Array.iter (fun (c, v) -> Printf.printf "* %s: %s\n" c v) cmt;
(* Using vorbis to decode the ogg. *)
Printf.printf "\n";
let params =
{
Vorbis.sample_size = 16;
Vorbis.big_endian = false;
Vorbis.signed = true
}
in
let tmpdst,oc = Filename.open_temp_file ~mode:[Open_binary] "ogg2wav" ".raw" in
let df = Vorbis.open_dec_file !src ~fmt:params in
(
let buf = String.create bufsize in
let pos = ref 0 in
let tot = (int_of_float infos.Vorbis.duration) * 44100 * 2 * 2 in
try
while true
do
let r = Vorbis.decode df buf 0 bufsize in
output oc buf 0 r;
pos := !pos + r;
progress_bar "Decoding ogg:" !pos tot
done;
close_out oc; Vorbis.close_dec_file df
with
| End_of_file -> close_out oc; Vorbis.close_dec_file df
);
Printf.printf "\n";
(* Do the wav stuff. *)
let datalen = (stat tmpdst).st_size in
let ic = open_in_bin tmpdst in
let oc = open_out_bin !dst in
output_string oc "RIFF";
output_int oc (4 + 24 + 8 + datalen);
output_string oc "WAVE";
output_string oc "fmt ";
output_int oc 16;
output_short oc 1; (* WAVE_FORMAT_PCM *)
output_short oc 2; (* channels *)
output_int oc 44100; (* freq *)
output_int oc (44100 * 2 * 2); (* bytes / s *)
output_short oc (2 * 2); (* block alignment *)
output_short oc 16; (* bits per sample *)
output_string oc "data";
output_int oc datalen;
(
let buflen = 256 * 1024 in
let buf = String.create buflen in
let r = ref 1 in
let pos = ref 0 in
let tot = datalen in
while !r <> 0
do
r := input ic buf 0 buflen;
output oc buf 0 !r;
pos := !pos + !r;
progress_bar "Tagging wav: " !pos tot
done
);
close_in ic;
close_out oc;
Unix.unlink tmpdst;
Printf.printf "\n"
|