1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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 */
10
11#include "webrtc/modules/audio_coding/main/acm2/acm_amrwb.h"
12
13#ifdef WEBRTC_CODEC_AMRWB
14// NOTE! GSM AMR-wb is not included in the open-source package. The
15// following interface file is needed:
16#include "webrtc/modules/audio_coding/main/codecs/amrwb/interface/amrwb_interface.h"
17#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
18#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
19#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
20#include "webrtc/system_wrappers/interface/trace.h"
21
22// The API in the header file should match the one below.
23//
24// int16_t WebRtcAmrWb_CreateEnc(AMRWB_encinst_t_** enc_inst);
25// int16_t WebRtcAmrWb_CreateDec(AMRWB_decinst_t_** dec_inst);
26// int16_t WebRtcAmrWb_FreeEnc(AMRWB_encinst_t_* enc_inst);
27// int16_t WebRtcAmrWb_FreeDec(AMRWB_decinst_t_* dec_inst);
28// int16_t WebRtcAmrWb_Encode(AMRWB_encinst_t_* enc_inst, int16_t* input,
29//                            int16_t len, int16_t* output, int16_t mode);
30// int16_t WebRtcAmrWb_EncoderInit(AMRWB_encinst_t_* enc_inst,
31//                                 int16_t dtx_mode);
32// int16_t WebRtcAmrWb_EncodeBitmode(AMRWB_encinst_t_* enc_inst,
33//                                    int format);
34// int16_t WebRtcAmrWb_Decode(AMRWB_decinst_t_* dec_inst);
35// int16_t WebRtcAmrWb_DecodePlc(AMRWB_decinst_t_* dec_inst);
36// int16_t WebRtcAmrWb_DecoderInit(AMRWB_decinst_t_* dec_inst);
37// int16_t WebRtcAmrWb_DecodeBitmode(AMRWB_decinst_t_* dec_inst,
38//                                   int format);
39#endif
40
41namespace webrtc {
42
43namespace acm2 {
44
45#ifndef WEBRTC_CODEC_AMRWB
46ACMAMRwb::ACMAMRwb(int16_t /* codec_id */)
47    : encoder_inst_ptr_(NULL),
48      encoding_mode_(-1),  // invalid value
49      encoding_rate_(0),   // invalid value
50      encoder_packing_format_(AMRBandwidthEfficient) {}
51
52ACMAMRwb::~ACMAMRwb() {}
53
54int16_t ACMAMRwb::InternalEncode(uint8_t* /* bitstream */,
55                                 int16_t* /* bitstream_len_byte */) {
56  return -1;
57}
58
59int16_t ACMAMRwb::EnableDTX() { return -1; }
60
61int16_t ACMAMRwb::DisableDTX() { return -1; }
62
63int16_t ACMAMRwb::InternalInitEncoder(
64    WebRtcACMCodecParams* /* codec_params */) {
65  return -1;
66}
67
68ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
69
70int16_t ACMAMRwb::InternalCreateEncoder() { return -1; }
71
72void ACMAMRwb::DestructEncoderSafe() { return; }
73
74int16_t ACMAMRwb::SetBitRateSafe(const int32_t /* rate */) { return -1; }
75
76int16_t ACMAMRwb::SetAMRwbEncoderPackingFormat(
77    ACMAMRPackingFormat /* packing_format */) {
78  return -1;
79}
80
81ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
82  return AMRUndefined;
83}
84
85int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
86    ACMAMRPackingFormat /* packing_format */) {
87  return -1;
88}
89
90ACMAMRPackingFormat ACMAMRwb::AMRwbDecoderPackingFormat() const {
91  return AMRUndefined;
92}
93
94#else     //===================== Actual Implementation =======================
95
96#define AMRWB_MODE_7k 0
97#define AMRWB_MODE_9k 1
98#define AMRWB_MODE_12k 2
99#define AMRWB_MODE_14k 3
100#define AMRWB_MODE_16k 4
101#define AMRWB_MODE_18k 5
102#define AMRWB_MODE_20k 6
103#define AMRWB_MODE_23k 7
104#define AMRWB_MODE_24k 8
105
106ACMAMRwb::ACMAMRwb(int16_t codec_id)
107    : encoder_inst_ptr_(NULL),
108      encoding_mode_(-1),  // invalid value
109      encoding_rate_(0) {  // invalid value
110  codec_id_ = codec_id;
111  has_internal_dtx_ = true;
112  encoder_packing_format_ = AMRBandwidthEfficient;
113  return;
114}
115
116ACMAMRwb::~ACMAMRwb() {
117  if (encoder_inst_ptr_ != NULL) {
118    WebRtcAmrWb_FreeEnc(encoder_inst_ptr_);
119    encoder_inst_ptr_ = NULL;
120  }
121  return;
122}
123
124int16_t ACMAMRwb::InternalEncode(uint8_t* bitstream,
125                                 int16_t* bitstream_len_byte) {
126  int16_t vad_decision = 1;
127  // sanity check, if the rate is set correctly. we might skip this
128  // sanity check. if rate is not set correctly, initialization flag
129  // should be false and should not be here.
130  if ((encoding_mode_ < AMRWB_MODE_7k) || (encoding_mode_ > AMRWB_MODE_24k)) {
131    *bitstream_len_byte = 0;
132    return -1;
133  }
134  *bitstream_len_byte = WebRtcAmrWb_Encode(
135      encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
136      reinterpret_cast<int16_t*>(bitstream), encoding_mode_);
137
138  // Update VAD, if internal DTX is used
139  if (has_internal_dtx_ && dtx_enabled_) {
140    if (*bitstream_len_byte <= (7 * frame_len_smpl_ / 160)) {
141      vad_decision = 0;
142    }
143    for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
144      vad_label_[n] = vad_decision;
145    }
146  }
147  // increment the read index this tell the caller that how far
148  // we have gone forward in reading the audio buffer
149  in_audio_ix_read_ += frame_len_smpl_;
150  return *bitstream_len_byte;
151}
152
153int16_t ACMAMRwb::EnableDTX() {
154  if (dtx_enabled_) {
155    return 0;
156  } else if (encoder_exist_) {  // check if encoder exist
157    // enable DTX
158    if (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_, 1) < 0) {
159      return -1;
160    }
161    dtx_enabled_ = true;
162    return 0;
163  } else {
164    return -1;
165  }
166}
167
168int16_t ACMAMRwb::DisableDTX() {
169  if (!dtx_enabled_) {
170    return 0;
171  } else if (encoder_exist_) {  // check if encoder exist
172    // disable DTX
173    if (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_, 0) < 0) {
174      return -1;
175    }
176    dtx_enabled_ = false;
177    return 0;
178  } else {
179    // encoder doesn't exists, therefore disabling is harmless
180    return 0;
181  }
182}
183
184int16_t ACMAMRwb::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
185  // sanity check
186  if (encoder_inst_ptr_ == NULL) {
187    return -1;
188  }
189
190  int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
191  status += (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_,
192                                     ((codec_params->enable_dtx) ? 1 : 0)) < 0)
193                ? -1
194                : 0;
195  status += (WebRtcAmrWb_EncodeBitmode(encoder_inst_ptr_,
196                                       encoder_packing_format_) < 0)
197                ? -1
198                : 0;
199  return (status < 0) ? -1 : 0;
200}
201
202ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
203
204int16_t ACMAMRwb::InternalCreateEncoder() {
205  return WebRtcAmrWb_CreateEnc(&encoder_inst_ptr_);
206}
207
208void ACMAMRwb::DestructEncoderSafe() {
209  if (encoder_inst_ptr_ != NULL) {
210    WebRtcAmrWb_FreeEnc(encoder_inst_ptr_);
211    encoder_inst_ptr_ = NULL;
212  }
213  // there is no encoder set the following
214  encoder_exist_ = false;
215  encoder_initialized_ = false;
216  encoding_mode_ = -1;  // invalid value
217  encoding_rate_ = 0;
218}
219
220int16_t ACMAMRwb::SetBitRateSafe(const int32_t rate) {
221  switch (rate) {
222    case 7000: {
223      encoding_mode_ = AMRWB_MODE_7k;
224      encoding_rate_ = 7000;
225      break;
226    }
227    case 9000: {
228      encoding_mode_ = AMRWB_MODE_9k;
229      encoding_rate_ = 9000;
230      break;
231    }
232    case 12000: {
233      encoding_mode_ = AMRWB_MODE_12k;
234      encoding_rate_ = 12000;
235      break;
236    }
237    case 14000: {
238      encoding_mode_ = AMRWB_MODE_14k;
239      encoding_rate_ = 14000;
240      break;
241    }
242    case 16000: {
243      encoding_mode_ = AMRWB_MODE_16k;
244      encoding_rate_ = 16000;
245      break;
246    }
247    case 18000: {
248      encoding_mode_ = AMRWB_MODE_18k;
249      encoding_rate_ = 18000;
250      break;
251    }
252    case 20000: {
253      encoding_mode_ = AMRWB_MODE_20k;
254      encoding_rate_ = 20000;
255      break;
256    }
257    case 23000: {
258      encoding_mode_ = AMRWB_MODE_23k;
259      encoding_rate_ = 23000;
260      break;
261    }
262    case 24000: {
263      encoding_mode_ = AMRWB_MODE_24k;
264      encoding_rate_ = 24000;
265      break;
266    }
267    default: {
268      return -1;
269    }
270  }
271  return 0;
272}
273
274int16_t ACMAMRwb::SetAMRwbEncoderPackingFormat(
275    ACMAMRPackingFormat packing_format) {
276  if ((packing_format != AMRBandwidthEfficient) &&
277      (packing_format != AMROctetAlligned) &&
278      (packing_format != AMRFileStorage)) {
279    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
280                 "Invalid AMRwb encoder packing-format.");
281    return -1;
282  } else {
283    if (WebRtcAmrWb_EncodeBitmode(encoder_inst_ptr_, packing_format) < 0) {
284      return -1;
285    } else {
286      encoder_packing_format_ = packing_format;
287      return 0;
288    }
289  }
290}
291
292ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
293  return encoder_packing_format_;
294}
295
296int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
297    ACMAMRPackingFormat packing_format) {
298  // Not implemented.
299  return -1;
300}
301
302ACMAMRPackingFormat ACMAMRwb::AMRwbDecoderPackingFormat() const {
303  // Not implemented.
304  return AMRUndefined;
305}
306
307#endif
308
309}  // namespace acm2
310
311}  // namespace webrtc
312