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
|
(*
* Copyright 2003 Savonet team
*
* This file is part of OCaml-Opus.
*
* OCaml-Opus 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-Opus 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-Opus; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)
(**
* An opus to wav converter using OCaml-Opus.
*
* @author Samuel Mimram
*)
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: opus2wav [options] source destination"
let use_ba = ref false
let () =
Arg.parse
[("-ba", Arg.Set use_ba, "Use big arrays")]
(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 sync, fd = Ogg.Sync.create_from_file !src in
Printf.printf "Checking file.\n%!";
let os, p1 =
let page = Ogg.Sync.read sync in
assert (Ogg.Page.bos page);
let serial = Ogg.Page.serialno page in
Printf.printf "Testing stream %nx.%!\n" serial;
let os = Ogg.Stream.create ~serial () in
Ogg.Stream.put_page os page;
let packet = Ogg.Stream.get_packet os in
assert (Opus.Decoder.check_packet packet);
Printf.printf "Found an opus stream!\n%!";
(os, packet)
in
let page = Ogg.Sync.read sync in
Ogg.Stream.put_page os page;
let p2 = Ogg.Stream.get_packet os in
let samplerate = 48000 in
Printf.printf "Creating decoder...\n%!";
let dec = Opus.Decoder.create ~samplerate p1 p2 in
let chans = Opus.Decoder.channels dec in
Printf.printf "Channels: %d\n%!" chans;
let vendor, comments = Opus.Decoder.comments dec in
Printf.printf "Vendor: %s\nComments:\n%!" vendor;
List.iter (fun (l, v) -> Printf.printf "- %s = %s\n%!" l v) comments;
Printf.printf "done.\n%!";
Printf.printf "Decoding...%!";
let max_frame_size = 960 * 6 in
let buflen = max_frame_size in
let outbuf = Array.make chans ([||] : float array) in
let decode () =
if !use_ba then (
let buf =
Array.init chans (fun _ ->
Bigarray.Array1.create Bigarray.float32 Bigarray.c_layout buflen)
in
let len = Opus.Decoder.decode_float_ba dec os buf 0 buflen in
for c = 0 to chans - 1 do
let pcm = Array.make len 0. in
for i = 0 to len - 1 do
pcm.(i) <- buf.(c).{i}
done;
outbuf.(c) <- pcm
done)
else (
let buf = Array.init chans (fun _ -> Array.make buflen 0.) in
let len = Opus.Decoder.decode_float dec os buf 0 buflen in
for c = 0 to chans - 1 do
outbuf.(c) <- Array.append outbuf.(c) (Array.sub buf.(c) 0 len)
done)
in
(try
while true do
try decode ()
with Ogg.Not_enough_data ->
let page = Ogg.Sync.read sync in
if Ogg.Page.serialno page = Ogg.Stream.serialno os then
Ogg.Stream.put_page os page
done
with Ogg.End_of_stream -> ());
Printf.printf "done.\n%!";
Unix.close fd;
let len = Array.length outbuf.(0) in
let datalen = 2 * len 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 samplerate;
(* freq *)
output_int oc (samplerate * 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;
for i = 0 to len - 1 do
for c = 0 to chans - 1 do
let x = outbuf.(c).(i) in
let x = int_of_float (x *. 32767.) in
output_short oc x
done
done;
close_out oc;
Gc.full_major ()
|