package opus

  1. Overview
  2. Docs
Bindings to libopus

Install

Dune Dependency

Authors

Maintainers

Sources

v1.0.0.tar.gz
md5=4a1490eba0b6bcd06e7849acfdf2c98a
sha512=625b1faed23a06c5f9a37bef3da817f9bac1b7493ceaab7d693d11aedd3125f75df50ae59ffd3088ffb0cb1e673ab82d14f4d684e757460a126232273865e846

doc/src/opus/opus.ml.html

Source file opus.ml

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
OCaml

Innovation. Community. Security.