add webrtc-audio-coding public library

This new lib contains the bare minimum to implement an iSAC encoder and
decoder.

The webrtc files have been copied from the revision as the existing
imported files (c8b569e0a7ad0b369e15f0197b3a558699ec8efa).
This commit is contained in:
Guillaume Desmottes 2020-03-26 15:32:43 +01:00
parent f13529b5b8
commit 34efc689c2
30 changed files with 8046 additions and 8 deletions

View File

@ -111,3 +111,15 @@ pkgconfig.generate(
] + platform_cflags, ] + platform_cflags,
libraries: libwebrtc_audio_processing, libraries: libwebrtc_audio_processing,
) )
pkgconfig.generate(
name: 'webrtc-audio-coding',
description: 'WebRTC Audio Coding library',
version: meson.project_version(),
filebase: 'webrtc-audio-coding',
subdirs: 'webrtc_audio_processing',
extra_cflags: [
'-DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD',
] + platform_cflags,
libraries: libwebrtc_audio_coding,
)

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include <assert.h>
#include "webrtc/base/checks.h"
namespace webrtc {
int AudioDecoder::Decode(const uint8_t* encoded, size_t encoded_len,
int sample_rate_hz, size_t max_decoded_bytes,
int16_t* decoded, SpeechType* speech_type) {
int duration = PacketDuration(encoded, encoded_len);
if (duration >= 0 &&
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
return -1;
}
return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
speech_type);
}
int AudioDecoder::DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
int sample_rate_hz, size_t max_decoded_bytes,
int16_t* decoded, SpeechType* speech_type) {
int duration = PacketDurationRedundant(encoded, encoded_len);
if (duration >= 0 &&
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
return -1;
}
return DecodeRedundantInternal(encoded, encoded_len, sample_rate_hz, decoded,
speech_type);
}
int AudioDecoder::DecodeInternal(const uint8_t* encoded, size_t encoded_len,
int sample_rate_hz, int16_t* decoded,
SpeechType* speech_type) {
return kNotImplemented;
}
int AudioDecoder::DecodeRedundantInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz, int16_t* decoded,
SpeechType* speech_type) {
return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
speech_type);
}
bool AudioDecoder::HasDecodePlc() const { return false; }
size_t AudioDecoder::DecodePlc(size_t num_frames, int16_t* decoded) {
return 0;
}
int AudioDecoder::IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
return 0;
}
int AudioDecoder::ErrorCode() { return 0; }
int AudioDecoder::PacketDuration(const uint8_t* encoded,
size_t encoded_len) const {
return kNotImplemented;
}
int AudioDecoder::PacketDurationRedundant(const uint8_t* encoded,
size_t encoded_len) const {
return kNotImplemented;
}
bool AudioDecoder::PacketHasFec(const uint8_t* encoded,
size_t encoded_len) const {
return false;
}
CNG_dec_inst* AudioDecoder::CngDecoderInstance() {
FATAL() << "Not a CNG decoder";
return NULL;
}
AudioDecoder::SpeechType AudioDecoder::ConvertSpeechType(int16_t type) {
switch (type) {
case 0: // TODO(hlundin): Both iSAC and Opus return 0 for speech.
case 1:
return kSpeech;
case 2:
return kComfortNoise;
default:
assert(false);
return kSpeech;
}
}
} // namespace webrtc

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_
#include <stdlib.h> // NULL
#include "webrtc/base/constructormagic.h"
#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
#include "webrtc/typedefs.h"
namespace webrtc {
// This is the interface class for decoders in NetEQ. Each codec type will have
// and implementation of this class.
class AudioDecoder {
public:
enum SpeechType {
kSpeech = 1,
kComfortNoise = 2
};
// Used by PacketDuration below. Save the value -1 for errors.
enum { kNotImplemented = -2 };
AudioDecoder() = default;
virtual ~AudioDecoder() = default;
// Decodes |encode_len| bytes from |encoded| and writes the result in
// |decoded|. The maximum bytes allowed to be written into |decoded| is
// |max_decoded_bytes|. Returns the total number of samples across all
// channels. If the decoder produced comfort noise, |speech_type|
// is set to kComfortNoise, otherwise it is kSpeech. The desired output
// sample rate is provided in |sample_rate_hz|, which must be valid for the
// codec at hand.
virtual int Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type);
// Same as Decode(), but interfaces to the decoders redundant decode function.
// The default implementation simply calls the regular Decode() method.
virtual int DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type);
// Indicates if the decoder implements the DecodePlc method.
virtual bool HasDecodePlc() const;
// Calls the packet-loss concealment of the decoder to update the state after
// one or several lost packets. The caller has to make sure that the
// memory allocated in |decoded| should accommodate |num_frames| frames.
virtual size_t DecodePlc(size_t num_frames, int16_t* decoded);
// Resets the decoder state (empty buffers etc.).
virtual void Reset() = 0;
// Notifies the decoder of an incoming packet to NetEQ.
virtual int IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp);
// Returns the last error code from the decoder.
virtual int ErrorCode();
// Returns the duration in samples-per-channel of the payload in |encoded|
// which is |encoded_len| bytes long. Returns kNotImplemented if no duration
// estimate is available, or -1 in case of an error.
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
// Returns the duration in samples-per-channel of the redandant payload in
// |encoded| which is |encoded_len| bytes long. Returns kNotImplemented if no
// duration estimate is available, or -1 in case of an error.
virtual int PacketDurationRedundant(const uint8_t* encoded,
size_t encoded_len) const;
// Detects whether a packet has forward error correction. The packet is
// comprised of the samples in |encoded| which is |encoded_len| bytes long.
// Returns true if the packet has FEC and false otherwise.
virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const;
// If this is a CNG decoder, return the underlying CNG_dec_inst*. If this
// isn't a CNG decoder, don't call this method.
virtual CNG_dec_inst* CngDecoderInstance();
virtual size_t Channels() const = 0;
protected:
static SpeechType ConvertSpeechType(int16_t type);
virtual int DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type);
virtual int DecodeRedundantInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type);
private:
RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoder);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/base/checks.h"
namespace webrtc {
AudioEncoder::EncodedInfo::EncodedInfo() = default;
AudioEncoder::EncodedInfo::~EncodedInfo() = default;
int AudioEncoder::RtpTimestampRateHz() const {
return SampleRateHz();
}
AudioEncoder::EncodedInfo AudioEncoder::Encode(uint32_t rtp_timestamp,
const int16_t* audio,
size_t num_samples_per_channel,
size_t max_encoded_bytes,
uint8_t* encoded) {
RTC_CHECK_EQ(num_samples_per_channel,
static_cast<size_t>(SampleRateHz() / 100));
EncodedInfo info =
EncodeInternal(rtp_timestamp, audio, max_encoded_bytes, encoded);
RTC_CHECK_LE(info.encoded_bytes, max_encoded_bytes);
return info;
}
bool AudioEncoder::SetFec(bool enable) {
return !enable;
}
bool AudioEncoder::SetDtx(bool enable) {
return !enable;
}
bool AudioEncoder::SetApplication(Application application) {
return false;
}
void AudioEncoder::SetMaxPlaybackRate(int frequency_hz) {}
void AudioEncoder::SetProjectedPacketLossRate(double fraction) {}
void AudioEncoder::SetTargetBitrate(int target_bps) {}
} // namespace webrtc

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
#include <algorithm>
#include <vector>
#include "webrtc/typedefs.h"
namespace webrtc {
// This is the interface class for encoders in AudioCoding module. Each codec
// type must have an implementation of this class.
class AudioEncoder {
public:
struct EncodedInfoLeaf {
size_t encoded_bytes = 0;
uint32_t encoded_timestamp = 0;
int payload_type = 0;
bool send_even_if_empty = false;
bool speech = true;
};
// This is the main struct for auxiliary encoding information. Each encoded
// packet should be accompanied by one EncodedInfo struct, containing the
// total number of |encoded_bytes|, the |encoded_timestamp| and the
// |payload_type|. If the packet contains redundant encodings, the |redundant|
// vector will be populated with EncodedInfoLeaf structs. Each struct in the
// vector represents one encoding; the order of structs in the vector is the
// same as the order in which the actual payloads are written to the byte
// stream. When EncoderInfoLeaf structs are present in the vector, the main
// struct's |encoded_bytes| will be the sum of all the |encoded_bytes| in the
// vector.
struct EncodedInfo : public EncodedInfoLeaf {
EncodedInfo();
~EncodedInfo();
std::vector<EncodedInfoLeaf> redundant;
};
virtual ~AudioEncoder() = default;
// Returns the maximum number of bytes that can be produced by the encoder
// at each Encode() call. The caller can use the return value to determine
// the size of the buffer that needs to be allocated. This value is allowed
// to depend on encoder parameters like bitrate, frame size etc., so if
// any of these change, the caller of Encode() is responsible for checking
// that the buffer is large enough by calling MaxEncodedBytes() again.
virtual size_t MaxEncodedBytes() const = 0;
// Returns the input sample rate in Hz and the number of input channels.
// These are constants set at instantiation time.
virtual int SampleRateHz() const = 0;
virtual int NumChannels() const = 0;
// Returns the rate at which the RTP timestamps are updated. The default
// implementation returns SampleRateHz().
virtual int RtpTimestampRateHz() const;
// Returns the number of 10 ms frames the encoder will put in the next
// packet. This value may only change when Encode() outputs a packet; i.e.,
// the encoder may vary the number of 10 ms frames from packet to packet, but
// it must decide the length of the next packet no later than when outputting
// the preceding packet.
virtual size_t Num10MsFramesInNextPacket() const = 0;
// Returns the maximum value that can be returned by
// Num10MsFramesInNextPacket().
virtual size_t Max10MsFramesInAPacket() const = 0;
// Returns the current target bitrate in bits/s. The value -1 means that the
// codec adapts the target automatically, and a current target cannot be
// provided.
virtual int GetTargetBitrate() const = 0;
// Accepts one 10 ms block of input audio (i.e., SampleRateHz() / 100 *
// NumChannels() samples). Multi-channel audio must be sample-interleaved.
// The encoder produces zero or more bytes of output in |encoded| and
// returns additional encoding information.
// The caller is responsible for making sure that |max_encoded_bytes| is
// not smaller than the number of bytes actually produced by the encoder.
// Encode() checks some preconditions, calls EncodeInternal() which does the
// actual work, and then checks some postconditions.
EncodedInfo Encode(uint32_t rtp_timestamp,
const int16_t* audio,
size_t num_samples_per_channel,
size_t max_encoded_bytes,
uint8_t* encoded);
virtual EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) = 0;
// Resets the encoder to its starting state, discarding any input that has
// been fed to the encoder but not yet emitted in a packet.
virtual void Reset() = 0;
// Enables or disables codec-internal FEC (forward error correction). Returns
// true if the codec was able to comply. The default implementation returns
// true when asked to disable FEC and false when asked to enable it (meaning
// that FEC isn't supported).
virtual bool SetFec(bool enable);
// Enables or disables codec-internal VAD/DTX. Returns true if the codec was
// able to comply. The default implementation returns true when asked to
// disable DTX and false when asked to enable it (meaning that DTX isn't
// supported).
virtual bool SetDtx(bool enable);
// Sets the application mode. Returns true if the codec was able to comply.
// The default implementation just returns false.
enum class Application { kSpeech, kAudio };
virtual bool SetApplication(Application application);
// Tells the encoder about the highest sample rate the decoder is expected to
// use when decoding the bitstream. The encoder would typically use this
// information to adjust the quality of the encoding. The default
// implementation just returns true.
virtual void SetMaxPlaybackRate(int frequency_hz);
// Tells the encoder what the projected packet loss rate is. The rate is in
// the range [0.0, 1.0]. The encoder would typically use this information to
// adjust channel coding efforts, such as FEC. The default implementation
// does nothing.
virtual void SetProjectedPacketLossRate(double fraction);
// Tells the encoder what average bitrate we'd like it to produce. The
// encoder is free to adjust or disregard the given bitrate (the default
// implementation does the latter).
virtual void SetTargetBitrate(int target_bps);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INCLUDE_WEBRTC_CNG_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INCLUDE_WEBRTC_CNG_H_
#include <stddef.h>
#include "webrtc/typedefs.h"
#ifdef __cplusplus
extern "C" {
#endif
#define WEBRTC_CNG_MAX_LPC_ORDER 12
#define WEBRTC_CNG_MAX_OUTSIZE_ORDER 640
/* Define Error codes. */
/* 6100 Encoder */
#define CNG_ENCODER_NOT_INITIATED 6120
#define CNG_DISALLOWED_LPC_ORDER 6130
#define CNG_DISALLOWED_FRAME_SIZE 6140
#define CNG_DISALLOWED_SAMPLING_FREQUENCY 6150
/* 6200 Decoder */
#define CNG_DECODER_NOT_INITIATED 6220
typedef struct WebRtcCngEncInst CNG_enc_inst;
typedef struct WebRtcCngDecInst CNG_dec_inst;
/****************************************************************************
* WebRtcCng_CreateEnc/Dec(...)
*
* These functions create an instance to the specified structure
*
* Input:
* - XXX_inst : Pointer to created instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcCng_CreateEnc(CNG_enc_inst** cng_inst);
int16_t WebRtcCng_CreateDec(CNG_dec_inst** cng_inst);
/****************************************************************************
* WebRtcCng_InitEnc/Dec(...)
*
* This function initializes a instance
*
* Input:
* - cng_inst : Instance that should be initialized
*
* - fs : 8000 for narrowband and 16000 for wideband
* - interval : generate SID data every interval ms
* - quality : Number of refl. coefs, maximum allowed is 12
*
* Output:
* - cng_inst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcCng_InitEnc(CNG_enc_inst* cng_inst, int fs, int16_t interval,
int16_t quality);
void WebRtcCng_InitDec(CNG_dec_inst* cng_inst);
/****************************************************************************
* WebRtcCng_FreeEnc/Dec(...)
*
* These functions frees the dynamic memory of a specified instance
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcCng_FreeEnc(CNG_enc_inst* cng_inst);
int16_t WebRtcCng_FreeDec(CNG_dec_inst* cng_inst);
/****************************************************************************
* WebRtcCng_Encode(...)
*
* These functions analyzes background noise
*
* Input:
* - cng_inst : Pointer to created instance
* - speech : Signal to be analyzed
* - nrOfSamples : Size of speech vector
* - forceSID : not zero to force SID frame and reset
*
* Output:
* - bytesOut : Nr of bytes to transmit, might be 0
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcCng_Encode(CNG_enc_inst* cng_inst, int16_t* speech,
size_t nrOfSamples, uint8_t* SIDdata,
size_t* bytesOut, int16_t forceSID);
/****************************************************************************
* WebRtcCng_UpdateSid(...)
*
* These functions updates the CN state, when a new SID packet arrives
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - SID : SID packet, all headers removed
* - length : Length in bytes of SID packet
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcCng_UpdateSid(CNG_dec_inst* cng_inst, uint8_t* SID,
size_t length);
/****************************************************************************
* WebRtcCng_Generate(...)
*
* These functions generates CN data when needed
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - outData : pointer to area to write CN data
* - nrOfSamples : How much data to generate
* - new_period : >0 if a new period of CNG, will reset history
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcCng_Generate(CNG_dec_inst* cng_inst, int16_t* outData,
size_t nrOfSamples, int16_t new_period);
/*****************************************************************************
* WebRtcCng_GetErrorCodeEnc/Dec(...)
*
* This functions can be used to check the error code of a CNG instance. When
* a function returns -1 a error code will be set for that instance. The
* function below extract the code of the last error that occurred in the
* specified instance.
*
* Input:
* - CNG_inst : CNG enc/dec instance
*
* Return value : Error code
*/
int16_t WebRtcCng_GetErrorCodeEnc(CNG_enc_inst* cng_inst);
int16_t WebRtcCng_GetErrorCodeDec(CNG_dec_inst* cng_inst);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INCLUDE_WEBRTC_CNG_H_

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
#include <vector>
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
namespace webrtc {
template <typename T>
class AudioDecoderIsacT final : public AudioDecoder {
public:
AudioDecoderIsacT();
explicit AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo);
~AudioDecoderIsacT() override;
bool HasDecodePlc() const override;
size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
void Reset() override;
int IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) override;
int ErrorCode() override;
size_t Channels() const override;
int DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) override;
private:
typename T::instance_type* isac_state_;
LockedIsacBandwidthInfo* bwinfo_;
int decoder_sample_rate_hz_;
RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacT);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
#include "webrtc/base/checks.h"
namespace webrtc {
template <typename T>
AudioDecoderIsacT<T>::AudioDecoderIsacT()
: AudioDecoderIsacT(nullptr) {}
template <typename T>
AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo)
: bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) {
RTC_CHECK_EQ(0, T::Create(&isac_state_));
T::DecoderInit(isac_state_);
if (bwinfo_) {
IsacBandwidthInfo bi;
T::GetBandwidthInfo(isac_state_, &bi);
bwinfo_->Set(bi);
}
}
template <typename T>
AudioDecoderIsacT<T>::~AudioDecoderIsacT() {
RTC_CHECK_EQ(0, T::Free(isac_state_));
}
template <typename T>
int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000)
<< "Unsupported sample rate " << sample_rate_hz;
if (sample_rate_hz != decoder_sample_rate_hz_) {
RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz));
decoder_sample_rate_hz_ = sample_rate_hz;
}
int16_t temp_type = 1; // Default is speech.
int ret =
T::DecodeInternal(isac_state_, encoded, encoded_len, decoded, &temp_type);
*speech_type = ConvertSpeechType(temp_type);
return ret;
}
template <typename T>
bool AudioDecoderIsacT<T>::HasDecodePlc() const {
return false;
}
template <typename T>
size_t AudioDecoderIsacT<T>::DecodePlc(size_t num_frames, int16_t* decoded) {
return T::DecodePlc(isac_state_, decoded, num_frames);
}
template <typename T>
void AudioDecoderIsacT<T>::Reset() {
T::DecoderInit(isac_state_);
}
template <typename T>
int AudioDecoderIsacT<T>::IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
int ret = T::UpdateBwEstimate(isac_state_, payload, payload_len,
rtp_sequence_number, rtp_timestamp,
arrival_timestamp);
if (bwinfo_) {
IsacBandwidthInfo bwinfo;
T::GetBandwidthInfo(isac_state_, &bwinfo);
bwinfo_->Set(bwinfo);
}
return ret;
}
template <typename T>
int AudioDecoderIsacT<T>::ErrorCode() {
return T::GetErrorCode(isac_state_);
}
template <typename T>
size_t AudioDecoderIsacT<T>::Channels() const {
return 1;
}
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
#include <vector>
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
namespace webrtc {
struct CodecInst;
template <typename T>
class AudioEncoderIsacT final : public AudioEncoder {
public:
// Allowed combinations of sample rate, frame size, and bit rate are
// - 16000 Hz, 30 ms, 10000-32000 bps
// - 16000 Hz, 60 ms, 10000-32000 bps
// - 32000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
struct Config {
bool IsOk() const;
LockedIsacBandwidthInfo* bwinfo = nullptr;
int payload_type = 103;
int sample_rate_hz = 16000;
int frame_size_ms = 30;
int bit_rate = kDefaultBitRate; // Limit on the short-term average bit
// rate, in bits/s.
int max_payload_size_bytes = -1;
int max_bit_rate = -1;
// If true, the encoder will dynamically adjust frame size and bit rate;
// the configured values are then merely the starting point.
bool adaptive_mode = false;
// In adaptive mode, prevent adaptive changes to the frame size. (Not used
// in nonadaptive mode.)
bool enforce_frame_size = false;
};
explicit AudioEncoderIsacT(const Config& config);
explicit AudioEncoderIsacT(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo);
~AudioEncoderIsacT() override;
size_t MaxEncodedBytes() const override;
int SampleRateHz() const override;
int NumChannels() const override;
size_t Num10MsFramesInNextPacket() const override;
size_t Max10MsFramesInAPacket() const override;
int GetTargetBitrate() const override;
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override;
void Reset() override;
private:
// This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
// STREAM_MAXW16_60MS for iSAC fix (60 ms).
static const size_t kSufficientEncodeBufferSizeBytes = 400;
static const int kDefaultBitRate = 32000;
// Recreate the iSAC encoder instance with the given settings, and save them.
void RecreateEncoderInstance(const Config& config);
Config config_;
typename T::instance_type* isac_state_ = nullptr;
LockedIsacBandwidthInfo* bwinfo_ = nullptr;
// Have we accepted input but not yet emitted it in a packet?
bool packet_in_progress_ = false;
// Timestamp of the first input of the currently in-progress packet.
uint32_t packet_timestamp_;
// Timestamp of the previously encoded packet.
uint32_t last_encoded_timestamp_;
RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderIsacT);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_

View File

@ -0,0 +1,190 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
#include "webrtc/base/checks.h"
namespace webrtc {
template <typename T>
typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo) {
typename AudioEncoderIsacT<T>::Config config;
config.bwinfo = bwinfo;
config.payload_type = codec_inst.pltype;
config.sample_rate_hz = codec_inst.plfreq;
config.frame_size_ms =
rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
config.adaptive_mode = (codec_inst.rate == -1);
if (codec_inst.rate != -1)
config.bit_rate = codec_inst.rate;
return config;
}
template <typename T>
bool AudioEncoderIsacT<T>::Config::IsOk() const {
if (max_bit_rate < 32000 && max_bit_rate != -1)
return false;
if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
return false;
if (adaptive_mode && !bwinfo)
return false;
switch (sample_rate_hz) {
case 16000:
if (max_bit_rate > 53400)
return false;
if (max_payload_size_bytes > 400)
return false;
return (frame_size_ms == 30 || frame_size_ms == 60) &&
(bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000));
case 32000:
if (max_bit_rate > 160000)
return false;
if (max_payload_size_bytes > 600)
return false;
return T::has_swb &&
(frame_size_ms == 30 &&
(bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000)));
default:
return false;
}
}
template <typename T>
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
RecreateEncoderInstance(config);
}
template <typename T>
AudioEncoderIsacT<T>::AudioEncoderIsacT(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo)
: AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}
template <typename T>
AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
RTC_CHECK_EQ(0, T::Free(isac_state_));
}
template <typename T>
size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
return kSufficientEncodeBufferSizeBytes;
}
template <typename T>
int AudioEncoderIsacT<T>::SampleRateHz() const {
return T::EncSampRate(isac_state_);
}
template <typename T>
int AudioEncoderIsacT<T>::NumChannels() const {
return 1;
}
template <typename T>
size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
return static_cast<size_t>(
rtc::CheckedDivExact(samples_in_next_packet,
rtc::CheckedDivExact(SampleRateHz(), 100)));
}
template <typename T>
size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
return 6; // iSAC puts at most 60 ms in a packet.
}
template <typename T>
int AudioEncoderIsacT<T>::GetTargetBitrate() const {
if (config_.adaptive_mode)
return -1;
return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
}
template <typename T>
AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal(
uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) {
if (!packet_in_progress_) {
// Starting a new packet; remember the timestamp for later.
packet_in_progress_ = true;
packet_timestamp_ = rtp_timestamp;
}
if (bwinfo_) {
IsacBandwidthInfo bwinfo = bwinfo_->Get();
T::SetBandwidthInfo(isac_state_, &bwinfo);
}
int r = T::Encode(isac_state_, audio, encoded);
RTC_CHECK_GE(r, 0) << "Encode failed (error code "
<< T::GetErrorCode(isac_state_) << ")";
// T::Encode doesn't allow us to tell it the size of the output
// buffer. All we can do is check for an overrun after the fact.
RTC_CHECK_LE(static_cast<size_t>(r), max_encoded_bytes);
if (r == 0)
return EncodedInfo();
// Got enough input to produce a packet. Return the saved timestamp from
// the first chunk of input that went into the packet.
packet_in_progress_ = false;
EncodedInfo info;
info.encoded_bytes = r;
info.encoded_timestamp = packet_timestamp_;
info.payload_type = config_.payload_type;
return info;
}
template <typename T>
void AudioEncoderIsacT<T>::Reset() {
RecreateEncoderInstance(config_);
}
template <typename T>
void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
RTC_CHECK(config.IsOk());
packet_in_progress_ = false;
bwinfo_ = config.bwinfo;
if (isac_state_)
RTC_CHECK_EQ(0, T::Free(isac_state_));
RTC_CHECK_EQ(0, T::Create(&isac_state_));
RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1));
RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
if (config.adaptive_mode) {
RTC_CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms,
config.enforce_frame_size));
} else {
RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
}
if (config.max_payload_size_bytes != -1)
RTC_CHECK_EQ(
0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
if (config.max_bit_rate != -1)
RTC_CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
// Set the decoder sample rate even though we just use the encoder. This
// doesn't appear to be necessary to produce a valid encoding, but without it
// we get an encoding that isn't bit-for-bit identical with what a combined
// encoder+decoder object produces.
RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
config_ = config;
}
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/audio_coding/codecs/isac/bandwidth_info.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
namespace webrtc {
// An IsacBandwidthInfo that's safe to access from multiple threads because
// it's protected by a mutex.
class LockedIsacBandwidthInfo final {
public:
LockedIsacBandwidthInfo();
~LockedIsacBandwidthInfo();
IsacBandwidthInfo Get() const {
CriticalSectionScoped cs(lock_.get());
return bwinfo_;
}
void Set(const IsacBandwidthInfo& bwinfo) {
CriticalSectionScoped cs(lock_.get());
bwinfo_ = bwinfo;
}
private:
const rtc::scoped_ptr<CriticalSectionWrapper> lock_;
IsacBandwidthInfo bwinfo_ GUARDED_BY(lock_);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
#include "webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
#include "webrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
namespace webrtc {
using AudioDecoderIsac = AudioDecoderIsacT<IsacFloat>;
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
#include "webrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
namespace webrtc {
using AudioEncoderIsac = AudioEncoderIsacT<IsacFloat>;
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
#include "webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h"
namespace webrtc {
// Explicit instantiation:
template class AudioDecoderIsacT<IsacFloat>;
} // namespace webrtc

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
namespace webrtc {
// Explicit instantiation:
template class AudioEncoderIsacT<IsacFloat>;
} // namespace webrtc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* bandwidth_estimator.h
*
* This header file contains the API for the Bandwidth Estimator
* designed for iSAC.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
#include "structs.h"
#include "settings.h"
#define MIN_ISAC_BW 10000
#define MIN_ISAC_BW_LB 10000
#define MIN_ISAC_BW_UB 25000
#define MAX_ISAC_BW 56000
#define MAX_ISAC_BW_UB 32000
#define MAX_ISAC_BW_LB 32000
#define MIN_ISAC_MD 5
#define MAX_ISAC_MD 25
// assumed header size, in bytes; we don't know the exact number
// (header compression may be used)
#define HEADER_SIZE 35
// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
#define INIT_FRAME_LEN_WB 60
#define INIT_FRAME_LEN_SWB 30
// Initial Bottleneck Estimate, in bits/sec, for
// Wideband & Super-wideband mode
#define INIT_BN_EST_WB 20e3f
#define INIT_BN_EST_SWB 56e3f
// Initial Header rate (header rate depends on frame-size),
// in bits/sec, for Wideband & Super-Wideband mode.
#define INIT_HDR_RATE_WB \
((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
#define INIT_HDR_RATE_SWB \
((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
// number of packets in a row for a high rate burst
#define BURST_LEN 3
// ms, max time between two full bursts
#define BURST_INTERVAL 500
// number of packets in a row for initial high rate burst
#define INIT_BURST_LEN 5
// bits/s, rate for the first BURST_LEN packets
#define INIT_RATE_WB INIT_BN_EST_WB
#define INIT_RATE_SWB INIT_BN_EST_SWB
#if defined(__cplusplus)
extern "C" {
#endif
/* This function initializes the struct */
/* to be called before using the struct for anything else */
/* returns 0 if everything went fine, -1 otherwise */
int32_t WebRtcIsac_InitBandwidthEstimator(
BwEstimatorstr* bwest_str,
enum IsacSamplingRate encoderSampRate,
enum IsacSamplingRate decoderSampRate);
/* This function updates the receiving estimate */
/* Parameters: */
/* rtp_number - value from RTP packet, from NetEq */
/* frame length - length of signal frame in ms, from iSAC decoder */
/* send_ts - value in RTP header giving send time in samples */
/* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
/* pksize - size of packet in bytes, from NetEq */
/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
/* returns 0 if everything went fine, -1 otherwise */
int16_t WebRtcIsac_UpdateBandwidthEstimator(
BwEstimatorstr* bwest_str,
const uint16_t rtp_number,
const int32_t frame_length,
const uint32_t send_ts,
const uint32_t arr_ts,
const size_t pksize);
/* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
int16_t WebRtcIsac_UpdateUplinkBwImpl(
BwEstimatorstr* bwest_str,
int16_t Index,
enum IsacSamplingRate encoderSamplingFreq);
/* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the sending iSAC payload */
void WebRtcIsac_GetDownlinkBwJitIndexImpl(
BwEstimatorstr* bwest_str,
int16_t* bottleneckIndex,
int16_t* jitterInfo,
enum IsacSamplingRate decoderSamplingFreq);
/* Returns the bandwidth estimation (in bps) */
int32_t WebRtcIsac_GetDownlinkBandwidth(
const BwEstimatorstr *bwest_str);
/* Returns the max delay (in ms) */
int32_t WebRtcIsac_GetDownlinkMaxDelay(
const BwEstimatorstr *bwest_str);
/* Returns the bandwidth that iSAC should send with in bps */
int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str);
/* Returns the max delay value from the other side in ms */
int32_t WebRtcIsac_GetUplinkMaxDelay(
const BwEstimatorstr *bwest_str);
/* Fills in an IsacExternalBandwidthInfo struct. */
void WebRtcIsacBw_GetBandwidthInfo(
BwEstimatorstr* bwest_str,
enum IsacSamplingRate decoder_sample_rate_hz,
IsacBandwidthInfo* bwinfo);
/* Uses the values from an IsacExternalBandwidthInfo struct. */
void WebRtcIsacBw_SetBandwidthInfo(BwEstimatorstr* bwest_str,
const IsacBandwidthInfo* bwinfo);
/*
* update amount of data in bottle neck buffer and burst handling
* returns minimum payload size (bytes)
*/
int WebRtcIsac_GetMinBytes(
RateModel* State,
int StreamSize, /* bytes in bitstream */
const int FrameLen, /* ms per frame */
const double BottleNeck, /* bottle neck rate; excl headers (bps) */
const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
enum ISACBandwidth bandwidth
/*,int16_t frequentLargePackets*/);
/*
* update long-term average bitrate and amount of data in buffer
*/
void WebRtcIsac_UpdateRateModel(
RateModel* State,
int StreamSize, /* bytes in bitstream */
const int FrameSamples, /* samples per frame */
const double BottleNeck); /* bottle neck rate; excl headers (bps) */
void WebRtcIsac_InitRateModel(
RateModel *State);
/* Returns the new framelength value (input argument: bottle_neck) */
int WebRtcIsac_GetNewFrameLength(
double bottle_neck,
int current_framelength);
/* Returns the new SNR value (input argument: bottle_neck) */
double WebRtcIsac_GetSnr(
double bottle_neck,
int new_framelength);
int16_t WebRtcIsac_UpdateUplinkJitter(
BwEstimatorstr* bwest_str,
int32_t index);
#if defined(__cplusplus)
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ */

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "crc.h"
#include <stdlib.h>
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#define POLYNOMIAL 0x04c11db7L
static const uint32_t kCrcTable[256] = {
0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4,
0x808d07d, 0xcc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
/****************************************************************************
* WebRtcIsac_GetCrc(...)
*
* This function returns a 32 bit CRC checksum of a bit stream
*
* Input:
* - bitstream : payload bitstream
* - len_bitstream_in_bytes : number of 8-bit words in the bit stream
*
* Output:
* - crc : checksum
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcIsac_GetCrc(const int16_t* bitstream,
int len_bitstream_in_bytes,
uint32_t* crc)
{
uint8_t* bitstream_ptr_uw8;
uint32_t crc_state;
int byte_cntr;
int crc_tbl_indx;
/* Sanity Check. */
if (bitstream == NULL) {
return -1;
}
/* cast to UWord8 pointer */
bitstream_ptr_uw8 = (uint8_t *)bitstream;
/* initialize */
crc_state = 0xFFFFFFFF;
for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
bitstream_ptr_uw8[byte_cntr]) & 0xFF;
crc_state = (crc_state << 8) ^ kCrcTable[crc_tbl_indx];
}
*crc = ~crc_state;
return 0;
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* crc.h
*
* Checksum functions
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
#include "webrtc/typedefs.h"
/****************************************************************************
* WebRtcIsac_GetCrc(...)
*
* This function returns a 32 bit CRC checksum of a bit stream
*
* Input:
* - encoded : payload bit stream
* - no_of_word8s : number of 8-bit words in the bit stream
*
* Output:
* - crc : checksum
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcIsac_GetCrc(
const int16_t* encoded,
int no_of_word8s,
uint32_t* crc);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */

View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* decode_B.c
*
* This file contains definition of funtions for decoding.
* Decoding of lower-band, including normal-decoding and RCU decoding.
* Decoding of upper-band, including 8-12 kHz, when the bandwidth is
* 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
*
*/
#include "codec.h"
#include "entropy_coding.h"
#include "pitch_estimator.h"
#include "bandwidth_estimator.h"
#include "structs.h"
#include "settings.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* function to decode the bitstream
* returns the total number of bytes in the stream
*/
int WebRtcIsac_DecodeLb(const TransformTables* transform_tables,
float* signal_out, ISACLBDecStruct* ISACdecLB_obj,
int16_t* current_framesamples,
int16_t isRCUPayload) {
int k;
int len, err;
int16_t bandwidthInd;
float LP_dec_float[FRAMESAMPLES_HALF];
float HP_dec_float[FRAMESAMPLES_HALF];
double LPw[FRAMESAMPLES_HALF];
double HPw[FRAMESAMPLES_HALF];
double LPw_pf[FRAMESAMPLES_HALF];
double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES];
double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
double PitchLags[4];
double PitchGains[4];
double AvgPitchGain;
int16_t PitchGains_Q12[4];
int16_t AvgPitchGain_Q12;
float gain;
int frame_nb; /* counter */
int frame_mode; /* 0 30ms, 1 for 60ms */
/* Processed_samples: 480 (30, 60 ms). Cannot take other values. */
WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj));
len = 0;
/* Decode framelength and BW estimation - not used,
only for stream pointer*/
err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
current_framesamples);
if (err < 0) {
return err;
}
/* Frame_mode:
* 0: indicates 30 ms frame (480 samples)
* 1: indicates 60 ms frame (960 samples) */
frame_mode = *current_framesamples / MAX_FRAMESAMPLES;
err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
if (err < 0) {
return err;
}
/* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames
bundled together (60ms). */
for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
/* Decode & de-quantize pitch parameters */
err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj,
PitchGains_Q12);
if (err < 0) {
return err;
}
err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12,
PitchLags);
if (err < 0) {
return err;
}
AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
/* Decode & de-quantize filter coefficients. */
err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef,
hi_filt_coef);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12,
kIsacLowerBand, real_f, imag_f);
if (len < 0) {
return len;
}
/* Inverse transform. */
WebRtcIsac_Spec2time(transform_tables, real_f, imag_f, LPw, HPw,
&ISACdecLB_obj->fftstr_obj);
/* Convert PitchGains back to float for pitchfilter_post */
for (k = 0; k < 4; k++) {
PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
}
if (isRCUPayload) {
for (k = 0; k < 240; k++) {
LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
}
}
/* Inverse pitch filter. */
WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj,
PitchLags, PitchGains);
/* Convert AvgPitchGain back to float for computation of gain. */
AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096;
gain = 1.0f - 0.45f * (float)AvgPitchGain;
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
/* Reduce gain to compensate for pitch enhancer. */
LPw_pf[k] *= gain;
}
if (isRCUPayload) {
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
/* Compensation for transcoding gain changes. */
LPw_pf[k] *= RCU_TRANSCODING_SCALE;
HPw[k] *= RCU_TRANSCODING_SCALE;
}
}
/* Perceptual post-filtering (using normalized lattice filter). */
WebRtcIsac_NormLatticeFilterAr(
ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef,
LP_dec_float);
WebRtcIsac_NormLatticeFilterAr(
ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
(ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef,
HP_dec_float);
/* Recombine the 2 bands. */
WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float,
signal_out + frame_nb * FRAMESAMPLES,
&ISACdecLB_obj->postfiltbankstr_obj);
}
return len;
}
/*
* This decode function is called when the codec is operating in 16 kHz
* bandwidth to decode the upperband, i.e. 8-16 kHz.
*
* Contrary to lower-band, the upper-band (8-16 kHz) is not split in
* frequency, but split to 12 sub-frames, i.e. twice as lower-band.
*/
int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables,
float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
int16_t isRCUPayload) {
int len, err;
double halfFrameFirst[FRAMESAMPLES_HALF];
double halfFrameSecond[FRAMESAMPLES_HALF];
double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) +
(UB_LPC_ORDER + 1)];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
len = 0;
/* Decode & de-quantize filter coefficients. */
memset(percepFilterParam, 0, sizeof(percepFilterParam));
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
percepFilterParam, isac16kHz);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
kIsacUpperBand16, real_f, imag_f);
if (len < 0) {
return len;
}
if (isRCUPayload) {
int n;
for (n = 0; n < 240; n++) {
real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
}
}
/* Inverse transform. */
WebRtcIsac_Spec2time(transform_tables,
real_f, imag_f, halfFrameFirst, halfFrameSecond,
&ISACdecUB_obj->fftstr_obj);
/* Perceptual post-filtering (using normalized lattice filter). */
WebRtcIsac_NormLatticeFilterAr(
UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
&percepFilterParam[(UB_LPC_ORDER + 1)], signal_out);
WebRtcIsac_NormLatticeFilterAr(
UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
&percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)],
&signal_out[FRAMESAMPLES_HALF]);
return len;
}
/*
* This decode function is called when the codec operates at 0-12 kHz
* bandwidth to decode the upperband, i.e. 8-12 kHz.
*
* At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
* kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
* reconstructed and 12-16 kHz replaced with zeros. Then two bands
* are combined, to reconstruct the upperband 8-16 kHz.
*/
int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables,
float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
int16_t isRCUPayload) {
int len, err;
float LP_dec_float[FRAMESAMPLES_HALF];
float HP_dec_float[FRAMESAMPLES_HALF];
double LPw[FRAMESAMPLES_HALF];
double HPw[FRAMESAMPLES_HALF];
double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
len = 0;
/* Decode & dequantize filter coefficients. */
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
percepFilterParam, isac12kHz);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
kIsacUpperBand12, real_f, imag_f);
if (len < 0) {
return len;
}
if (isRCUPayload) {
int n;
for (n = 0; n < 240; n++) {
real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
}
}
/* Inverse transform. */
WebRtcIsac_Spec2time(transform_tables,
real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj);
/* perceptual post-filtering (using normalized lattice filter) */
WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG,
LPw, percepFilterParam, LP_dec_float);
/* Zero for 12-16 kHz. */
memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
/* Recombine the 2 bands. */
WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
&ISACdecUB_obj->postfiltbankstr_obj);
return len;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "structs.h"
#include "bandwidth_estimator.h"
#include "entropy_coding.h"
#include "codec.h"
int
WebRtcIsac_EstimateBandwidth(
BwEstimatorstr* bwest_str,
Bitstr* streamdata,
size_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts,
enum IsacSamplingRate encoderSampRate,
enum IsacSamplingRate decoderSampRate)
{
int16_t index;
int16_t frame_samples;
uint32_t sendTimestampIn16kHz;
uint32_t arrivalTimestampIn16kHz;
uint32_t diffSendTime;
uint32_t diffArrivalTime;
int err;
/* decode framelength and BW estimation */
err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
if(err < 0) // error check
{
return err;
}
err = WebRtcIsac_DecodeSendBW(streamdata, &index);
if(err < 0) // error check
{
return err;
}
/* UPDATE ESTIMATES FROM OTHER SIDE */
err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
if(err < 0)
{
return err;
}
// We like BWE to work at 16 kHz sampling rate,
// therefore, we have to change the timestamps accordingly.
// translate the send timestamp if required
diffSendTime = (uint32_t)((uint32_t)send_ts -
(uint32_t)bwest_str->senderTimestamp);
bwest_str->senderTimestamp = send_ts;
diffArrivalTime = (uint32_t)((uint32_t)arr_ts -
(uint32_t)bwest_str->receiverTimestamp);
bwest_str->receiverTimestamp = arr_ts;
if(decoderSampRate == kIsacSuperWideband)
{
diffArrivalTime = (uint32_t)diffArrivalTime >> 1;
diffSendTime = (uint32_t)diffSendTime >> 1;
}
// arrival timestamp in 16 kHz
arrivalTimestampIn16kHz = (uint32_t)((uint32_t)
bwest_str->prev_rec_arr_ts + (uint32_t)diffArrivalTime);
// send timestamp in 16 kHz
sendTimestampIn16kHz = (uint32_t)((uint32_t)
bwest_str->prev_rec_send_ts + (uint32_t)diffSendTime);
err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
(frame_samples * 1000) / FS, sendTimestampIn16kHz,
arrivalTimestampIn16kHz, packet_size);
// error check
if(err < 0)
{
return err;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,943 @@
/*
* Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
* Queen's Univ at Kingston (Canada)
*
* Permission to use, copy, modify, and distribute this software for
* any purpose without fee is hereby granted, provided that this
* entire notice is included in all copies of any software which is
* or includes a copy or modification of this software and in all
* copies of the supporting documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
* UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
* KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* All of which is to say that you can do what you like with this
* source code provided you don't try to sell it as your own and you
* include an unaltered copy of this message (including the
* copyright).
*
* It is also implicitly understood that bug fixes and improvements
* should make their way back to the general Internet community so
* that everyone benefits.
*
* Changes:
* Trivial type modifications by the WebRTC authors.
*/
/*
* File:
* WebRtcIsac_Fftn.c
*
* Public:
* WebRtcIsac_Fftn / fftnf ();
*
* Private:
* WebRtcIsac_Fftradix / fftradixf ();
*
* Descript:
* multivariate complex Fourier transform, computed in place
* using mixed-radix Fast Fourier Transform algorithm.
*
* Fortran code by:
* RC Singleton, Stanford Research Institute, Sept. 1968
*
* translated by f2c (version 19950721).
*
* int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[],
* int iSign, double scaling);
*
* NDIM = the total number dimensions
* DIMS = a vector of array sizes
* if NDIM is zero then DIMS must be zero-terminated
*
* RE and IM hold the real and imaginary components of the data, and return
* the resulting real and imaginary Fourier coefficients. Multidimensional
* data *must* be allocated contiguously. There is no limit on the number
* of dimensions.
*
* ISIGN = the sign of the complex exponential (ie, forward or inverse FFT)
* the magnitude of ISIGN (normally 1) is used to determine the
* correct indexing increment (see below).
*
* SCALING = normalizing constant by which the final result is *divided*
* if SCALING == -1, normalize by total dimension of the transform
* if SCALING < -1, normalize by the square-root of the total dimension
*
* example:
* tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
*
* int dims[3] = {n1,n2,n3}
* WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling);
*
*-----------------------------------------------------------------------*
* int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass,
* size_t nSpan, int iSign, size_t max_factors,
* size_t max_perm);
*
* RE, IM - see above documentation
*
* Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must
* be called once for each dimension, but the calls may be in any order.
*
* NTOTAL = the total number of complex data values
* NPASS = the dimension of the current variable
* NSPAN/NPASS = the spacing of consecutive data values while indexing the
* current variable
* ISIGN - see above documentation
*
* example:
* tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
*
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1, n1, 1, maxf, maxp);
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2, n1*n2, 1, maxf, maxp);
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp);
*
* single-variate transform,
* NTOTAL = N = NSPAN = (number of complex data values),
*
* WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp);
*
* The data can also be stored in a single array with alternating real and
* imaginary parts, the magnitude of ISIGN is changed to 2 to give correct
* indexing increment, and data [0] and data [1] used to pass the initial
* addresses for the sequences of real and imaginary values,
*
* example:
* REAL data [2*NTOTAL];
* WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp);
*
* for temporary allocation:
*
* MAX_FACTORS >= the maximum prime factor of NPASS
* MAX_PERM >= the number of prime factors of NPASS. In addition,
* if the square-free portion K of NPASS has two or more prime
* factors, then MAX_PERM >= (K-1)
*
* storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS
* has more than one square-free factor, the product of the square-free
* factors must be <= 210 array storage for maximum prime factor of 23 the
* following two constants should agree with the array dimensions.
*
*----------------------------------------------------------------------*/
#include "fft.h"
#include <stdlib.h>
#include <math.h>
/* double precision routine */
static int
WebRtcIsac_Fftradix (double Re[], double Im[],
size_t nTotal, size_t nPass, size_t nSpan, int isign,
int max_factors, unsigned int max_perm,
FFTstr *fftstate);
#ifndef M_PI
# define M_PI 3.14159265358979323846264338327950288
#endif
#ifndef SIN60
# define SIN60 0.86602540378443865 /* sin(60 deg) */
# define COS72 0.30901699437494742 /* cos(72 deg) */
# define SIN72 0.95105651629515357 /* sin(72 deg) */
#endif
# define REAL double
# define FFTN WebRtcIsac_Fftn
# define FFTNS "fftn"
# define FFTRADIX WebRtcIsac_Fftradix
# define FFTRADIXS "fftradix"
int WebRtcIsac_Fftns(unsigned int ndim, const int dims[],
double Re[],
double Im[],
int iSign,
double scaling,
FFTstr *fftstate)
{
size_t nSpan, nPass, nTotal;
unsigned int i;
int ret, max_factors, max_perm;
/*
* tally the number of elements in the data array
* and determine the number of dimensions
*/
nTotal = 1;
if (ndim && dims [0])
{
for (i = 0; i < ndim; i++)
{
if (dims [i] <= 0)
{
return -1;
}
nTotal *= dims [i];
}
}
else
{
ndim = 0;
for (i = 0; dims [i]; i++)
{
if (dims [i] <= 0)
{
return -1;
}
nTotal *= dims [i];
ndim++;
}
}
/* determine maximum number of factors and permuations */
#if 1
/*
* follow John Beale's example, just use the largest dimension and don't
* worry about excess allocation. May be someone else will do it?
*/
max_factors = max_perm = 1;
for (i = 0; i < ndim; i++)
{
nSpan = dims [i];
if ((int)nSpan > max_factors)
{
max_factors = (int)nSpan;
}
if ((int)nSpan > max_perm)
{
max_perm = (int)nSpan;
}
}
#else
/* use the constants used in the original Fortran code */
max_factors = 23;
max_perm = 209;
#endif
/* loop over the dimensions: */
nPass = 1;
for (i = 0; i < ndim; i++)
{
nSpan = dims [i];
nPass *= nSpan;
ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign,
max_factors, max_perm, fftstate);
/* exit, clean-up already done */
if (ret)
return ret;
}
/* Divide through by the normalizing constant: */
if (scaling && scaling != 1.0)
{
if (iSign < 0) iSign = -iSign;
if (scaling < 0.0)
{
scaling = (double)nTotal;
if (scaling < -1.0)
scaling = sqrt (scaling);
}
scaling = 1.0 / scaling; /* multiply is often faster */
for (i = 0; i < nTotal; i += iSign)
{
Re [i] *= scaling;
Im [i] *= scaling;
}
}
return 0;
}
/*
* singleton's mixed radix routine
*
* could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's
* possible to make this a standalone function
*/
static int FFTRADIX (REAL Re[],
REAL Im[],
size_t nTotal,
size_t nPass,
size_t nSpan,
int iSign,
int max_factors,
unsigned int max_perm,
FFTstr *fftstate)
{
int ii, mfactor, kspan, ispan, inc;
int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt;
REAL radf;
REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp;
REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp;
REAL *Rtmp = NULL; /* temp space for real part*/
REAL *Itmp = NULL; /* temp space for imaginary part */
REAL *Cos = NULL; /* Cosine values */
REAL *Sin = NULL; /* Sine values */
REAL s60 = SIN60; /* sin(60 deg) */
REAL c72 = COS72; /* cos(72 deg) */
REAL s72 = SIN72; /* sin(72 deg) */
REAL pi2 = M_PI; /* use PI first, 2 PI later */
fftstate->SpaceAlloced = 0;
fftstate->MaxPermAlloced = 0;
// initialize to avoid warnings
k3 = c2 = c3 = s2 = s3 = 0.0;
if (nPass < 2)
return 0;
/* allocate storage */
if (fftstate->SpaceAlloced < max_factors * sizeof (REAL))
{
#ifdef SUN_BROKEN_REALLOC
if (!fftstate->SpaceAlloced) /* first time */
{
fftstate->SpaceAlloced = max_factors * sizeof (REAL);
}
else
{
#endif
fftstate->SpaceAlloced = max_factors * sizeof (REAL);
#ifdef SUN_BROKEN_REALLOC
}
#endif
}
else
{
/* allow full use of alloc'd space */
max_factors = fftstate->SpaceAlloced / sizeof (REAL);
}
if (fftstate->MaxPermAlloced < max_perm)
{
#ifdef SUN_BROKEN_REALLOC
if (!fftstate->MaxPermAlloced) /* first time */
else
#endif
fftstate->MaxPermAlloced = max_perm;
}
else
{
/* allow full use of alloc'd space */
max_perm = fftstate->MaxPermAlloced;
}
/* assign pointers */
Rtmp = (REAL *) fftstate->Tmp0;
Itmp = (REAL *) fftstate->Tmp1;
Cos = (REAL *) fftstate->Tmp2;
Sin = (REAL *) fftstate->Tmp3;
/*
* Function Body
*/
inc = iSign;
if (iSign < 0) {
s72 = -s72;
s60 = -s60;
pi2 = -pi2;
inc = -inc; /* absolute value */
}
/* adjust for strange increments */
nt = inc * (int)nTotal;
ns = inc * (int)nSpan;
kspan = ns;
nn = nt - inc;
jc = ns / (int)nPass;
radf = pi2 * (double) jc;
pi2 *= 2.0; /* use 2 PI from here on */
ii = 0;
jf = 0;
/* determine the factors of n */
mfactor = 0;
k = (int)nPass;
while (k % 16 == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = 4;
k /= 16;
}
j = 3;
jj = 9;
do {
while (k % jj == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = j;
k /= jj;
}
j += 2;
jj = j * j;
} while (jj <= k);
if (k <= 4) {
kt = mfactor;
fftstate->factor [mfactor] = k;
if (k != 1)
mfactor++;
} else {
if (k - (k / 4 << 2) == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = 2;
k /= 4;
}
kt = mfactor;
j = 2;
do {
if (k % j == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = j;
k /= j;
}
j = ((j + 1) / 2 << 1) + 1;
} while (j <= k);
}
if (kt) {
j = kt;
do {
mfactor++;
fftstate->factor [mfactor - 1] = fftstate->factor [j - 1];
j--;
} while (j);
}
/* test that mfactors is in range */
if (mfactor > NFACTOR)
{
return -1;
}
/* compute fourier transform */
for (;;) {
sd = radf / (double) kspan;
cd = sin(sd);
cd = 2.0 * cd * cd;
sd = sin(sd + sd);
kk = 0;
ii++;
switch (fftstate->factor [ii - 1]) {
case 2:
/* transform for factor of 2 (including rotation factor) */
kspan /= 2;
k1 = kspan + 2;
do {
do {
k2 = kk + kspan;
ak = Re [k2];
bk = Im [k2];
Re [k2] = Re [kk] - ak;
Im [k2] = Im [kk] - bk;
Re [kk] += ak;
Im [kk] += bk;
kk = k2 + kspan;
} while (kk < nn);
kk -= nn;
} while (kk < jc);
if (kk >= kspan)
goto Permute_Results_Label; /* exit infinite loop */
do {
c1 = 1.0 - cd;
s1 = sd;
do {
do {
do {
k2 = kk + kspan;
ak = Re [kk] - Re [k2];
bk = Im [kk] - Im [k2];
Re [kk] += Re [k2];
Im [kk] += Im [k2];
Re [k2] = c1 * ak - s1 * bk;
Im [k2] = s1 * ak + c1 * bk;
kk = k2 + kspan;
} while (kk < (nt-1));
k2 = kk - nt;
c1 = -c1;
kk = k1 - k2;
} while (kk > k2);
ak = c1 - (cd * c1 + sd * s1);
s1 = sd * c1 - cd * s1 + s1;
c1 = 2.0 - (ak * ak + s1 * s1);
s1 *= c1;
c1 *= ak;
kk += jc;
} while (kk < k2);
k1 += inc + inc;
kk = (k1 - kspan + 1) / 2 + jc - 1;
} while (kk < (jc + jc));
break;
case 4: /* transform for factor of 4 */
ispan = kspan;
kspan /= 4;
do {
c1 = 1.0;
s1 = 0.0;
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
k3 = k2 + kspan;
akp = Re [kk] + Re [k2];
akm = Re [kk] - Re [k2];
ajp = Re [k1] + Re [k3];
ajm = Re [k1] - Re [k3];
bkp = Im [kk] + Im [k2];
bkm = Im [kk] - Im [k2];
bjp = Im [k1] + Im [k3];
bjm = Im [k1] - Im [k3];
Re [kk] = akp + ajp;
Im [kk] = bkp + bjp;
ajp = akp - ajp;
bjp = bkp - bjp;
if (iSign < 0) {
akp = akm + bjm;
bkp = bkm - ajm;
akm -= bjm;
bkm += ajm;
} else {
akp = akm - bjm;
bkp = bkm + ajm;
akm += bjm;
bkm -= ajm;
}
/* avoid useless multiplies */
if (s1 == 0.0) {
Re [k1] = akp;
Re [k2] = ajp;
Re [k3] = akm;
Im [k1] = bkp;
Im [k2] = bjp;
Im [k3] = bkm;
} else {
Re [k1] = akp * c1 - bkp * s1;
Re [k2] = ajp * c2 - bjp * s2;
Re [k3] = akm * c3 - bkm * s3;
Im [k1] = akp * s1 + bkp * c1;
Im [k2] = ajp * s2 + bjp * c2;
Im [k3] = akm * s3 + bkm * c3;
}
kk = k3 + kspan;
} while (kk < nt);
c2 = c1 - (cd * c1 + sd * s1);
s1 = sd * c1 - cd * s1 + s1;
c1 = 2.0 - (c2 * c2 + s1 * s1);
s1 *= c1;
c1 *= c2;
/* values of c2, c3, s2, s3 that will get used next time */
c2 = c1 * c1 - s1 * s1;
s2 = 2.0 * c1 * s1;
c3 = c2 * c1 - s2 * s1;
s3 = c2 * s1 + s2 * c1;
kk = kk - nt + jc;
} while (kk < kspan);
kk = kk - kspan + inc;
} while (kk < jc);
if (kspan == jc)
goto Permute_Results_Label; /* exit infinite loop */
break;
default:
/* transform for odd factors */
#ifdef FFT_RADIX4
return -1;
break;
#else /* FFT_RADIX4 */
k = fftstate->factor [ii - 1];
ispan = kspan;
kspan /= k;
switch (k) {
case 3: /* transform for factor of 3 (optional code) */
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
ak = Re [kk];
bk = Im [kk];
aj = Re [k1] + Re [k2];
bj = Im [k1] + Im [k2];
Re [kk] = ak + aj;
Im [kk] = bk + bj;
ak -= 0.5 * aj;
bk -= 0.5 * bj;
aj = (Re [k1] - Re [k2]) * s60;
bj = (Im [k1] - Im [k2]) * s60;
Re [k1] = ak - bj;
Re [k2] = ak + bj;
Im [k1] = bk + aj;
Im [k2] = bk - aj;
kk = k2 + kspan;
} while (kk < (nn - 1));
kk -= nn;
} while (kk < kspan);
break;
case 5: /* transform for factor of 5 (optional code) */
c2 = c72 * c72 - s72 * s72;
s2 = 2.0 * c72 * s72;
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
k3 = k2 + kspan;
k4 = k3 + kspan;
akp = Re [k1] + Re [k4];
akm = Re [k1] - Re [k4];
bkp = Im [k1] + Im [k4];
bkm = Im [k1] - Im [k4];
ajp = Re [k2] + Re [k3];
ajm = Re [k2] - Re [k3];
bjp = Im [k2] + Im [k3];
bjm = Im [k2] - Im [k3];
aa = Re [kk];
bb = Im [kk];
Re [kk] = aa + akp + ajp;
Im [kk] = bb + bkp + bjp;
ak = akp * c72 + ajp * c2 + aa;
bk = bkp * c72 + bjp * c2 + bb;
aj = akm * s72 + ajm * s2;
bj = bkm * s72 + bjm * s2;
Re [k1] = ak - bj;
Re [k4] = ak + bj;
Im [k1] = bk + aj;
Im [k4] = bk - aj;
ak = akp * c2 + ajp * c72 + aa;
bk = bkp * c2 + bjp * c72 + bb;
aj = akm * s2 - ajm * s72;
bj = bkm * s2 - bjm * s72;
Re [k2] = ak - bj;
Re [k3] = ak + bj;
Im [k2] = bk + aj;
Im [k3] = bk - aj;
kk = k4 + kspan;
} while (kk < (nn-1));
kk -= nn;
} while (kk < kspan);
break;
default:
if (k != jf) {
jf = k;
s1 = pi2 / (double) k;
c1 = cos(s1);
s1 = sin(s1);
if (jf > max_factors){
return -1;
}
Cos [jf - 1] = 1.0;
Sin [jf - 1] = 0.0;
j = 1;
do {
Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1;
Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1;
k--;
Cos [k - 1] = Cos [j - 1];
Sin [k - 1] = -Sin [j - 1];
j++;
} while (j < k);
}
do {
do {
k1 = kk;
k2 = kk + ispan;
ak = aa = Re [kk];
bk = bb = Im [kk];
j = 1;
k1 += kspan;
do {
k2 -= kspan;
j++;
Rtmp [j - 1] = Re [k1] + Re [k2];
ak += Rtmp [j - 1];
Itmp [j - 1] = Im [k1] + Im [k2];
bk += Itmp [j - 1];
j++;
Rtmp [j - 1] = Re [k1] - Re [k2];
Itmp [j - 1] = Im [k1] - Im [k2];
k1 += kspan;
} while (k1 < k2);
Re [kk] = ak;
Im [kk] = bk;
k1 = kk;
k2 = kk + ispan;
j = 1;
do {
k1 += kspan;
k2 -= kspan;
jj = j;
ak = aa;
bk = bb;
aj = 0.0;
bj = 0.0;
k = 1;
do {
k++;
ak += Rtmp [k - 1] * Cos [jj - 1];
bk += Itmp [k - 1] * Cos [jj - 1];
k++;
aj += Rtmp [k - 1] * Sin [jj - 1];
bj += Itmp [k - 1] * Sin [jj - 1];
jj += j;
if (jj > jf) {
jj -= jf;
}
} while (k < jf);
k = jf - j;
Re [k1] = ak - bj;
Im [k1] = bk + aj;
Re [k2] = ak + bj;
Im [k2] = bk - aj;
j++;
} while (j < k);
kk += ispan;
} while (kk < nn);
kk -= nn;
} while (kk < kspan);
break;
}
/* multiply by rotation factor (except for factors of 2 and 4) */
if (ii == mfactor)
goto Permute_Results_Label; /* exit infinite loop */
kk = jc;
do {
c2 = 1.0 - cd;
s1 = sd;
do {
c1 = c2;
s2 = s1;
kk += kspan;
do {
do {
ak = Re [kk];
Re [kk] = c2 * ak - s2 * Im [kk];
Im [kk] = s2 * ak + c2 * Im [kk];
kk += ispan;
} while (kk < nt);
ak = s1 * s2;
s2 = s1 * c2 + c1 * s2;
c2 = c1 * c2 - ak;
kk = kk - nt + kspan;
} while (kk < ispan);
c2 = c1 - (cd * c1 + sd * s1);
s1 += sd * c1 - cd * s1;
c1 = 2.0 - (c2 * c2 + s1 * s1);
s1 *= c1;
c2 *= c1;
kk = kk - ispan + jc;
} while (kk < kspan);
kk = kk - kspan + jc + inc;
} while (kk < (jc + jc));
break;
#endif /* FFT_RADIX4 */
}
}
/* permute the results to normal order---done in two stages */
/* permutation for square factors of n */
Permute_Results_Label:
fftstate->Perm [0] = ns;
if (kt) {
k = kt + kt + 1;
if (mfactor < k)
k--;
j = 1;
fftstate->Perm [k] = jc;
do {
fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1];
fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1];
j++;
k--;
} while (j < k);
k3 = fftstate->Perm [k];
kspan = fftstate->Perm [1];
kk = jc;
k2 = kspan;
j = 1;
if (nPass != nTotal) {
/* permutation for multivariate transform */
Permute_Multi_Label:
do {
do {
k = kk + jc;
do {
/* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
kk += inc;
k2 += inc;
} while (kk < (k-1));
kk += ns - jc;
k2 += ns - jc;
} while (kk < (nt-1));
k2 = k2 - nt + kspan;
kk = kk - nt + jc;
} while (k2 < (ns-1));
do {
do {
k2 -= fftstate->Perm [j - 1];
j++;
k2 = fftstate->Perm [j] + k2;
} while (k2 > fftstate->Perm [j - 1]);
j = 1;
do {
if (kk < (k2-1))
goto Permute_Multi_Label;
kk += jc;
k2 += kspan;
} while (k2 < (ns-1));
} while (kk < (ns-1));
} else {
/* permutation for single-variate transform (optional code) */
Permute_Single_Label:
do {
/* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
kk += inc;
k2 += kspan;
} while (k2 < (ns-1));
do {
do {
k2 -= fftstate->Perm [j - 1];
j++;
k2 = fftstate->Perm [j] + k2;
} while (k2 >= fftstate->Perm [j - 1]);
j = 1;
do {
if (kk < k2)
goto Permute_Single_Label;
kk += inc;
k2 += kspan;
} while (k2 < (ns-1));
} while (kk < (ns-1));
}
jc = k3;
}
if ((kt << 1) + 1 >= mfactor)
return 0;
ispan = fftstate->Perm [kt];
/* permutation for square-free factors of n */
j = mfactor - kt;
fftstate->factor [j] = 1;
do {
fftstate->factor [j - 1] *= fftstate->factor [j];
j--;
} while (j != kt);
kt++;
nn = fftstate->factor [kt - 1] - 1;
if (nn > (int) max_perm) {
return -1;
}
j = jj = 0;
for (;;) {
k = kt + 1;
k2 = fftstate->factor [kt - 1];
kk = fftstate->factor [k - 1];
j++;
if (j > nn)
break; /* exit infinite loop */
jj += kk;
while (jj >= k2) {
jj -= k2;
k2 = kk;
k++;
kk = fftstate->factor [k - 1];
jj += kk;
}
fftstate->Perm [j - 1] = jj;
}
/* determine the permutation cycles of length greater than 1 */
j = 0;
for (;;) {
do {
j++;
kk = fftstate->Perm [j - 1];
} while (kk < 0);
if (kk != j) {
do {
k = kk;
kk = fftstate->Perm [k - 1];
fftstate->Perm [k - 1] = -kk;
} while (kk != j);
k3 = kk;
} else {
fftstate->Perm [j - 1] = -j;
if (j == nn)
break; /* exit infinite loop */
}
}
max_factors *= inc;
/* reorder a and b, following the permutation cycles */
for (;;) {
j = k3 + 1;
nt -= ispan;
ii = nt - inc + 1;
if (nt < 0)
break; /* exit infinite loop */
do {
do {
j--;
} while (fftstate->Perm [j - 1] < 0);
jj = jc;
do {
kspan = jj;
if (jj > max_factors) {
kspan = max_factors;
}
jj -= kspan;
k = fftstate->Perm [j - 1];
kk = jc * k + ii + jj;
k1 = kk + kspan - 1;
k2 = 0;
do {
k2++;
Rtmp [k2 - 1] = Re [k1];
Itmp [k2 - 1] = Im [k1];
k1 -= inc;
} while (k1 != (kk-1));
do {
k1 = kk + kspan - 1;
k2 = k1 - jc * (k + fftstate->Perm [k - 1]);
k = -fftstate->Perm [k - 1];
do {
Re [k1] = Re [k2];
Im [k1] = Im [k2];
k1 -= inc;
k2 -= inc;
} while (k1 != (kk-1));
kk = k2 + 1;
} while (k != j);
k1 = kk + kspan - 1;
k2 = 0;
do {
k2++;
Re [k1] = Rtmp [k2 - 1];
Im [k1] = Itmp [k2 - 1];
k1 -= inc;
} while (k1 != (kk-1));
} while (jj);
} while (j != 1);
}
return 0; /* exit point here */
}
/* ---------------------- end-of-file (c source) ---------------------- */

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*--------------------------------*-C-*---------------------------------*
* File:
* fftn.h
* ---------------------------------------------------------------------*
* Re[]: real value array
* Im[]: imaginary value array
* nTotal: total number of complex values
* nPass: number of elements involved in this pass of transform
* nSpan: nspan/nPass = number of bytes to increment pointer
* in Re[] and Im[]
* isign: exponent: +1 = forward -1 = reverse
* scaling: normalizing constant by which the final result is *divided*
* scaling == -1, normalize by total dimension of the transform
* scaling < -1, normalize by the square-root of the total dimension
*
* ----------------------------------------------------------------------
* See the comments in the code for correct usage!
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
#include "structs.h"
/* double precision routine */
int WebRtcIsac_Fftns (unsigned int ndim, const int dims[], double Re[], double Im[],
int isign, double scaling, FFTstr *fftstate);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
#include "webrtc/modules/audio_coding/codecs/isac/main/include/isac.h"
namespace webrtc {
struct IsacFloat {
using instance_type = ISACStruct;
static const bool has_swb = true;
static inline int16_t Control(instance_type* inst,
int32_t rate,
int framesize) {
return WebRtcIsac_Control(inst, rate, framesize);
}
static inline int16_t ControlBwe(instance_type* inst,
int32_t rate_bps,
int frame_size_ms,
int16_t enforce_frame_size) {
return WebRtcIsac_ControlBwe(inst, rate_bps, frame_size_ms,
enforce_frame_size);
}
static inline int16_t Create(instance_type** inst) {
return WebRtcIsac_Create(inst);
}
static inline int DecodeInternal(instance_type* inst,
const uint8_t* encoded,
size_t len,
int16_t* decoded,
int16_t* speech_type) {
return WebRtcIsac_Decode(inst, encoded, len, decoded, speech_type);
}
static inline size_t DecodePlc(instance_type* inst,
int16_t* decoded,
size_t num_lost_frames) {
return WebRtcIsac_DecodePlc(inst, decoded, num_lost_frames);
}
static inline void DecoderInit(instance_type* inst) {
WebRtcIsac_DecoderInit(inst);
}
static inline int Encode(instance_type* inst,
const int16_t* speech_in,
uint8_t* encoded) {
return WebRtcIsac_Encode(inst, speech_in, encoded);
}
static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
return WebRtcIsac_EncoderInit(inst, coding_mode);
}
static inline uint16_t EncSampRate(instance_type* inst) {
return WebRtcIsac_EncSampRate(inst);
}
static inline int16_t Free(instance_type* inst) {
return WebRtcIsac_Free(inst);
}
static inline void GetBandwidthInfo(instance_type* inst,
IsacBandwidthInfo* bwinfo) {
WebRtcIsac_GetBandwidthInfo(inst, bwinfo);
}
static inline int16_t GetErrorCode(instance_type* inst) {
return WebRtcIsac_GetErrorCode(inst);
}
static inline int16_t GetNewFrameLen(instance_type* inst) {
return WebRtcIsac_GetNewFrameLen(inst);
}
static inline void SetBandwidthInfo(instance_type* inst,
const IsacBandwidthInfo* bwinfo) {
WebRtcIsac_SetBandwidthInfo(inst, bwinfo);
}
static inline int16_t SetDecSampRate(instance_type* inst,
uint16_t sample_rate_hz) {
return WebRtcIsac_SetDecSampRate(inst, sample_rate_hz);
}
static inline int16_t SetEncSampRate(instance_type* inst,
uint16_t sample_rate_hz) {
return WebRtcIsac_SetEncSampRate(inst, sample_rate_hz);
}
static inline void SetEncSampRateInDecoder(instance_type* inst,
uint16_t sample_rate_hz) {
WebRtcIsac_SetEncSampRateInDecoder(inst, sample_rate_hz);
}
static inline void SetInitialBweBottleneck(instance_type* inst,
int bottleneck_bits_per_second) {
WebRtcIsac_SetInitialBweBottleneck(inst, bottleneck_bits_per_second);
}
static inline int16_t UpdateBwEstimate(instance_type* inst,
const uint8_t* encoded,
size_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts) {
return WebRtcIsac_UpdateBwEstimate(inst, encoded, packet_size,
rtp_seq_number, send_ts, arr_ts);
}
static inline int16_t SetMaxPayloadSize(instance_type* inst,
int16_t max_payload_size_bytes) {
return WebRtcIsac_SetMaxPayloadSize(inst, max_payload_size_bytes);
}
static inline int16_t SetMaxRate(instance_type* inst, int32_t max_bit_rate) {
return WebRtcIsac_SetMaxRate(inst, max_bit_rate);
}
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* lattice.c
*
* contains the normalized lattice filter routines (MA and AR) for iSAC codec
*
*/
#include "settings.h"
#include "codec.h"
#include <math.h>
#include <memory.h>
#include <string.h>
#ifdef WEBRTC_ANDROID
#include <stdlib.h>
#endif
/* filter the signal using normalized lattice filter */
/* MA filter */
void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
float *stateF,
float *stateG,
float *lat_in,
double *filtcoeflo,
double *lat_out)
{
int n,k,i,u,temp1;
int ord_1 = orderCoef+1;
float sth[MAX_AR_MODEL_ORDER];
float cth[MAX_AR_MODEL_ORDER];
float inv_cth[MAX_AR_MODEL_ORDER];
double a[MAX_AR_MODEL_ORDER+1];
float f[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], g[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
float gain1;
for (u=0;u<SUBFRAMES;u++)
{
/* set the Direct Form coefficients */
temp1 = u*ord_1;
a[0] = 1;
memcpy(a+1, filtcoeflo+temp1+1, sizeof(double) * (ord_1-1));
/* compute lattice filter coefficients */
WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
/* compute the gain */
gain1 = (float)filtcoeflo[temp1];
for (k=0;k<orderCoef;k++)
{
gain1 *= cth[k];
inv_cth[k] = 1/cth[k];
}
/* normalized lattice filter */
/*****************************/
/* initial conditions */
for (i=0;i<HALF_SUBFRAMELEN;i++)
{
f[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
g[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
}
/* get the state of f&g for the first input, for all orders */
for (i=1;i<ord_1;i++)
{
f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
}
/* filtering */
for(k=0;k<orderCoef;k++)
{
for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
{
f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
}
}
for(n=0;n<HALF_SUBFRAMELEN;n++)
{
lat_out[n + u * HALF_SUBFRAMELEN] = gain1 * f[orderCoef][n];
}
/* save the states */
for (i=0;i<ord_1;i++)
{
stateF[i] = f[i][HALF_SUBFRAMELEN-1];
stateG[i] = g[i][HALF_SUBFRAMELEN-1];
}
/* process next frame */
}
return;
}
/*///////////////////AR filter ///////////////////////////////*/
/* filter the signal using normalized lattice filter */
void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
float *stateF,
float *stateG,
double *lat_in,
double *lo_filt_coef,
float *lat_out)
{
int n,k,i,u,temp1;
int ord_1 = orderCoef+1;
float sth[MAX_AR_MODEL_ORDER];
float cth[MAX_AR_MODEL_ORDER];
double a[MAX_AR_MODEL_ORDER+1];
float ARf[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], ARg[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
float gain1,inv_gain1;
for (u=0;u<SUBFRAMES;u++)
{
/* set the denominator and numerator of the Direct Form */
temp1 = u*ord_1;
a[0] = 1;
memcpy(a+1, lo_filt_coef+temp1+1, sizeof(double) * (ord_1-1));
WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
gain1 = (float)lo_filt_coef[temp1];
for (k=0;k<orderCoef;k++)
{
gain1 = cth[k]*gain1;
}
/* initial conditions */
inv_gain1 = 1/gain1;
for (i=0;i<HALF_SUBFRAMELEN;i++)
{
ARf[orderCoef][i] = (float)lat_in[i + u * HALF_SUBFRAMELEN]*inv_gain1;
}
for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
{
ARf[i][0] = cth[i]*ARf[i+1][0] - sth[i]*stateG[i];
ARg[i+1][0] = sth[i]*ARf[i+1][0] + cth[i]* stateG[i];
}
ARg[0][0] = ARf[0][0];
for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
{
for(k=orderCoef-1;k>=0;k--)
{
ARf[k][n+1] = cth[k]*ARf[k+1][n+1] - sth[k]*ARg[k][n];
ARg[k+1][n+1] = sth[k]*ARf[k+1][n+1] + cth[k]* ARg[k][n];
}
ARg[0][n+1] = ARf[0][n+1];
}
memcpy(lat_out+u * HALF_SUBFRAMELEN, &(ARf[0][0]), sizeof(float) * HALF_SUBFRAMELEN);
/* cannot use memcpy in the following */
for (i=0;i<ord_1;i++)
{
stateF[i] = ARf[i][HALF_SUBFRAMELEN-1];
stateG[i] = ARg[i][HALF_SUBFRAMELEN-1];
}
}
return;
}
/* compute the reflection coefficients using the step-down procedure*/
/* converts the direct form parameters to lattice form.*/
/* a and b are vectors which contain the direct form coefficients,
according to
A(z) = a(1) + a(2)*z + a(3)*z^2 + ... + a(M+1)*z^M
B(z) = b(1) + b(2)*z + b(3)*z^2 + ... + b(M+1)*z^M
*/
void WebRtcIsac_Dir2Lat(double *a,
int orderCoef,
float *sth,
float *cth)
{
int m, k;
float tmp[MAX_AR_MODEL_ORDER];
float tmp_inv, cth2;
sth[orderCoef-1] = (float)a[orderCoef];
cth2 = 1.0f - sth[orderCoef-1] * sth[orderCoef-1];
cth[orderCoef-1] = (float)sqrt(cth2);
for (m=orderCoef-1; m>0; m--)
{
tmp_inv = 1.0f / cth2;
for (k=1; k<=m; k++)
{
tmp[k] = ((float)a[k] - sth[m] * (float)a[m-k+1]) * tmp_inv;
}
for (k=1; k<m; k++)
{
a[k] = tmp[k];
}
sth[m-1] = tmp[m];
cth2 = 1 - sth[m-1] * sth[m-1];
cth[m-1] = (float)sqrt(cth2);
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "settings.h"
#include "fft.h"
#include "codec.h"
#include "os_specific_inline.h"
#include <math.h>
void WebRtcIsac_InitTransform(TransformTables* tables) {
int k;
double fact, phase;
fact = PI / (FRAMESAMPLES_HALF);
phase = 0.0;
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
tables->costab1[k] = cos(phase);
tables->sintab1[k] = sin(phase);
phase += fact;
}
fact = PI * ((double) (FRAMESAMPLES_HALF - 1)) / ((double) FRAMESAMPLES_HALF);
phase = 0.5 * fact;
for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
tables->costab2[k] = cos(phase);
tables->sintab2[k] = sin(phase);
phase += fact;
}
}
void WebRtcIsac_Time2Spec(const TransformTables* tables,
double* inre1,
double* inre2,
int16_t* outreQ7,
int16_t* outimQ7,
FFTstr* fftstr_obj) {
int k;
int dims[1];
double tmp1r, tmp1i, xr, xi, yr, yi, fact;
double tmpre[FRAMESAMPLES_HALF], tmpim[FRAMESAMPLES_HALF];
dims[0] = FRAMESAMPLES_HALF;
/* Multiply with complex exponentials and combine into one complex vector */
fact = 0.5 / sqrt(FRAMESAMPLES_HALF);
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
tmp1r = tables->costab1[k];
tmp1i = tables->sintab1[k];
tmpre[k] = (inre1[k] * tmp1r + inre2[k] * tmp1i) * fact;
tmpim[k] = (inre2[k] * tmp1r - inre1[k] * tmp1i) * fact;
}
/* Get DFT */
WebRtcIsac_Fftns(1, dims, tmpre, tmpim, -1, 1.0, fftstr_obj);
/* Use symmetry to separate into two complex vectors and center frames in time around zero */
for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
xr = tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
yi = -tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k];
yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - k];
tmp1r = tables->costab2[k];
tmp1i = tables->sintab2[k];
outreQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1r - xi * tmp1i) * 128.0);
outimQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1i + xi * tmp1r) * 128.0);
outreQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1i - yi * tmp1r) * 128.0);
outimQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1r + yi * tmp1i) * 128.0);
}
}
void WebRtcIsac_Spec2time(const TransformTables* tables,
double* inre,
double* inim,
double* outre1,
double* outre2,
FFTstr* fftstr_obj) {
int k;
double tmp1r, tmp1i, xr, xi, yr, yi, fact;
int dims;
dims = FRAMESAMPLES_HALF;
for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
/* Move zero in time to beginning of frames */
tmp1r = tables->costab2[k];
tmp1i = tables->sintab2[k];
xr = inre[k] * tmp1r + inim[k] * tmp1i;
xi = inim[k] * tmp1r - inre[k] * tmp1i;
yr = -inim[FRAMESAMPLES_HALF - 1 - k] * tmp1r - inre[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
yi = -inre[FRAMESAMPLES_HALF - 1 - k] * tmp1r + inim[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
/* Combine into one vector, z = x + j * y */
outre1[k] = xr - yi;
outre1[FRAMESAMPLES_HALF - 1 - k] = xr + yi;
outre2[k] = xi + yr;
outre2[FRAMESAMPLES_HALF - 1 - k] = -xi + yr;
}
/* Get IDFT */
WebRtcIsac_Fftns(1, &dims, outre1, outre2, 1, FRAMESAMPLES_HALF, fftstr_obj);
/* Demodulate and separate */
fact = sqrt(FRAMESAMPLES_HALF);
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
tmp1r = tables->costab1[k];
tmp1i = tables->sintab1[k];
xr = (outre1[k] * tmp1r - outre2[k] * tmp1i) * fact;
outre2[k] = (outre2[k] * tmp1r + outre1[k] * tmp1i) * fact;
outre1[k] = xr;
}
}

View File

@ -1,4 +1,4 @@
audio_coding_sources = [ webrtc_audio_coding_sources = [
'codecs/isac/main/source/arith_routines.c', 'codecs/isac/main/source/arith_routines.c',
'codecs/isac/main/source/arith_routines_hist.c', 'codecs/isac/main/source/arith_routines_hist.c',
'codecs/isac/main/source/arith_routines_logist.c', 'codecs/isac/main/source/arith_routines_logist.c',
@ -18,16 +18,45 @@ audio_coding_sources = [
'codecs/isac/main/source/pitch_gain_tables.c', 'codecs/isac/main/source/pitch_gain_tables.c',
'codecs/isac/main/source/pitch_lag_tables.c', 'codecs/isac/main/source/pitch_lag_tables.c',
'codecs/isac/main/source/spectrum_ar_model_tables.c', 'codecs/isac/main/source/spectrum_ar_model_tables.c',
'codecs/audio_decoder.cc',
'codecs/audio_encoder.cc',
'codecs/isac/main/source/audio_decoder_isac.cc',
'codecs/isac/main/source/audio_encoder_isac.cc',
'codecs/isac/main/source/bandwidth_estimator.c',
'codecs/isac/main/source/crc.c',
'codecs/isac/main/source/decode.c',
'codecs/isac/main/source/decode_bwe.c',
'codecs/isac/main/source/encode.c',
'codecs/isac/main/source/fft.c',
'codecs/isac/main/source/isac.c',
'codecs/isac/main/source/lattice.c',
'codecs/isac/main/source/transform.c',
] ]
libaudio_coding = static_library('audio_coding', libwebrtc_audio_coding = library('webrtc_audio_coding',
audio_coding_sources, webrtc_audio_coding_sources,
dependencies: common_deps, dependencies: [base_dep, common_audio_dep] + common_deps,
include_directories: webrtc_inc, include_directories: webrtc_inc,
c_args: common_cflags, c_args: common_cflags,
cpp_args: common_cxxflags cpp_args: common_cxxflags,
soversion: soversion,
install: true
) )
audio_coding_dep = declare_dependency( webrtc_audio_coding_dep = declare_dependency(
link_with: libaudio_coding link_with: libwebrtc_audio_coding,
include_directories: webrtc_inc,
version: meson.project_version()
)
install_headers(['codecs/isac/bandwidth_info.h'],
subdir: 'webrtc_audio_processing/webrtc/modules/audio_coding/codecs/isac'
)
install_headers(['codecs/isac/main/source/settings.h'],
subdir: 'webrtc_audio_processing/webrtc/modules/audio_coding/codecs/isac/main/source'
)
install_headers(['codecs/isac/main/include/isac.h'],
subdir: 'webrtc_audio_processing/webrtc/modules/audio_coding/codecs/isac/main/include'
) )

View File

@ -109,7 +109,7 @@ install_headers(webrtc_audio_processing_include_headers,
libwebrtc_audio_processing = library('webrtc_audio_processing', libwebrtc_audio_processing = library('webrtc_audio_processing',
webrtc_audio_processing_sources, webrtc_audio_processing_sources,
dependencies: [base_dep, audio_coding_dep, system_wrappers_dep, common_audio_dep, audio_coding_dep, webrtc_dep] + common_deps, dependencies: [base_dep, webrtc_audio_coding_dep, system_wrappers_dep, common_audio_dep, webrtc_dep] + common_deps,
link_with: extra_libs, link_with: extra_libs,
include_directories: webrtc_inc, include_directories: webrtc_inc,
c_args: common_cflags, c_args: common_cflags,