Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/webrtc/modules/audio_coding/main/source/acm_speex.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 12.6 KB
Line 
1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/audio_coding/main/source/acm_speex.h"
12
13#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
14#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
15#include "webrtc/modules/audio_coding/main/source/acm_neteq.h"
16#include "webrtc/modules/audio_coding/neteq/interface/webrtc_neteq.h"
17#include "webrtc/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h"
18#include "webrtc/system_wrappers/interface/trace.h"
19
20#ifdef WEBRTC_CODEC_SPEEX
21// NOTE! Speex is not included in the open-source package. Modify this file or
22// your codec API to match the function calls and names of used Speex API file.
23#include "speex_interface.h"
24#endif
25
26namespace webrtc {
27
28namespace acm1 {
29
30#ifndef WEBRTC_CODEC_SPEEX
31ACMSPEEX::ACMSPEEX(int16_t /* codec_id */)
32    : encoder_inst_ptr_(NULL),
33      decoder_inst_ptr_(NULL),
34      compl_mode_(0),
35      vbr_enabled_(false),
36      encoding_rate_(-1),
37      sampling_frequency_(-1),
38      samples_in_20ms_audio_(-1) {
39  return;
40}
41
42ACMSPEEX::~ACMSPEEX() {
43  return;
44}
45
46int16_t ACMSPEEX::InternalEncode(
47    uint8_t* /* bitstream */,
48    int16_t* /* bitstream_len_byte */) {
49  return -1;
50}
51
52int16_t ACMSPEEX::DecodeSafe(uint8_t* /* bitstream */,
53                             int16_t /* bitstream_len_byte */,
54                             int16_t* /* audio */,
55                             int16_t* /* audio_samples */,
56                             int8_t* /* speech_type */) {
57  return -1;
58}
59
60int16_t ACMSPEEX::EnableDTX() {
61  return -1;
62}
63
64int16_t ACMSPEEX::DisableDTX() {
65  return -1;
66}
67
68int16_t ACMSPEEX::InternalInitEncoder(
69    WebRtcACMCodecParams* /* codec_params */) {
70  return -1;
71}
72
73int16_t ACMSPEEX::InternalInitDecoder(
74    WebRtcACMCodecParams* /* codec_params */) {
75  return -1;
76}
77
78int32_t ACMSPEEX::CodecDef(WebRtcNetEQ_CodecDef& /* codec_def */,
79                           const CodecInst& /* codec_inst */) {
80  return -1;
81}
82
83ACMGenericCodec* ACMSPEEX::CreateInstance(void) {
84  return NULL;
85}
86
87int16_t ACMSPEEX::InternalCreateEncoder() {
88  return -1;
89}
90
91void ACMSPEEX::DestructEncoderSafe() {
92  return;
93}
94
95int16_t ACMSPEEX::InternalCreateDecoder() {
96  return -1;
97}
98
99void ACMSPEEX::DestructDecoderSafe() {
100  return;
101}
102
103int16_t ACMSPEEX::SetBitRateSafe(const int32_t /* rate */) {
104  return -1;
105}
106
107void ACMSPEEX::InternalDestructEncoderInst(void* /* ptr_inst */) {
108  return;
109}
110
111#ifdef UNUSEDSPEEX
112int16_t ACMSPEEX::EnableVBR() {
113  return -1;
114}
115
116int16_t ACMSPEEX::DisableVBR() {
117  return -1;
118}
119
120int16_t ACMSPEEX::SetComplMode(int16_t mode) {
121  return -1;
122}
123#endif
124
125#else  //===================== Actual Implementation =======================
126
127ACMSPEEX::ACMSPEEX(int16_t codec_id)
128    : encoder_inst_ptr_(NULL),
129      decoder_inst_ptr_(NULL) {
130  codec_id_ = codec_id;
131
132  // Set sampling frequency, frame size and rate Speex
133  if (codec_id_ == ACMCodecDB::kSPEEX8) {
134    sampling_frequency_ = 8000;
135    samples_in_20ms_audio_ = 160;
136    encoding_rate_ = 11000;
137  } else if (codec_id_ == ACMCodecDB::kSPEEX16) {
138    sampling_frequency_ = 16000;
139    samples_in_20ms_audio_ = 320;
140    encoding_rate_ = 22000;
141  } else {
142    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
143                 "Wrong codec id for Speex.");
144
145    sampling_frequency_ = -1;
146    samples_in_20ms_audio_ = -1;
147    encoding_rate_ = -1;
148  }
149
150  has_internal_dtx_ = true;
151  dtx_enabled_ = false;
152  vbr_enabled_ = false;
153  compl_mode_ = 3;  // default complexity value
154
155  return;
156}
157
158ACMSPEEX::~ACMSPEEX() {
159  if (encoder_inst_ptr_ != NULL) {
160    WebRtcSpeex_FreeEnc(encoder_inst_ptr_);
161    encoder_inst_ptr_ = NULL;
162  }
163  if (decoder_inst_ptr_ != NULL) {
164    WebRtcSpeex_FreeDec(decoder_inst_ptr_);
165    decoder_inst_ptr_ = NULL;
166  }
167  return;
168}
169
170int16_t ACMSPEEX::InternalEncode(uint8_t* bitstream,
171                                 int16_t* bitstream_len_byte) {
172  int16_t status;
173  int16_t num_encoded_samples = 0;
174  int16_t n = 0;
175
176  while (num_encoded_samples < frame_len_smpl_) {
177    status = WebRtcSpeex_Encode(encoder_inst_ptr_,
178                                &in_audio_[in_audio_ix_read_], encoding_rate_);
179
180    // increment the read index this tell the caller that how far
181    // we have gone forward in reading the audio buffer
182    in_audio_ix_read_ += samples_in_20ms_audio_;
183    num_encoded_samples += samples_in_20ms_audio_;
184
185    if (status < 0) {
186      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
187                   "Error in Speex encoder");
188      return status;
189    }
190
191    // Update VAD, if internal DTX is used
192    if (has_internal_dtx_ && dtx_enabled_) {
193      vad_label_[n++] = status;
194      vad_label_[n++] = status;
195    }
196
197    if (status == 0) {
198      // This frame is detected as inactive. We need send whatever
199      // encoded so far.
200      *bitstream_len_byte = WebRtcSpeex_GetBitstream(encoder_inst_ptr_,
201                                                     (int16_t*)bitstream);
202      return *bitstream_len_byte;
203    }
204  }
205
206  *bitstream_len_byte = WebRtcSpeex_GetBitstream(encoder_inst_ptr_,
207                                                 (int16_t*)bitstream);
208  return *bitstream_len_byte;
209}
210
211int16_t ACMSPEEX::DecodeSafe(uint8_t* /* bitstream */,
212                             int16_t /* bitstream_len_byte */,
213                             int16_t* /* audio */,
214                             int16_t* /* audio_samples */,
215                             int8_t* /* speech_type */) {
216  return 0;
217}
218
219int16_t ACMSPEEX::EnableDTX() {
220  if (dtx_enabled_) {
221    return 0;
222  } else if (encoder_exist_) {  // check if encoder exist
223    // enable DTX
224    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, (vbr_enabled_ ? 1 : 0),
225                                compl_mode_, 1) < 0) {
226      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
227                   "Cannot enable DTX for Speex");
228      return -1;
229    }
230    dtx_enabled_ = true;
231    return 0;
232  } else {
233    return -1;
234  }
235
236  return 0;
237}
238
239int16_t ACMSPEEX::DisableDTX() {
240  if (!dtx_enabled_) {
241    return 0;
242  } else if (encoder_exist_) {  // check if encoder exist
243    // disable DTX
244    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, (vbr_enabled_ ? 1 : 0),
245                                compl_mode_, 0) < 0) {
246      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
247                   "Cannot disable DTX for Speex");
248      return -1;
249    }
250    dtx_enabled_ = false;
251    return 0;
252  } else {
253    // encoder doesn't exists, therefore disabling is harmless
254    return 0;
255  }
256
257  return 0;
258}
259
260int16_t ACMSPEEX::InternalInitEncoder(
261    WebRtcACMCodecParams* codec_params) {
262  // sanity check
263  if (encoder_inst_ptr_ == NULL) {
264    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
265                 "Cannot initialize Speex encoder, instance does not exist");
266    return -1;
267  }
268
269  int16_t status = SetBitRateSafe((codec_params->codecInstant).rate);
270  status +=
271      (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, vbr_enabled_, compl_mode_,
272                               ((codec_params->enable_dtx) ? 1 : 0)) < 0) ?
273                                   -1 : 0;
274
275  if (status >= 0) {
276    return 0;
277  } else {
278    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
279                 "Error in initialization of Speex encoder");
280    return -1;
281  }
282}
283
284int16_t ACMSPEEX::InternalInitDecoder(
285    WebRtcACMCodecParams* /* codec_params */) {
286  int16_t status;
287
288  // sanity check
289  if (decoder_inst_ptr_ == NULL) {
290    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
291                 "Cannot initialize Speex decoder, instance does not exist");
292    return -1;
293  }
294  status = ((WebRtcSpeex_DecoderInit(decoder_inst_ptr_) < 0) ? -1 : 0);
295
296  if (status >= 0) {
297    return 0;
298  } else {
299    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
300                 "Error in initialization of Speex decoder");
301    return -1;
302  }
303}
304
305int32_t ACMSPEEX::CodecDef(WebRtcNetEQ_CodecDef& codec_def,
306                           const CodecInst& codec_inst) {
307  if (!decoder_initialized_) {
308    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
309                 "Error, Speex decoder is not initialized");
310    return -1;
311  }
312
313  // Fill up the structure by calling
314  // "SET_CODEC_PAR" & "SET_SPEEX_FUNCTION."
315  // Then call NetEQ to add the codec to its
316  // database.
317
318  switch (sampling_frequency_) {
319    case 8000: {
320      SET_CODEC_PAR((codec_def), kDecoderSPEEX_8, codec_inst.pltype,
321                    decoder_inst_ptr_, 8000);
322      break;
323    }
324    case 16000: {
325      SET_CODEC_PAR((codec_def), kDecoderSPEEX_16, codec_inst.pltype,
326                    decoder_inst_ptr_, 16000);
327      break;
328    }
329    default: {
330      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
331                   "Unsupported sampling frequency for Speex");
332
333      return -1;
334    }
335  }
336
337  SET_SPEEX_FUNCTIONS((codec_def));
338  return 0;
339}
340
341ACMGenericCodec* ACMSPEEX::CreateInstance(void) {
342  return NULL;
343}
344
345int16_t ACMSPEEX::InternalCreateEncoder() {
346  return WebRtcSpeex_CreateEnc(&encoder_inst_ptr_, sampling_frequency_);
347}
348
349void ACMSPEEX::DestructEncoderSafe() {
350  if (encoder_inst_ptr_ != NULL) {
351    WebRtcSpeex_FreeEnc(encoder_inst_ptr_);
352    encoder_inst_ptr_ = NULL;
353  }
354  // there is no encoder set the following
355  encoder_exist_ = false;
356  encoder_initialized_ = false;
357  encoding_rate_ = 0;
358}
359
360int16_t ACMSPEEX::InternalCreateDecoder() {
361  return WebRtcSpeex_CreateDec(&decoder_inst_ptr_, sampling_frequency_, 1);
362}
363
364void ACMSPEEX::DestructDecoderSafe() {
365  if (decoder_inst_ptr_ != NULL) {
366    WebRtcSpeex_FreeDec(decoder_inst_ptr_);
367    decoder_inst_ptr_ = NULL;
368  }
369  // there is no encoder instance set the followings
370  decoder_exist_ = false;
371  decoder_initialized_ = false;
372}
373
374int16_t ACMSPEEX::SetBitRateSafe(const int32_t rate) {
375  // Check if changed rate
376  if (rate == encoding_rate_) {
377    return 0;
378  } else if (rate > 2000) {
379    encoding_rate_ = rate;
380    encoder_params_.codecInstant.rate = rate;
381  } else {
382    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
383                 "Unsupported encoding rate for Speex");
384
385    return -1;
386  }
387
388  return 0;
389}
390
391void ACMSPEEX::InternalDestructEncoderInst(void* ptr_inst) {
392  if (ptr_inst != NULL) {
393    WebRtcSpeex_FreeEnc((SPEEX_encinst_t_*) ptr_inst);
394  }
395  return;
396}
397
398#ifdef UNUSEDSPEEX
399
400// This API is currently not in use. If requested to be able to enable/disable
401// VBR an ACM API need to be added.
402int16_t ACMSPEEX::EnableVBR() {
403  if (vbr_enabled_) {
404    return 0;
405  } else if (encoder_exist_) {  // check if encoder exist
406    // enable Variable Bit Rate (VBR)
407    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 1, compl_mode_,
408                                (dtx_enabled_ ? 1 : 0)) < 0) {
409      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
410                   "Cannot enable VBR mode for Speex");
411
412      return -1;
413    }
414    vbr_enabled_ = true;
415    return 0;
416  } else {
417    return -1;
418  }
419}
420
421// This API is currently not in use. If requested to be able to enable/disable
422// VBR an ACM API need to be added.
423int16_t ACMSPEEX::DisableVBR() {
424  if (!vbr_enabled_) {
425    return 0;
426  } else if (encoder_exist_) {  // check if encoder exist
427    // disable DTX
428    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 0, compl_mode_,
429                                (dtx_enabled_ ? 1 : 0)) < 0) {
430      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
431                   "Cannot disable DTX for Speex");
432
433      return -1;
434    }
435    vbr_enabled_ = false;
436    return 0;
437  } else {
438    // encoder doesn't exists, therefore disabling is harmless
439    return 0;
440  }
441}
442
443// This API is currently not in use. If requested to be able to set complexity
444// an ACM API need to be added.
445int16_t ACMSPEEX::SetComplMode(int16_t mode) {
446  // Check if new mode
447  if (mode == compl_mode_) {
448    return 0;
449  } else if (encoder_exist_) {  // check if encoder exist
450    // Set new mode
451    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 0, mode,
452                                (dtx_enabled_ ? 1 : 0)) < 0) {
453      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
454                   "Error in complexity mode for Speex");
455      return -1;
456    }
457    compl_mode_ = mode;
458    return 0;
459  } else {
460    // encoder doesn't exists, therefore disabling is harmless
461    return 0;
462  }
463}
464
465#endif
466
467#endif
468
469}  // namespace acm1
470
471}  // namespace webrtc
Note: See TracBrowser for help on using the repository browser.