File: speex2wav.ml

package info (click to toggle)
ocaml-xiph 1.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 820 kB
  • sloc: ml: 4,494; ansic: 3,994; makefile: 3
file content (136 lines) | stat: -rw-r--r-- 4,075 bytes parent folder | download | duplicates (2)
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
(*
 * Copyright 2008 Savonet team
 *
 * This file is part of OCaml-speex.
 *
 * OCaml-speex 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-speex 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-speex; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)

(**
  * A speex to wav converter using OCaml-speex.
  *
  * @author Samuel Mimram
  * @author Romain Beauxis
  *)

let src = ref ""
let dst = ref ""

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 usage = "usage: speex2wav source destination"
let () = Speex_decoder.register ()

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 dec, fd = Ogg_decoder.init_from_file !src in
  let { Ogg_decoder.audio_track; _ } = Ogg_decoder.get_standard_tracks dec in
  let audio_track =
    match audio_track with
      | None ->
          Printf.eprintf "Error: no audio track\n";
          exit 1
      | Some audio_track -> audio_track
  in
  let { Ogg_decoder.channels; sample_rate }, (encoder, comments) =
    Ogg_decoder.audio_info dec audio_track
  in
  Printf.printf "Encoder: %s\n" encoder;
  let print_comment (k, v) = Printf.printf "%s: %s\n" k v in
  Printf.printf "Comments:\n";
  List.iter print_comment comments;
  Printf.printf "\n";
  Printf.printf "Input file characteristics: %d channels, %d Hz\n" channels
    sample_rate;
  (* Using speex to decode the ogg. *)
  Printf.printf "\nDecoding...\n";
  flush_all ();
  let tmpdst, oc =
    Filename.open_temp_file ~mode:[Open_binary] "speex2wav" ".raw"
  in
  (try
     while true do
       Ogg_decoder.decode_audio dec audio_track (fun data ->
           let s1 = data.(0) in
           Array.iteri
             (fun n _ ->
               Array.iter
                 (fun s ->
                   let sample = int_of_float (s.(n) *. 32767.) in
                   output_short oc sample)
                 data)
             s1)
     done
   with Ogg_decoder.End_of_stream -> close_out oc);
  Printf.printf "Decoding finished, writing WAV..\n";
  Unix.close fd;
  (* Do the wav stuff. *)
  let datalen = (Unix.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 sample_rate;
  (* freq *)
  output_int oc (sample_rate * 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 = Bytes.create buflen in
   let r = ref 1 in
   let pos = ref 0 in
   while !r <> 0 do
     r := input ic buf 0 buflen;
     output oc buf 0 !r;
     pos := !pos + !r
   done);
  close_in ic;
  close_out oc;
  Unix.unlink tmpdst;
  Printf.printf "Done !\n";
  Gc.full_major ()