Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: webrtc/modules/audio_coding/codecs/opus/opus_interface.c

Issue 1415173005: Prevent Opus DTX from generating intermittent noise during silence (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 11 matching lines...) Expand all
22 * side, we must allow for packets of that size. NetEq is currently limited 22 * side, we must allow for packets of that size. NetEq is currently limited
23 * to 60 ms on the receive side. */ 23 * to 60 ms on the receive side. */
24 kWebRtcOpusMaxDecodeFrameSizeMs = 120, 24 kWebRtcOpusMaxDecodeFrameSizeMs = 120,
25 25
26 /* Maximum sample count per channel is 48 kHz * maximum frame size in 26 /* Maximum sample count per channel is 48 kHz * maximum frame size in
27 * milliseconds. */ 27 * milliseconds. */
28 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs, 28 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
29 29
30 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */ 30 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */
31 kWebRtcOpusDefaultFrameSize = 960, 31 kWebRtcOpusDefaultFrameSize = 960,
32
33 // Maximum number of consecutive zeros, beyond or equal to which DTX can fail.
34 kZeroBreakCount = 158,
32 }; 35 };
33 36
34 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, 37 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
35 int32_t channels, 38 int32_t channels,
36 int32_t application) { 39 int32_t application) {
37 OpusEncInst* state; 40 if (inst == NULL)
38 if (inst != NULL) { 41 return -1;
39 state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
40 if (state) {
41 int opus_app;
42 switch (application) {
43 case 0: {
44 opus_app = OPUS_APPLICATION_VOIP;
45 break;
46 }
47 case 1: {
48 opus_app = OPUS_APPLICATION_AUDIO;
49 break;
50 }
51 default: {
52 free(state);
53 return -1;
54 }
55 }
56 42
57 int error; 43 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
58 state->encoder = opus_encoder_create(48000, channels, opus_app, 44 if (!state)
59 &error); 45 return -1;
60 state->in_dtx_mode = 0; 46
61 if (error == OPUS_OK && state->encoder != NULL) { 47 // Allocate buffer for input signal.
62 *inst = state; 48 state->buffer =
63 return 0; 49 (int16_t*)calloc(channels * 48 * kWebRtcOpusMaxEncodeFrameSizeMs,
64 } 50 sizeof(int16_t));
65 free(state); 51 if (!state->buffer) {
52 free(state);
53 return -1;
54 }
55
56 // Allocate buffer for zero counters.
57 state->zero_counts = (size_t*)calloc(channels, sizeof(size_t));
58 if (!state->zero_counts) {
59 free(state->buffer);
60 free(state);
61 return -1;
62 }
63
64 int opus_app;
65 switch (application) {
66 case 0: {
67 opus_app = OPUS_APPLICATION_VOIP;
68 break;
69 }
70 case 1: {
71 opus_app = OPUS_APPLICATION_AUDIO;
72 break;
73 }
74 default: {
75 WebRtcOpus_EncoderFree(state);
76 return -1;
66 } 77 }
67 } 78 }
68 return -1; 79
80 int error;
81 state->encoder = opus_encoder_create(48000, channels, opus_app,
82 &error);
83 if (error != OPUS_OK || state->encoder == NULL) {
84 WebRtcOpus_EncoderFree(state);
85 return -1;
86 }
87
88 state->in_dtx_mode = 0;
89 state->channels = channels;
90
91 *inst = state;
92 return 0;
69 } 93 }
70 94
71 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) { 95 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
72 if (inst) { 96 if (inst) {
73 opus_encoder_destroy(inst->encoder); 97 opus_encoder_destroy(inst->encoder);
98 free(inst->zero_counts);
99 free(inst->buffer);
74 free(inst); 100 free(inst);
75 return 0; 101 return 0;
76 } else { 102 } else {
77 return -1; 103 return -1;
78 } 104 }
79 } 105 }
80 106
81 int WebRtcOpus_Encode(OpusEncInst* inst, 107 int WebRtcOpus_Encode(OpusEncInst* inst,
82 const int16_t* audio_in, 108 const int16_t* audio_in,
83 size_t samples, 109 size_t samples,
84 size_t length_encoded_buffer, 110 size_t length_encoded_buffer,
85 uint8_t* encoded) { 111 uint8_t* encoded) {
86 int res; 112 int res;
87 113
88 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) { 114 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
89 return -1; 115 return -1;
90 } 116 }
91 117
118 const int channels = inst->channels;
119 int16_t* pointer = inst->buffer;
120 // Break long consecutive zeros by forcing a "1" every |kZeroBreakCount|
121 // samples.
122 memcpy(pointer, audio_in, samples * channels * sizeof(int16_t));
123 if (inst->in_dtx_mode) {
124 for (size_t i = 0; i < samples; ++i) {
125 for (int c = 0; c < channels; ++c, ++pointer) {
126 if (*pointer == 0) {
127 ++inst->zero_counts[c];
128 if (inst->zero_counts[c] == kZeroBreakCount) {
129 *pointer = 1;
130 inst->zero_counts[c] = 0;
131 }
132 } else {
133 inst->zero_counts[c] = 0;
134 }
135 }
136 }
137 }
tlegrand-webrtc 2015/10/27 13:51:22 I think there is a much simpler way of doing this,
minyue-webrtc 2015/10/27 18:29:01 There is a problem with checking if whole frame ar
tlegrand-webrtc 2015/10/28 13:20:37 Ah, I see now why you need to check for shorter pe
138
92 res = opus_encode(inst->encoder, 139 res = opus_encode(inst->encoder,
93 (const opus_int16*)audio_in, 140 inst->buffer,
94 (int)samples, 141 (int)samples,
95 encoded, 142 encoded,
96 (opus_int32)length_encoded_buffer); 143 (opus_int32)length_encoded_buffer);
97 144
98 if (res == 1) { 145 if (res == 1) {
99 // Indicates DTX since the packet has nothing but a header. In principle, 146 // Indicates DTX since the packet has nothing but a header. In principle,
100 // there is no need to send this packet. However, we do transmit the first 147 // there is no need to send this packet. However, we do transmit the first
101 // occurrence to let the decoder know that the encoder enters DTX mode. 148 // occurrence to let the decoder know that the encoder enters DTX mode.
102 if (inst->in_dtx_mode) { 149 if (inst->in_dtx_mode) {
103 return 0; 150 return 0;
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 return 0; 499 return 0;
453 } 500 }
454 501
455 for (n = 0; n < channels; n++) { 502 for (n = 0; n < channels; n++) {
456 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1))) 503 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
457 return 1; 504 return 1;
458 } 505 }
459 506
460 return 0; 507 return 0;
461 } 508 }
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/codecs/opus/opus_inst.h ('k') | webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698