Home | History | Annotate | Download | only in neteq
      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/neteq/comfort_noise.h"
     12 
     13 #include <assert.h>
     14 
     15 #include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
     16 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
     17 #include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
     18 #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
     19 #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
     20 
     21 namespace webrtc {
     22 
     23 void ComfortNoise::Reset() {
     24   first_call_ = true;
     25   internal_error_code_ = 0;
     26 }
     27 
     28 int ComfortNoise::UpdateParameters(Packet* packet) {
     29   assert(packet);  // Existence is verified by caller.
     30   // Get comfort noise decoder.
     31   AudioDecoder* cng_decoder = decoder_database_->GetDecoder(
     32       packet->header.payloadType);
     33   if (!cng_decoder) {
     34     delete [] packet->payload;
     35     delete packet;
     36     return kUnknownPayloadType;
     37   }
     38   decoder_database_->SetActiveCngDecoder(packet->header.payloadType);
     39   CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
     40   int16_t ret = WebRtcCng_UpdateSid(cng_inst,
     41                                     packet->payload,
     42                                     packet->payload_length);
     43   delete [] packet->payload;
     44   delete packet;
     45   if (ret < 0) {
     46     internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
     47     return kInternalError;
     48   }
     49   return kOK;
     50 }
     51 
     52 int ComfortNoise::Generate(size_t requested_length,
     53                            AudioMultiVector* output) {
     54   // TODO(hlundin): Change to an enumerator and skip assert.
     55   assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ ==  32000 ||
     56          fs_hz_ == 48000);
     57   // Not adapted for multi-channel yet.
     58   if (output->Channels() != 1) {
     59     return kMultiChannelNotSupported;
     60   }
     61 
     62   size_t number_of_samples = requested_length;
     63   int16_t new_period = 0;
     64   if (first_call_) {
     65     // Generate noise and overlap slightly with old data.
     66     number_of_samples = requested_length + overlap_length_;
     67     new_period = 1;
     68   }
     69   output->AssertSize(number_of_samples);
     70   // Get the decoder from the database.
     71   AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
     72   if (!cng_decoder) {
     73     return kUnknownPayloadType;
     74   }
     75   CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
     76   // The expression &(*output)[0][0] is a pointer to the first element in
     77   // the first channel.
     78   if (WebRtcCng_Generate(cng_inst, &(*output)[0][0],
     79                          static_cast<int16_t>(number_of_samples),
     80                          new_period) < 0) {
     81     // Error returned.
     82     output->Zeros(requested_length);
     83     internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
     84     return kInternalError;
     85   }
     86 
     87   if (first_call_) {
     88     // Set tapering window parameters. Values are in Q15.
     89     int16_t muting_window;  // Mixing factor for overlap data.
     90     int16_t muting_window_increment;  // Mixing factor increment (negative).
     91     int16_t unmuting_window;  // Mixing factor for comfort noise.
     92     int16_t unmuting_window_increment;  // Mixing factor increment.
     93     if (fs_hz_ == 8000) {
     94       muting_window = DspHelper::kMuteFactorStart8kHz;
     95       muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
     96       unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
     97       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
     98     } else if (fs_hz_ == 16000) {
     99       muting_window = DspHelper::kMuteFactorStart16kHz;
    100       muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
    101       unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
    102       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
    103     } else if (fs_hz_ == 32000) {
    104       muting_window = DspHelper::kMuteFactorStart32kHz;
    105       muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
    106       unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
    107       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
    108     } else {  // fs_hz_ == 48000
    109       muting_window = DspHelper::kMuteFactorStart48kHz;
    110       muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
    111       unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
    112       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
    113     }
    114 
    115     // Do overlap-add between new vector and overlap.
    116     size_t start_ix = sync_buffer_->Size() - overlap_length_;
    117     for (size_t i = 0; i < overlap_length_; i++) {
    118       /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
    119       // The expression (*output)[0][i] is the i-th element in the first
    120       // channel.
    121       (*sync_buffer_)[0][start_ix + i] =
    122           (((*sync_buffer_)[0][start_ix + i] * muting_window) +
    123               ((*output)[0][i] * unmuting_window) + 16384) >> 15;
    124       muting_window += muting_window_increment;
    125       unmuting_window += unmuting_window_increment;
    126     }
    127     // Remove |overlap_length_| samples from the front of |output| since they
    128     // were mixed into |sync_buffer_| above.
    129     output->PopFront(overlap_length_);
    130   }
    131   first_call_ = false;
    132   return kOK;
    133 }
    134 
    135 }  // namespace webrtc
    136