~ubuntu-branches/ubuntu/maverick/ocaml-vorbis/maverick

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"