-
Notifications
You must be signed in to change notification settings - Fork 0
/
dec.go
113 lines (97 loc) · 2.34 KB
/
dec.go
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
package opus
/*
#cgo pkg-config: opus
#include <opus.h>
int opus_decoder_ctl_set_wrapped(OpusDecoder *st, int request, int value) {
return opus_decoder_ctl(st, request, value);
}
int opus_decoder_ctl_get_wrapped(OpusDecoder *st, int request, int *value) {
return opus_decoder_ctl(st, request, value);
}
*/
import "C"
import "unsafe"
// Opus Decoder Config
type OpusDecoderConfig struct {
// Sampling rate of input signal (Hz).
// This must be one of 8000, 12000, 16000, 24000, or 48000.
SampleRate int
// Number of channels in input signal.
MaxChannels int
// Decoder gain adjustment.
Gain int
// Enable inband forward error correction (FEC).
EnableInbandFEC bool
}
// Opus Decoder
type OpusDecoder struct {
// private handler
ph *C.OpusDecoder
// config
OpusDecoderConfig
}
// Decode
func (dec *OpusDecoder) Decode(in, out []byte) (int, error) {
var inPtr, outPtr unsafe.Pointer
if len(in) > 0 {
inPtr = unsafe.Pointer(&in[0])
}
if len(out) > 0 {
outPtr = unsafe.Pointer(&out[0])
}
fecFlag := C.int(0)
if dec.EnableInbandFEC {
fecFlag = C.int(1)
}
bytesPerSample := 2
frameSize := len(out) / bytesPerSample / dec.MaxChannels
n := C.opus_decode(dec.ph, (*C.uchar)(inPtr), C.int(len(in)),
(*C.opus_int16)(outPtr), C.int(frameSize), fecFlag)
if n < 0 {
return 0, genericErrors[int(n)]
}
return int(n) * bytesPerSample * dec.MaxChannels, nil
}
// Close
func (dec *OpusDecoder) Close() error {
C.opus_decoder_destroy(dec.ph)
dec.ph = nil
return nil
}
// Create Opus Decoder
func CreateOpusDecoder(config *OpusDecoderConfig) (dec *OpusDecoder, err error) {
config = populateDecConfig(config)
dec = &OpusDecoder{
OpusDecoderConfig: *config,
}
errNo := C.int(0)
dec.ph = C.opus_decoder_create(
C.int(dec.SampleRate), C.int(dec.MaxChannels), &errNo)
if errNo != C.OPUS_OK {
return nil, genericErrors[int(errNo)]
}
defer func() {
if errNo != C.OPUS_OK {
dec.Close()
}
}()
if dec.Gain != 0 {
if errNo = C.opus_decoder_ctl_set_wrapped(dec.ph, C.OPUS_SET_GAIN_REQUEST,
C.int(dec.Gain)); errNo != C.OPUS_OK {
return nil, genericErrors[int(errNo)]
}
}
return dec, nil
}
func populateDecConfig(c *OpusDecoderConfig) *OpusDecoderConfig {
if c == nil {
c = &OpusDecoderConfig{}
}
if c.SampleRate == 0 {
c.SampleRate = defaultSampleRate
}
if c.MaxChannels == 0 {
c.MaxChannels = defaultMaxChannels
}
return c
}