Bug 797671: Import Webrtc.org code from stable branch 3.12 (rev 2820) rs=jesup
[gecko.git] / media / webrtc / trunk / src / modules / audio_coding / codecs / opus / opus_interface.c
blobb441ab19c97b404ebbbb3b3c3928ff767c7c210b
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
11 #include "opus_interface.h"
13 #include <stdlib.h>
14 #include <string.h>
16 #include <opus.h>
18 #include "neteq_defines.h"
19 #include "signal_processing_library.h"
20 #include "resample_by_2_internal.h"
22 /* We always produce 20ms frames. */
23 #define WEBRTC_OPUS_MAX_ENCODE_FRAME_SIZE_MS (20)
25 /* The format allows up to 120ms frames. Since we
26 * don't control the other side, we must allow
27 * for packets that large. NetEq is currently
28 * limited to 60 ms on the receive side.
30 #define WEBRTC_OPUS_MAX_DECODE_FRAME_SIZE_MS (120)
32 /* Sample count is 48 kHz * FRAME_SIZE_MS. */
33 #define WEBRTC_OPUS_MAX_FRAME_SIZE (48*WEBRTC_OPUS_MAX_DECODE_FRAME_SIZE_MS)
35 struct WebRTCOpusEncInst{
36 int32_t state_32_64[8];
37 int32_t state_64_48[8];
38 OpusEncoder *encoder;
41 int16_t WebRtcOpus_EncoderCreate(OpusEncInst **inst,
42 int32_t channels)
44 OpusEncInst *state;
45 state = (OpusEncInst*)calloc(1, sizeof(*state));
46 if(state) {
47 int error;
48 state->encoder = opus_encoder_create(48000, channels,
49 OPUS_APPLICATION_VOIP, &error);
50 if (error == OPUS_OK && state->encoder != NULL) {
51 *inst = state;
52 return 0;
54 free(state);
56 return -1;
59 int16_t WebRtcOpus_EncoderFree(OpusEncInst *inst)
61 opus_encoder_destroy(inst->encoder);
62 free(inst);
63 return 0;
66 int16_t WebRtcOpus_EncodeNative(OpusEncInst *inst,
67 int16_t *audioIn,
68 uint8_t *encoded,
69 int16_t encodedLenByte,
70 int16_t len)
72 opus_int16 *audio = (opus_int16 *)audioIn;
73 unsigned char *coded = encoded;
75 int res = opus_encode(inst->encoder, audio, len, coded, encodedLenByte);
77 if (res > 0) {
78 return res;
81 return -1;
84 int16_t WebRtcOpus_Encode(OpusEncInst *inst,
85 int16_t *audioIn,
86 uint8_t *encoded,
87 int16_t encodedLenByte,
88 int16_t len)
90 int16_t buffer16[48*WEBRTC_OPUS_MAX_ENCODE_FRAME_SIZE_MS];
91 int32_t buffer32[64*WEBRTC_OPUS_MAX_ENCODE_FRAME_SIZE_MS+7];
92 int i;
94 if (len > 32*WEBRTC_OPUS_MAX_ENCODE_FRAME_SIZE_MS) {
95 return -1;
97 /* Resample 32 kHz to 64 kHz. */
98 for(i = 0; i < 7; i++) {
99 buffer32[i] = inst->state_64_48[i];
101 WebRtcSpl_UpBy2ShortToInt(audioIn, len, buffer32+7, inst->state_32_64);
102 /* Resample 64 kHz to 48 kHz. */
103 for(i = 0; i < 7; i++) {
104 inst->state_64_48[i] = buffer32[2*len+i];
106 len >>= 1;
107 WebRtcSpl_Resample32khzTo24khz(buffer32, buffer32, len);
108 len *= 3;
109 WebRtcSpl_VectorBitShiftW32ToW16(buffer16, len, buffer32, 15);
111 return WebRtcOpus_EncodeNative(inst, buffer16,
112 encoded, encodedLenByte, len);
115 int16_t WebRtcOpus_SetBitRate(OpusEncInst *inst, int32_t rate)
117 return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
121 struct WebRTCOpusDecInst{
122 int16_t state_48_32[8];
123 OpusDecoder *decoder;
126 int16_t WebRtcOpus_DecoderCreate(OpusDecInst **inst,
127 int32_t fs,
128 int32_t channels)
130 OpusDecInst *state;
131 state = (OpusDecInst*)calloc(1 ,sizeof(*state));
132 if(state) {
133 int error;
134 state->decoder = opus_decoder_create(48000, channels, &error);
135 if (error == OPUS_OK && state->decoder != NULL) {
136 *inst = state;
137 return 0;
139 free(state);
141 return -1;
144 int16_t WebRtcOpus_DecoderFree(OpusDecInst *inst)
146 opus_decoder_destroy(inst->decoder);
147 free(inst);
148 return 0;
151 int16_t WebRtcOpus_DecoderInit(OpusDecInst* inst)
153 int error = opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
154 if(error == OPUS_OK) {
155 memset(inst->state_48_32,0,sizeof(inst->state_48_32));
156 return 0;
158 return -1;
161 int16_t WebRtcOpus_DecodeNative(OpusDecInst *inst,
162 int16_t *encoded,
163 int16_t len,
164 int16_t *decoded,
165 int16_t *audioType)
167 unsigned char *coded = (unsigned char *)encoded;
168 opus_int16 *audio = (opus_int16 *)decoded;
170 int res = opus_decode(inst->decoder, coded, len, audio,
171 WEBRTC_OPUS_MAX_FRAME_SIZE, 0);
172 /* TODO: set to DTX for zero-length packets? */
173 *audioType = 0;
175 if(res > 0) {
176 return res;
178 return -1;
182 int16_t WebRtcOpus_Decode(OpusDecInst *inst,
183 int16_t *encoded,
184 int16_t len,
185 int16_t *decoded,
186 int16_t *audioType)
188 /* Enough for 120 ms (the largest Opus packet size) of mono audio at 48 kHz.
189 * This will need to be enlarged for stereo decoding. */
190 int16_t buffer16[WEBRTC_OPUS_MAX_FRAME_SIZE];
191 int32_t buffer32[WEBRTC_OPUS_MAX_FRAME_SIZE+7];
192 int decodedSamples;
193 int blocks;
194 int16_t outputSamples;
195 int i;
197 /* Decode to a temporary buffer. */
198 decodedSamples =
199 WebRtcOpus_DecodeNative(inst, encoded, len, buffer16, audioType);
200 if (decodedSamples < 0) {
201 return -1;
203 /* Resample from 48 kHz to 32 kHz. */
204 for (i = 0; i < 7; i++) {
205 buffer32[i] = inst->state_48_32[i];
207 for (i = 0; i < decodedSamples; i++) {
208 buffer32[7+i] = buffer16[i];
210 for (i = 0; i < 7; i++) {
211 inst->state_48_32[i] = (int16_t)buffer32[decodedSamples+i];
213 blocks = decodedSamples/3;
214 WebRtcSpl_Resample48khzTo32khz(buffer32, buffer32, blocks);
215 outputSamples = (int16_t)(blocks*2);
216 WebRtcSpl_VectorBitShiftW32ToW16(decoded, outputSamples, buffer32, 15);
218 return outputSamples;
222 int16_t WebRtcOpus_DecodePlc(OpusDecInst *inst,
223 int16_t *decoded,
224 int16_t noOfLostFrames)
226 /* TODO: We can pass NULL to opus_decode to activate packet
227 * loss concealment, but I don't know how many samples
228 * noOfLostFrames corresponds to. */
229 return -1;
232 int16_t WebRtcOpus_Version(char *version, int16_t lenBytes)
234 const char *opus = opus_get_version_string();
236 if (opus == NULL || version == NULL || lenBytes < 0) {
237 return -1;
240 strncpy(version, opus, lenBytes);
241 version[lenBytes-1] = '\0';
243 return 0;