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