Home | History | Annotate | Download | only in acm2
      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 
     41 namespace webrtc {
     42 
     43 namespace acm2 {
     44 
     45 #ifndef WEBRTC_CODEC_AMRWB
     46 ACMAMRwb::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 
     52 ACMAMRwb::~ACMAMRwb() {}
     53 
     54 int16_t ACMAMRwb::InternalEncode(uint8_t* /* bitstream */,
     55                                  int16_t* /* bitstream_len_byte */) {
     56   return -1;
     57 }
     58 
     59 int16_t ACMAMRwb::EnableDTX() { return -1; }
     60 
     61 int16_t ACMAMRwb::DisableDTX() { return -1; }
     62 
     63 int16_t ACMAMRwb::InternalInitEncoder(
     64     WebRtcACMCodecParams* /* codec_params */) {
     65   return -1;
     66 }
     67 
     68 ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
     69 
     70 int16_t ACMAMRwb::InternalCreateEncoder() { return -1; }
     71 
     72 void ACMAMRwb::DestructEncoderSafe() { return; }
     73 
     74 int16_t ACMAMRwb::SetBitRateSafe(const int32_t /* rate */) { return -1; }
     75 
     76 int16_t ACMAMRwb::SetAMRwbEncoderPackingFormat(
     77     ACMAMRPackingFormat /* packing_format */) {
     78   return -1;
     79 }
     80 
     81 ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
     82   return AMRUndefined;
     83 }
     84 
     85 int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
     86     ACMAMRPackingFormat /* packing_format */) {
     87   return -1;
     88 }
     89 
     90 ACMAMRPackingFormat 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 
    106 ACMAMRwb::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 
    116 ACMAMRwb::~ACMAMRwb() {
    117   if (encoder_inst_ptr_ != NULL) {
    118     WebRtcAmrWb_FreeEnc(encoder_inst_ptr_);
    119     encoder_inst_ptr_ = NULL;
    120   }
    121   return;
    122 }
    123 
    124 int16_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 
    153 int16_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 
    168 int16_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 
    184 int16_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 
    202 ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
    203 
    204 int16_t ACMAMRwb::InternalCreateEncoder() {
    205   return WebRtcAmrWb_CreateEnc(&encoder_inst_ptr_);
    206 }
    207 
    208 void 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 
    220 int16_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 
    274 int16_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 
    292 ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
    293   return encoder_packing_format_;
    294 }
    295 
    296 int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
    297     ACMAMRPackingFormat packing_format) {
    298   // Not implemented.
    299   return -1;
    300 }
    301 
    302 ACMAMRPackingFormat ACMAMRwb::AMRwbDecoderPackingFormat() const {
    303   // Not implemented.
    304   return AMRUndefined;
    305 }
    306 
    307 #endif
    308 
    309 }  // namespace acm2
    310 
    311 }  // namespace webrtc
    312