blob: cb4878fee576d31dafe834d4dc92650096a3de06 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 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/*
12 * This file contains the function for obtaining comfort noise from noise parameters
13 * according to IETF RFC 3389.
14 */
15
16#include "dsp.h"
17
18#include "signal_processing_library.h"
19#include "webrtc_cng.h"
20
21#include "dsp_helpfunctions.h"
22#include "neteq_error_codes.h"
23
24/****************************************************************************
25 * WebRtcNetEQ_Cng(...)
26 *
27 * This function produces CNG according to RFC 3389.
28 *
29 * Input:
30 * - inst : NetEQ DSP instance
31 * - len : Number of samples to produce (max 640 or
32 * 640 - fsHz*5/8000 for first-time CNG, governed by
33 * the definition of WEBRTC_CNG_MAX_OUTSIZE_ORDER in
34 * webrtc_cng.h)
35 *
36 * Output:
37 * - pw16_outData : Output CNG
38 *
39 * Return value : 0 - Ok
40 * <0 - Error
41 */
42
43#ifdef NETEQ_CNG_CODEC
44/* Must compile NetEQ with CNG support to enable this function */
45
pbos@webrtc.org0946a562013-04-09 00:28:06 +000046int WebRtcNetEQ_Cng(DSPInst_t *inst, int16_t *pw16_outData, int len)
niklase@google.com470e71d2011-07-07 08:21:25 +000047{
pbos@webrtc.org0946a562013-04-09 00:28:06 +000048 int16_t w16_winMute = 0; /* mixing factor for overlap data */
49 int16_t w16_winUnMute = 0; /* mixing factor for comfort noise */
50 int16_t w16_winMuteInc = 0; /* mixing factor increment (negative) */
51 int16_t w16_winUnMuteInc = 0; /* mixing factor increment */
niklase@google.com470e71d2011-07-07 08:21:25 +000052 int i;
53
54 /*
55 * Check if last RecOut call was other than RFC3389,
56 * that is, this call is the first of a CNG period.
57 */
58 if (inst->w16_mode != MODE_RFC3389CNG)
59 {
60 /* Reset generation and overlap slightly with old data */
61
62 /* Generate len samples + overlap */
63 if (WebRtcCng_Generate(inst->CNG_Codec_inst, pw16_outData,
pbos@webrtc.org0946a562013-04-09 00:28:06 +000064 (int16_t) (len + inst->ExpandInst.w16_overlap), 1) < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +000065 {
66 /* error returned */
67 return -WebRtcCng_GetErrorCodeDec(inst->CNG_Codec_inst);
68 }
69
70 /* Set windowing parameters depending on sample rate */
71 if (inst->fs == 8000)
72 {
73 /* Windowing in Q15 */
74 w16_winMute = NETEQ_OVERLAP_WINMUTE_8KHZ_START;
75 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_8KHZ_INC;
76 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_8KHZ_START;
77 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_8KHZ_INC;
78#ifdef NETEQ_WIDEBAND
79 }
80 else if (inst->fs == 16000)
81 {
82 /* Windowing in Q15 */
83 w16_winMute = NETEQ_OVERLAP_WINMUTE_16KHZ_START;
84 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_16KHZ_INC;
85 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_16KHZ_START;
86 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_16KHZ_INC;
87#endif
88#ifdef NETEQ_32KHZ_WIDEBAND
89 }
90 else if (inst->fs == 32000)
91 {
92 /* Windowing in Q15 */
93 w16_winMute = NETEQ_OVERLAP_WINMUTE_32KHZ_START;
94 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_32KHZ_INC;
95 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_32KHZ_START;
96 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_32KHZ_INC;
97#endif
98#ifdef NETEQ_48KHZ_WIDEBAND
99 }
100 else if (inst->fs == 48000)
101 {
102 /* Windowing in Q15 */
103 w16_winMute = NETEQ_OVERLAP_WINMUTE_48KHZ_START;
104 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_48KHZ_INC;
105 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_48KHZ_START;
106 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_48KHZ_INC;
107#endif
108 }
109 else
110 {
111 /* Unsupported sample rate (should not be possible) */
112 return NETEQ_OTHER_ERROR;
113 }
114
115 /* Do overlap add between new vector and overlap */
116 for (i = 0; i < inst->ExpandInst.w16_overlap; i++)
117 {
118 /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000119 inst->ExpandInst.pw16_overlapVec[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 WEBRTC_SPL_MUL_16_16(
121 inst->ExpandInst.pw16_overlapVec[i], w16_winMute) +
122 WEBRTC_SPL_MUL_16_16(pw16_outData[i], w16_winUnMute)
123 + 16384, 15); /* shift with proper rounding */
124
125 w16_winMute += w16_winMuteInc; /* decrease mute factor (inc<0) */
126 w16_winUnMute += w16_winUnMuteInc; /* increase unmute factor (inc>0) */
127
128 }
129
130 /*
131 * Shift the contents of the outData buffer by overlap samples, since we
132 * already used these first samples in the overlapVec above
133 */
134
135 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_outData+inst->ExpandInst.w16_overlap, len);
136
137 }
138 else
139 {
140 /* This is a subsequent CNG call; no special overlap needed */
141
142 /* Generate len samples */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000143 if (WebRtcCng_Generate(inst->CNG_Codec_inst, pw16_outData, (int16_t) len, 0) < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 {
145 /* error returned */
146 return -WebRtcCng_GetErrorCodeDec(inst->CNG_Codec_inst);
147 }
148 }
149
150 return 0;
151
152}
153
154#endif /* NETEQ_CNG_CODEC */
155