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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
exception Buffer_too_small
exception Internal_error
exception Invalid_packet
exception Unimplemented
exception Invalid_state
exception Alloc_fail
let () =
Callback.register_exception "opus_exn_buffer_too_small" Buffer_too_small;
Callback.register_exception "opus_exn_internal_error" Internal_error;
Callback.register_exception "opus_exn_invalid_packet" Invalid_packet;
Callback.register_exception "opus_exn_unimplemented" Unimplemented;
Callback.register_exception "opus_exn_invalid_state" Invalid_state;
Callback.register_exception "opus_exn_alloc_fail" Alloc_fail
let recommended_frame_size = 960 * 6
external version_string : unit -> string = "ocaml_opus_version_string"
let version_string = version_string ()
type max_bandwidth =
[ `Narrow_band | `Medium_band | `Wide_band | `Super_wide_band | `Full_band ]
type bandwidth = [ `Auto | max_bandwidth ]
type generic_control =
[ `Reset_state
| `Get_final_range of int ref
| `Get_pitch of int ref
| `Get_bandwidth of bandwidth ref
| `Set_lsb_depth of int
| `Get_lsb_depth of int ref
| `Set_phase_inversion_disabled of bool ]
module Decoder = struct
type control = [ generic_control | `Set_gain of int | `Get_gain of int ref ]
external check_packet : Ogg.Stream.packet -> bool
= "ocaml_opus_packet_check_header"
external channels : Ogg.Stream.packet -> int = "ocaml_opus_decoder_channels"
external comments : Ogg.Stream.packet -> string * string array
= "ocaml_opus_comments"
let comments p =
let vendor, comments = comments p in
let comments =
Array.map
(fun s ->
let n = String.index s '=' in
(String.sub s 0 n, String.sub s (n + 1) (String.length s - n - 1)))
comments
in
let comments = Array.to_list comments in
(vendor, comments)
type decoder
type t = {
header : Ogg.Stream.packet;
comments : Ogg.Stream.packet;
decoder : decoder;
}
external create : samplerate:int -> channels:int -> decoder
= "ocaml_opus_decoder_create"
let create ?(samplerate = 48000) p1 p2 =
if not (check_packet p1) then raise Invalid_packet;
let decoder = create ~samplerate ~channels:(channels p1) in
{ header = p1; comments = p2; decoder }
external apply_control : control -> decoder -> unit = "ocaml_opus_decoder_ctl"
let apply_control control t = apply_control control t.decoder
external decode_float :
decoder ->
Ogg.Stream.stream ->
float array array ->
int ->
int ->
bool ->
int
= "ocaml_opus_decoder_decode_float_byte" "ocaml_opus_decoder_decode_float"
let decode_float ?(decode_fec = false) t os buf ofs len =
decode_float t.decoder os buf ofs len decode_fec
external decode_float_ba :
decoder ->
Ogg.Stream.stream ->
(float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.t array ->
int ->
int ->
bool ->
int
= "ocaml_opus_decoder_decode_float_ba_byte"
"ocaml_opus_decoder_decode_float_ba"
let decode_float_ba ?(decode_fec = false) t os buf ofs len =
decode_float_ba t.decoder os buf ofs len decode_fec
let comments t = comments t.comments
let channels t = channels t.header
end
module Encoder = struct
type application = [ `Voip | `Audio | `Restricted_lowdelay ]
type signal = [ `Auto | `Voice | `Music ]
type bitrate = [ `Auto | `Bitrate_max | `Bitrate of int ]
type control =
[ generic_control
| `Set_complexity of int
| `Get_complexity of int ref
| `Set_bitrate of bitrate
| `Get_bitrate of bitrate ref
| `Set_vbr of bool
| `Get_vbr of bool ref
| `Set_vbr_constraint of bool
| `Get_vbr_constraint of bool ref
| `Set_force_channels of bool
| `Get_force_channels of bool ref
| `Set_max_bandwidth of max_bandwidth
| `Get_max_bandwidth of max_bandwidth
| `Set_bandwidth of bandwidth
| `Set_signal of signal
| `Get_signal of signal ref
| `Set_application of application
| `Get_application of application
| `Get_samplerate of int
| `Get_lookhead of int
| `Set_inband_fec of bool
| `Get_inband_fec of bool ref
| `Set_packet_loss_perc of int
| `Get_packet_loss_perc of int ref
| `Set_dtx of bool
| `Get_dtx of bool ref ]
type encoder
type t = {
header : Ogg.Stream.packet;
comments : Ogg.Stream.packet;
os : Ogg.Stream.stream;
samplerate : int;
enc : encoder;
}
external create :
pre_skip:int ->
comments:string array ->
gain:int ->
samplerate:int ->
channels:int ->
application:application ->
encoder * Ogg.Stream.packet * Ogg.Stream.packet
= "ocaml_opus_encoder_create_byte" "ocaml_opus_encoder_create"
let create ?(pre_skip = 3840) ?(comments = []) ?(gain = 0) ~samplerate
~channels ~application os =
let comments =
List.map
(fun (label, value) -> Printf.sprintf "%s=%s" label value)
comments
in
let comments = Array.of_list comments in
let enc, p1, p2 =
create ~pre_skip ~comments ~gain ~samplerate ~channels ~application
in
{ os; header = p1; comments = p2; samplerate; enc }
let header enc = enc.header
let comments enc = enc.comments
external apply_control : control -> encoder -> unit = "ocaml_opus_encoder_ctl"
let apply_control control enc = apply_control control enc.enc
external encode_float :
frame_size:int ->
encoder ->
Ogg.Stream.stream ->
float array array ->
int ->
int ->
int = "ocaml_opus_encode_float_byte" "ocaml_opus_encode_float"
external encode_float_ba :
frame_size:int ->
encoder ->
Ogg.Stream.stream ->
(float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.t array ->
int ->
int ->
int = "ocaml_opus_encode_float_ba_byte" "ocaml_opus_encode_float_ba"
let mk_encode_float fn ?(frame_size = 20.) t =
let frame_size = frame_size *. float t.samplerate /. 1000. in
fn ~frame_size:(int_of_float frame_size) t.enc t.os
let encode_float = mk_encode_float encode_float
let encode_float_ba = mk_encode_float encode_float_ba
external eos : Ogg.Stream.stream -> encoder -> unit = "ocaml_opus_encode_eos"
let eos t = eos t.os t.enc
end
|