diff --git a/src/build/generate_asm_header.py b/src/build/generate_asm_header.py new file mode 100644 index 000000000..7d275efb8 --- /dev/null +++ b/src/build/generate_asm_header.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# 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. + +"""This script generates a C header file of offsets from an ARM assembler file. + +It parses an ARM assembler generated .S file, finds declarations of variables +whose names start with the string specified as the third argument in the +command-line, translates the variable names and values into constant defines and +writes them into a header file. +""" + +import sys + +def usage(): + print("Usage: generate_asm_header.py " + + " ") + sys.exit(1) + +def main(argv): + if len(argv) != 3: + usage() + + infile = open(argv[0]) + outfile = open(argv[1], 'w') + + for line in infile: # Iterate though all the lines in the input file. + if line.startswith(argv[2]): + outfile.write('#define ') + outfile.write(line.split(':')[0]) # Write the constant name. + outfile.write(' ') + + if line.find('.word') >= 0: + outfile.write(line.split('.word')[1]) # Write the constant value. + + infile.close() + outfile.close() + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/src/modules/audio_processing/ns/Android.mk b/src/modules/audio_processing/ns/Android.mk index 5e442f638..3b4e7ae20 100644 --- a/src/modules/audio_processing/ns/Android.mk +++ b/src/modules/audio_processing/ns/Android.mk @@ -23,7 +23,7 @@ LOCAL_SRC_FILES := \ nsx_core.c # Files for floating point. -# noise_suppression.c ns_core.c +# noise_suppression.c ns_core.c # Flags passed to both C and C++ files. LOCAL_CFLAGS := $(MY_WEBRTC_COMMON_DEFS) @@ -57,8 +57,20 @@ LOCAL_ARM_MODE := arm LOCAL_MODULE_CLASS := STATIC_LIBRARIES LOCAL_MODULE := libwebrtc_ns_neon LOCAL_MODULE_TAGS := optional +GEN := $(LOCAL_PATH)/nsx_core_neon_offsets.h -LOCAL_SRC_FILES := nsx_core_neon.c +# Generate a header file nsx_core_neon_offsets.h which will be included in +# assembly file nsx_core_neon.S, from file nsx_core_neon_offsets.c. +$(GEN): $(LOCAL_PATH)/../../../../src/build/generate_asm_header.py \ + $(intermediates)/nsx_core_neon_offsets.S + @python $^ $@ offset_nsx_ + +$(intermediates)/nsx_core_neon_offsets.S: $(LOCAL_PATH)/nsx_core_neon_offsets.c + @$(TARGET_CC) $(addprefix -I, $(LOCAL_INCLUDES)) $(addprefix -isystem ,\ + $(TARGET_C_INCLUDES)) -S -o $@ $^ + +LOCAL_GENERATED_SOURCES := $(GEN) +LOCAL_SRC_FILES := nsx_core_neon.S # Flags passed to both C and C++ files. LOCAL_CFLAGS := \ @@ -72,6 +84,8 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/../../.. \ $(LOCAL_PATH)/../../../common_audio/signal_processing/include +LOCAL_INCLUDES := $(LOCAL_C_INCLUDES) + ifndef NDK_ROOT include external/stlport/libstlport.mk endif diff --git a/src/modules/audio_processing/ns/nsx_core.c b/src/modules/audio_processing/ns/nsx_core.c index b8fe4b9bb..214b807ba 100644 --- a/src/modules/audio_processing/ns/nsx_core.c +++ b/src/modules/audio_processing/ns/nsx_core.c @@ -435,6 +435,18 @@ AnalysisUpdate WebRtcNsx_AnalysisUpdate; Denormalize WebRtcNsx_Denormalize; CreateComplexBuffer WebRtcNsx_CreateComplexBuffer; +#if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) +// Initialize function pointers for ARM Neon platform. +static void WebRtcNsx_InitNeon(void) { + WebRtcNsx_NoiseEstimation = WebRtcNsx_NoiseEstimationNeon; + WebRtcNsx_PrepareSpectrum = WebRtcNsx_PrepareSpectrumNeon; + WebRtcNsx_SynthesisUpdate = WebRtcNsx_SynthesisUpdateNeon; + WebRtcNsx_AnalysisUpdate = WebRtcNsx_AnalysisUpdateNeon; + WebRtcNsx_Denormalize = WebRtcNsx_DenormalizeNeon; + WebRtcNsx_CreateComplexBuffer = WebRtcNsx_CreateComplexBufferNeon; +} +#endif + // Update the noise estimation information. static void UpdateNoiseEstimate(NsxInst_t* inst, int offset) { WebRtc_Word32 tmp32no1 = 0; @@ -1881,8 +1893,11 @@ int WebRtcNsx_ProcessCore(NsxInst_t* inst, short* speechFrame, short* speechFram int q_domain_to_use = 0; // Code for ARMv7-Neon platform assumes the following: + assert(inst->anaLen > 0); + assert(inst->anaLen2 > 0); assert(inst->anaLen % 16 == 0); assert(inst->anaLen2 % 8 == 0); + assert(inst->blockLen10ms > 0); assert(inst->blockLen10ms % 16 == 0); assert(inst->magnLen == inst->anaLen2 + 1); diff --git a/src/modules/audio_processing/ns/nsx_core.h b/src/modules/audio_processing/ns/nsx_core.h index 0a0faf98f..4740c0610 100644 --- a/src/modules/audio_processing/ns/nsx_core.h +++ b/src/modules/audio_processing/ns/nsx_core.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * 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 @@ -206,10 +206,26 @@ typedef void (*CreateComplexBuffer)(NsxInst_t* inst, int16_t* out); extern CreateComplexBuffer WebRtcNsx_CreateComplexBuffer; -/**************************************************************************** - * Initialization of the above function pointers for ARM Neon. - */ -void WebRtcNsx_InitNeon(void); +#if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON) +// For the above function pointers, functions for generic platforms are declared +// and defined as static in file nsx_core.c, while those for ARM Neon platforms +// are declared below and defined in file nsx_core_neon.S. +void WebRtcNsx_NoiseEstimationNeon(NsxInst_t* inst, + uint16_t* magn, + uint32_t* noise, + int16_t* q_noise); +void WebRtcNsx_CreateComplexBufferNeon(NsxInst_t* inst, + int16_t* in, + int16_t* out); +void WebRtcNsx_SynthesisUpdateNeon(NsxInst_t* inst, + int16_t* out_frame, + int16_t gain_factor); +void WebRtcNsx_AnalysisUpdateNeon(NsxInst_t* inst, + int16_t* out, + int16_t* new_speech); +void WebRtcNsx_DenormalizeNeon(NsxInst_t* inst, int16_t* in, int factor); +void WebRtcNsx_PrepareSpectrumNeon(NsxInst_t* inst, int16_t* freq_buff); +#endif extern const WebRtc_Word16 WebRtcNsx_kLogTable[9]; extern const WebRtc_Word16 WebRtcNsx_kLogTableFrac[256]; diff --git a/src/modules/audio_processing/ns/nsx_core_neon.S b/src/modules/audio_processing/ns/nsx_core_neon.S new file mode 100644 index 000000000..31eea06a9 --- /dev/null +++ b/src/modules/audio_processing/ns/nsx_core_neon.S @@ -0,0 +1,682 @@ +@ +@ 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. +@ + +@ nsx_core_neon.s +@ This file contains some functions in NS, optimized for ARM Neon +@ platforms. Reference C code is in file nsx_core.c. Bit-exact. + +.arch armv7-a +.fpu neon + +#include "nsx_defines.h" +#include "nsx_core_neon_offsets.h" + +.global WebRtcNsx_NoiseEstimationNeon +.global WebRtcNsx_PrepareSpectrumNeon +.global WebRtcNsx_SynthesisUpdateNeon +.global WebRtcNsx_AnalysisUpdateNeon +.global WebRtcNsx_DenormalizeNeon +.global WebRtcNsx_CreateComplexBufferNeon + +@ void NoiseEstimationNeon(NsxInst_t* inst, +@ uint16_t* magn, +@ uint32_t* noise, +@ int16_t* q_noise); + +@ Register usage (across major loops of NoiseEstimationNeon()): +@ r0-r3: function arguments, and scratch registers. +@ r4: &inst +@ r5: &noiseEstLogQuantile[] +@ r6: inst->magnLen +@ r7: offset +@ r8: s, the loop counter for the LOOP_SIMULT +@ r9: &inst->noiseEstDensity[] +@ r10: &inst->noiseEstCounter[] +@ r11: countDiv +@ r12: i, the loop counter for LOOP_NOISEESTIMATION_MAGNLEN_INNER + +WebRtcNsx_NoiseEstimationNeon: +.fnstart +.save {r4-r11, r14} +.vsave {d8-d15} +.pad #(16 + (HALF_ANAL_BLOCKL + 3) / 4 * 8) + + push {r4-r11, r14} + vpush {d8-d15} + sub sp, #(16 + (HALF_ANAL_BLOCKL + 3) / 4 * 8) + +@ [sp, #0]: logval +@ [sp, #4]: noise +@ [sp, #8]: q_noise +@ [sp, #12]: factor +@ [sp, #16 ~ #(16 + (HALF_ANAL_BLOCKL + 3) / 4 * 8)]: lmagn[HALF_ANAL_BLOCKL] + + str r2, [sp, #4] @ noise + str r3, [sp, #8] @ q_noise + movw r4, #offset_nsx_normData + ldr r2, [r0, #offset_nsx_stages] @ inst->stages + ldr r4, [r0, r4] @ inst->normData + ldr r12, =WebRtcNsx_kLogTable + subs r3, r2, r4 @ tabind = inst->stages - inst->normData; + ldr r5, [r0, #offset_nsx_magnLen] @ magnLen + rsblt r3, #0 + lsl r3, #1 + ldrh r3, [r12, r3] @ logval = WebRtcNsx_kLogTable[tabind]; + add r12, sp, #16 @ lmagn[] + rsblt r3, #0 @ logval = -WebRtcNsx_kLogTable[-tabind]; + str r3, [sp] + vdup.16 q15, r3 + + ldr r9, =WebRtcNsx_kLogTableFrac + +LOOP_SET_LMAGN: + ldrh r2, [r1], #2 @ magn[i] + cmp r2, #0 + streqh r3, [r12], #2 @ lmagn[i] = logval; + beq CHECK_LMAGN_COUNTER + + clz r6, r2 + mov r4, r6 @ zeros + rsb r6, #31 + lsl r2, r4 + ubfx r4, r2, #23, #8 + mov r2, r4, lsl #1 + ldrh r4, [r9, r2] @ WebRtcNsx_kLogTableFrac[frac] + add r7, r4, r6, lsl #8 @ log2 + movw r2, #22713 @ log2_const + smulbb r2, r7, r2 + add r2, r3, r2, lsr #15 + strh r2, [r12], #2 @ lmagn[i] + +CHECK_LMAGN_COUNTER: + subs r5, #1 + bgt LOOP_SET_LMAGN + + movw r3, #21845 @ width_factor + vdup.16 q5, r3 + vmov.s16 q14, #WIDTH_Q8 + + movw r5, #offset_nsx_noiseEstLogQuantile + movw r7, #offset_nsx_blockIndex + movw r9, #offset_nsx_noiseEstDensity + add r5, r0 + ldr r6, [r0, #offset_nsx_magnLen] + ldr r7, [r0, r7] + add r9, r0 + cmp r7, #END_STARTUP_LONG + add r10, r0, #offset_nsx_noiseEstCounter + movge r7, #FACTOR_Q7 + movlt r7, #FACTOR_Q7_STARTUP + mov r4, r0 + str r7, [sp, #12] @ factor + mov r8, #SIMULT + mov r7, #0 + +LOOP_SIMULT: + ldrsh r1, [r10] @ inst->noiseEstCounter[s] + ldr r3, =WebRtcNsx_kCounterDiv + mov r11, r1, lsl #1 @ counter + ldrh r11, [r3, r11] @ countDiv = WebRtcNsx_kCounterDiv[counter]; + sub r12, r6, #1 @ Loop counter. + smulbb r3, r1, r11 @ countProd + vdup.16 q11, r11 + + vqrdmulh.s16 q11, q5, q11 @ WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( + @ width_factor, countDiv, 15); + vdup.16 d24, r11 + vdup.16 d25, r3 + + ldr r3, [sp, #12] @ factor + add r1, sp, #16 @ &lmagn[0] + vdup.16 q9, r3 + vmov.i16 q13, #512 + vmov.i16 q7, #15 + vmov.i32 q6, #FACTOR_Q16 + +LOOP_NOISEESTIMATION_MAGNLEN_INNER: + vld1.16 {q0}, [r9] @ noiseEstDensity[offset + i] + + @ Compute delta in the next two blocks. + vclz.i16 q4, q0 + vsub.i16 q4, q4, q7 @ Value of the shift factors; likely negative. + vmovl.s16 q3, d8 + vmovl.s16 q2, d9 + + vshl.s32 q1, q6, q3 + vmovn.i32 d8, q1 @ d8 holds shifted FACTOR_Q16. + vshl.s32 q1, q6, q2 + vcgt.s16 q3, q0, q13 @ Compare noiseEstDensity to 512. + vmovn.i32 d9, q1 @ d9 holds shifted FACTOR_Q16. + vmov.i16 q1, q9 + vbit.s16 q1, q4, q3 @ If bigger than 512, delta = shifted FACTOR_Q16. + + vmull.s16 q8, d3, d24 + vmull.s16 q4, d2, d24 + vshrn.i32 d2, q4, #14 + vshrn.i32 d3, q8, #14 + + vrshr.s16 q3, q1, #1 + vrshr.s16 q8, q1, #2 + vmull.s16 q4, d7, d28 + vmull.s16 q3, d6, d28 + vld1.16 {q10}, [r5] @ inst->noiseEstLogQuantile[offset + i] + vshrn.i32 d4, q3, #1 + vshrn.i32 d5, q4, #1 + + vld1.16 {q3}, [r1]! @ lmagn[i] + vsub.i16 q4, q10, q2 + vadd.i16 q8, q10, q8 + vsub.i16 q2, q3, q10 + vmax.s16 q4, q4, q15 + vcgt.s16 q1, q2, #0 + vbit q10, q8, q1 + vbif q10, q4, q1 + + vsub.i16 q1, q3, q10 + vst1.16 {q10}, [r5]! @ inst->noiseEstLogQuantile[offset + i] + vabs.s16 q4, q1 + vqrdmulh.s16 d2, d0, d25 + vqrdmulh.s16 d3, d1, d25 + vcgt.s16 q4, q14, q4 + vadd.i16 q1, q1, q11 + vbit q0, q1, q4 + subs r12, #8 + vst1.16 {q0}, [r9]! @ noiseEstDensity[offset + i] + bgt LOOP_NOISEESTIMATION_MAGNLEN_INNER + +@ +@ Last iteration over magnitude spectrum. +@ + +COMPUTE_DELTA: + ldrsh r2, [r9] @ inst->noiseEstDensity[offset + i] + cmp r2, #512 + bgt COMPUTE_DELTA_BIGGER_DENSITY + + movw r2, #offset_nsx_blockIndex + ldr r0, [r4, r2] + cmp r0, #END_STARTUP_LONG + movge r0, #FACTOR_Q7 @ delta + movlt r0, #FACTOR_Q7_STARTUP @ delta + b UPDATE_LOG_QUANTILE_ESTIMATE + +COMPUTE_DELTA_BIGGER_DENSITY: + clz r2, r2 + rsb r0, r2, #31 @ 14 - factor + mov r2, #FACTOR_Q16 + mov r0, r2, lsr r0 @ FACTOR_Q16 >> (14 - factor) + +UPDATE_LOG_QUANTILE_ESTIMATE: + smulbb r12, r0, r11 + ldrsh r1, [r1] @ lmagn[i] + ubfx r12, r12, #14, #16 @ tmp16 + ldrsh r2, [r5] @ inst->noiseEstLogQuantile[offset + i] + cmp r1, r2 + bgt UPDATE_LOG_QUANTILE_ESTIMATE_BIGGER_LMAGN + + add r12, #1 + ldr r3, [sp] @ logval + mov r0, r12, lsr #1 @ tmp16no1 + mov r12, #3 + smulbb r12, r0, r12 @ tmp16no2 + sub r2, r12, lsr #1 + cmp r3, r2 + ldrgt r2, [sp] + ldrgt r3, [sp] + b UPDATE_LOG_QUANTILE_ESTIMATE_STORE + +UPDATE_LOG_QUANTILE_ESTIMATE_BIGGER_LMAGN: + add r3, r12, #2 + add r2, r3, lsr #2 + +UPDATE_LOG_QUANTILE_ESTIMATE_STORE: + vmov.s16 r0, d25[0] @ countProd + strh r2, [r5] + add r5, #2 @ increment &noiseEstLogQuantile[offset + i] + +UPDATE_DENSITY_ESTIMATE: + subs r12, r1, r2 + rsblt r12, #0 + cmp r12, #WIDTH_Q8 + bge UPDATE_DENSITY_ESTIMATE_CHECK_COUNTER + + movw r3, #21845 @ width_factor + ldrh r12, [r9] @ inst->noiseEstDensity[offset + i] + smulbb r2, r3, r11 + smulbb r1, r12, r0 + add r0, r2, #1 << 14 @ Rounding + add r12, r1, #1 << 14 + mov r1, r12, lsr #15 + add r3, r1, r0, lsr #15 + strh r3, [r9] @ inst->noiseEstDensity[offset + i] + +UPDATE_DENSITY_ESTIMATE_CHECK_COUNTER: + add r9, #2 @ updata &noiseEstDensity[offset + i] + ldrsh r3, [r10] @ inst->noiseEstCounter[s] + cmp r3, #END_STARTUP_LONG + blt POST_UPDATE_DENSITY_ESTIMATE + + movw r2, #offset_nsx_blockIndex + mov r12, #0 + ldr r2, [r4, r2] + strh r12, [r10] + cmp r2, #END_STARTUP_LONG + blt POST_UPDATE_DENSITY_ESTIMATE + + mov r0, r4 + mov r1, r7 + bl UpdateNoiseEstimateNeon + +POST_UPDATE_DENSITY_ESTIMATE: + ldrh r3, [r10] + add r3, #1 + strh r3, [r10], #2 + subs r8, #1 + add r7, r6 @ offset += inst->magnLen; + bgt LOOP_SIMULT + + movw r2, #offset_nsx_blockIndex + ldr r2, [r4, r2] + cmp r2, #END_STARTUP_LONG + bge UPDATE_NOISE + + sub r1, r7, r6 + mov r0, r4 + bl UpdateNoiseEstimateNeon + +UPDATE_NOISE: + movw r1, #offset_nsx_noiseEstQuantile + add r1, r4 + ldr r2, [sp, #4] + +@ Initial value of loop counter r6 = inst->magnLen. +LOOP_UPDATE_NOISE: + ldrsh r0, [r1], #2 + subs r6, #1 + str r0, [r2], #4 + bgt LOOP_UPDATE_NOISE + +UPDATE_Q_NOISE: + movw r2, #offset_nsx_qNoise + ldr r1, [sp, #8] + ldrh r2, [r4, r2] + strh r2, [r1] + + add sp, #(16 + (HALF_ANAL_BLOCKL + 3) / 4 * 8) + vpop {d8-d15} + pop {r4-r11, pc} +.fnend + +@ static void UpdateNoiseEstimateNeon(NsxInst_t* inst, int offset); +@ Neon registers touched: q0-q3, q8-q13. +UpdateNoiseEstimateNeon: +.fnstart +.save {r4, r5, r6, r14} + + push {r4, r5, r6, r14} + mov r5, r0 + + vmov.i32 q10, #21 + vmov.i32 q11, #0x1FFFFF + vmov.i32 q9, #0x200000 + + movw r0, #offset_nsx_noiseEstLogQuantile + movw r6, #offset_nsx_magnLen + add r0, r5 @ &inst->noiseEstLogQuantile + add r4, r0, r1, lsl #1 @ &inst->noiseEstLogQuantile[offset] + ldrsh r6, [r5, r6] @ &inst->magnLen + + mov r0, r4 + mov r1, r6 + bl WebRtcSpl_MaxValueW16 + + sub r12, r6, #1 @ Loop counter: inst->magnLen - 1. + + movw r6, #11819 @ kExp2Const in Q13 + movw r2, #offset_nsx_noiseEstQuantile + vdup.16 d16, r6 + smulbb r3, r6, r0 + add r0, r3, #1 << 20 @ Round + movw r1, #offset_nsx_qNoise + mov r0, r0, lsr #21 + rsb r0, r0, #14 @ 14 - (round(kExp2Const * tmp16) >> 21) + add r2, r5 @ &inst->noiseEstQuantile + vdup.32 q13, r0 + str r0, [r5, r1] + + +LOOP_UPDATE: + vld1.16 {d0, d1}, [r4]! @ &inst->noiseEstLogQuantile[offset + i] + vmull.s16 q1, d0, d16 + vmull.s16 q0, d1, d16 + vshr.s32 q3, q1, #21 + vshr.s32 q2, q0, #21 + vand q1, q1, q11 + vand q0, q0, q11 + vsub.i32 q3, q3, q10 + vsub.i32 q2, q2, q10 + vorr q1, q1, q9 + vorr q0, q0, q9 + vadd.i32 q3, q3, q13 + vadd.i32 q2, q2, q13 + vshl.s32 q1, q1, q3 + vshl.s32 q0, q0, q2 + vqmovn.s32 d1, q0 + vqmovn.s32 d0, q1 + subs r12, #8 + vst1.16 {d0, d1}, [r2]! + bgt LOOP_UPDATE + +POST_LOOP_MAGNLEN: + ldrh r1, [r4] + smulbb r3, r6, r1 @ kExp2Const * ptr_noiseEstLogQuantile[offset + i] + mov r12, #0x00200000 + bfi r12, r3, #0, #21 @ tmp32no1 = 0x00200000 | (tmp32no2 & 0x001FFFFF); + rsb r0, #21 @ 21 - &inst->qNoise + sub r14, r0, r3, lsr #21 @ -tmp16 + mov r0, r12, lsr r14 + ssat r3, #16, r0 + strh r3, [r2] + + pop {r4, r5, r6, pc} +.fnend + +@ void PrepareSpectrumNeon(NsxInst_t* inst, int16_t* freq_buf); +WebRtcNsx_PrepareSpectrumNeon: +.fnstart +.save {r4-r8} + + push {r4-r8} + + movw r2, #offset_nsx_real + movw r12, #offset_nsx_noiseSupFilter + movw r4, #offset_nsx_imag + movw r5, #offset_nsx_magnLen + + add r2, r0 @ &inst->real[0] + add r4, r0 @ &inst->image[0] + mov r9, r4 @ &inst->image[0] + mov r3, r2 @ &inst->real[0] + ldr r5, [r0, r5] @ inst->magnLen + add r6, r4, #2 @ &inst->image[1] + sub r5, #1 + add r12, r0 @ &inst->noiseSupFilter[0] + add r5, r2, r5, lsl #1 @ &inst->real[inst->magnLen - 1] + +LOOP_MAGNLEN: + @ Filter the elements. + vld1.16 {d20, d21}, [r2] @ inst->real[] + vld1.16 {d24, d25}, [r12]! @ inst->noiseSupFilter[] + vld1.16 {d22, d23}, [r4] @ inst->imag[] + vmull.s16 q0, d20, d24 + vmull.s16 q1, d21, d25 + vmull.s16 q2, d22, d24 + vmull.s16 q3, d23, d25 + vshrn.s32 d0, q0, #14 + vshrn.s32 d1, q1, #14 + vshrn.s32 d2, q2, #14 + vshrn.s32 d3, q3, #14 + vst1.16 {d0, d1}, [r2]! + vst1.16 {d2, d3}, [r4]! + cmp r2, r5 + bcc LOOP_MAGNLEN + + @ Last two elements to filter: + ldrh r7, [r2] + ldrh r8, [r12] + ldrh r5, [r4] + smulbb r7, r7, r8 + smulbb r5, r5, r8 + mov r7, r7, lsr #14 + mov r8, r5, lsr #14 + strh r7, [r2] + strh r8, [r4] + + ldr r5, [r0, #offset_nsx_anaLen2] @ inst->anaLen2 + ldr r7, [r0, #offset_nsx_anaLen] @ inst->anaLen + add r5, r3, r5, lsl #1 @ &inst->real[inst->anaLen2] + + ldrh r2, [r3], #2 @ inst->real[0] + ldrh r0, [r9] @ inst->imag[0] + strh r2, [r1], #2 @ Store to freq_buf[0] + rsb r0, r0, #0 + strh r0, [r1], #2 @ Store to freq_buf[1]. Now r1 -> &freq_buf[2] + + add r2, r1, r7, lsl #2 + sub r2, #36 @ &freq_buf[-16] + + mvn r12, #0x1F @ -32 + +@ At the last iteration, &freq_buf[inst->anaLen + 1] will be written to by both +@ the vst1 instructions. Only the 2nd vst1 instruction has the correct value +@ (-inst->imag[inst->anaLen2]), so the order of the two vst1's is important. +LOOP_ANALEN2: + vld1.16 {d0, d1}, [r3]! @ inst->real[], starting from inst->real[1] + vld1.16 {d2, d3}, [r6]! @ inst->imag[], starting from inst->imag[1] + vmov.s16 d4, d0 + vmov.s16 d6, d1 + vneg.s16 d5, d2 + vneg.s16 d7, d3 + vzip.16 d0, d2 + vzip.16 d1, d3 + vzip.16 d4, d5 + vzip.16 d6, d7 + vrev64.32 d16, d3 + vrev64.32 d17, d1 + vrev64.32 d18, d2 + vrev64.32 d19, d0 + cmp r3, r5 + vst1.16 {d16, d17, d18, d19}, [r2], r12 + vst1.16 {d4, d5, d6, d7}, [r1]! + bls LOOP_ANALEN2 + + pop {r4-r8} + bx r14 +.fnend + +@ void WebRtcNsx_DenormalizeNeon(NsxInst_t* inst, int16_t* in, int factor); +WebRtcNsx_DenormalizeNeon: +.fnstart + movw r12, #offset_nsx_normData + movw r3, #offset_nsx_real + ldr r12, [r0, r12] @ inst->normData + add r3, r0 @ &inst->real[0] + sub r2, r12 + vdup.32 q10, r2 + + movw r2, #offset_nsx_anaLen + ldrsh r2, [r0, r2] @ inst->anaLen + add r0, r3, r2, lsl #1 @ &inst->real[inst->anaLen] + +LOOP_ANALEN: + vld2.16 {d0, d1}, [r1]! @ &in[] + vld2.16 {d2, d3}, [r1]! @ &in[] + vmovl.s16 q2, d0 + vmovl.s16 q3, d2 + vshl.s32 q2, q10 + vshl.s32 q3, q10 + vqmovn.s32 d0, q2 + vqmovn.s32 d1, q3 + vst1.16 {d0, d1}, [r3]! @ inst->real[] + cmp r3, r0 + blt LOOP_ANALEN + + bx r14 +.fnend + +@ void SynthesisUpdateNeon(NsxInst_t* inst, +@ int16_t* out_frame, +@ int16_t gain_factor); +WebRtcNsx_SynthesisUpdateNeon: +.fnstart +.save {r4, r5} + push {r4, r5} + + vdup.16 d31, r2 + + movw r2, #offset_nsx_anaLen + movw r4, #offset_nsx_real + movw r12, #offset_nsx_synthesisBuffer + + ldrsh r5, [r0, r2] @ inst->anaLen + add r12, r0 @ &inst->synthesisBuffer[0]; + ldr r3, [r0, #offset_nsx_window] @ &inst->window[0] + add r4, r0 @ &inst->real[0] + add r5, r12, r5, lsl #1 @ &inst->synthesisBuffer[inst->anaLen] + + mov r2, r12 @ &inst->synthesisBuffer[0]; + +LOOP_SYNTHESIS: + vld1.16 {d0, d1}, [r4]! @ inst->real[] + vld1.16 {d2, d3}, [r3]! @ inst->window[] + vld1.16 {d4, d5}, [r2] @ inst->synthesisBuffer[]; + vmull.s16 q3, d0, d2 + vmull.s16 q8, d1, d3 + vrshrn.i32 d0, q3, #14 + vrshrn.i32 d1, q8, #14 + vmull.s16 q3, d31, d0 + vmull.s16 q8, d31, d1 + vqrshrn.s32 d0, q3, #13 + vqrshrn.s32 d1, q8, #13 + vqadd.s16 d4, d0 + vqadd.s16 d5, d1 + vst1.16 {d4, d5}, [r2]! + cmp r2, r5 + blt LOOP_SYNTHESIS + +POST_LOOP_SYNTHESIS: + movw r3, #offset_nsx_blockLen10ms + ldr r2, [r0, r3] + mov r3, r12 @ &inst->synthesisBuffer[0]; + add r0, r12, r2, lsl #1 @ &inst->synthesisBuffer[inst->blockLen10ms] + +LOOP_BLOCKLEN10MS: + vld1.16 {q0, q1}, [r3]! @ inst->synthesisBuffer[]; + cmp r3, r0 + vst1.16 {q0, q1}, [r1]! @ out_frame[] + blt LOOP_BLOCKLEN10MS + + cmp r0, r5 + bge POST_LOOP_MEMCPY + +LOOP_MEMCPY: + vld1.16 {q0, q1}, [r0]! @ inst->synthesisBuffer[i + inst->blockLen10ms] + cmp r0, r5 + vst1.16 {q0, q1}, [r12]! @ inst->synthesisBuffer[i] + blt LOOP_MEMCPY + +POST_LOOP_MEMCPY: + cmp r12, r5 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + bge EXIT_SYNTHESISUPDATE + +LOOP_ZEROSARRAY: + vst1.16 {q10, q11}, [r12]! @ inst->synthesisBuffer[i + inst->anaLen] + cmp r12, r5 + blt LOOP_ZEROSARRAY + +EXIT_SYNTHESISUPDATE: + pop {r4, r5} + bx r14 + +.fnend + +@ void AnalysisUpdateNeon(NsxInst_t* inst, int16_t* out, int16_t* new_speech); +WebRtcNsx_AnalysisUpdateNeon: +.fnstart +.save {r4-r6} + push {r4-r6} + + movw r3, #offset_nsx_analysisBuffer + movw r4, #offset_nsx_anaLen + movw r12, #offset_nsx_blockLen10ms + add r3, r0 @ &inst->analysisBuffer[0] + ldrsh r4, [r0, r4] @ inst->anaLen + ldr r12, [r0, r12] @ inst->blockLen10ms + sub r6, r4, r12 + add r6, r3, r6, lsl #1 @ &inst->analysisBuffer[inst->anaLen + @ - inst->blockLen10ms] + cmp r3, r6 + mov r5, r3 + bge POST_LOOP_MEMCPY_1 + + add r12, r3, r12, lsl #1 @ &inst->analysisBuffer[inst->blockLen10ms] + +LOOP_MEMCPY_1: + vld1.16 {q10, q11}, [r12]! @ inst->analysisBuffer[i + inst->blockLen10ms] + vst1.16 {q10, q11}, [r5]! @ inst->analysisBuffer[i] + cmp r5, r6 + blt LOOP_MEMCPY_1 + +POST_LOOP_MEMCPY_1: + add r12, r3, r4, lsl #1 @ &inst->analysisBuffer[inst->anaLen] + cmp r5, r12 + bge POST_LOOP_MEMCPY_2 + +LOOP_MEMCPY_2: + vld1.16 {q10, q11}, [r2]! @ new_speech[i] + vst1.16 {q10, q11}, [r5]! @ inst->analysisBuffer[ + @ i + inst->anaLen - inst->blockLen10ms] + cmp r5, r12 + blt LOOP_MEMCPY_2 + +POST_LOOP_MEMCPY_2: + add r4, r1, r4, lsl #1 @ &out[inst->anaLen] + cmp r1, r4 + ldr r2, [r0, #offset_nsx_window] @ &inst->window[0] + bge POST_LOOP_WINDOW_DATA + +LOOP_WINDOW_DATA: + vld1.16 {d4, d5}, [r3]! @ inst->analysisBuffer[] + vld1.16 {d6, d7}, [r2]! @ inst->window[] + vmull.s16 q0, d4, d6 + vmull.s16 q1, d5, d7 + vrshrn.i32 d4, q0, #14 + vrshrn.i32 d5, q1, #14 + vst1.16 {d4, d5}, [r1]! @ out[] + cmp r1, r4 + blt LOOP_WINDOW_DATA + +POST_LOOP_WINDOW_DATA: + pop {r4-r6} + bx r14 +.fnend + +@ void CreateComplexBufferNeon(NsxInst_t* inst, int16_t* in, int16_t* out); +WebRtcNsx_CreateComplexBufferNeon: +.fnstart + movw r3, #offset_nsx_anaLen + movw r12, #offset_nsx_normData + ldrsh r3, [r0, r3] @ inst->anaLen + ldr r12, [r0, r12] @ inst->normData + add r3, r1, r3, lsl #1 @ &in[inst->anaLen] + + vmov.i16 d7, #0 @ For writing to imaginary parts. + vmov.i16 d5, #0 @ For writing to imaginary parts. + vdup.i16 q10, r12 + +LOOP_CREATE_COMPLEX_BUFFER: @ Unrolled by 16. + vld1.16 {d0, d1, d2, d3}, [r1]! @ in[] + cmp r1, r3 + vshl.s16 q0, q10 + vshl.s16 q1, q10 + vmov d4, d1 + vmov d1, d5 + vmov d6, d3 + vmov d3, d7 + vst2.16 {d0, d1}, [r2]! + vst2.16 {d4, d5}, [r2]! + vst2.16 {d2, d3}, [r2]! + vst2.16 {d6, d7}, [r2]! + blt LOOP_CREATE_COMPLEX_BUFFER + + bx r14 +.fnend diff --git a/src/modules/audio_processing/ns/nsx_core_neon.c b/src/modules/audio_processing/ns/nsx_core_neon.c index 92daa75d9..8fc74e72d 100644 --- a/src/modules/audio_processing/ns/nsx_core_neon.c +++ b/src/modules/audio_processing/ns/nsx_core_neon.c @@ -91,10 +91,10 @@ static void UpdateNoiseEstimateNeon(NsxInst_t* inst, int offset) { } // Noise Estimation -static void NoiseEstimationNeon(NsxInst_t* inst, - uint16_t* magn, - uint32_t* noise, - int16_t* q_noise) { +void WebRtcNsx_NoiseEstimationNeon(NsxInst_t* inst, + uint16_t* magn, + uint32_t* noise, + int16_t* q_noise) { int16_t lmagn[HALF_ANAL_BLOCKL], counter, countDiv; int16_t countProd, delta, zeros, frac; int16_t log2, tabind, logval, tmp16, tmp16no1, tmp16no2; @@ -320,7 +320,7 @@ static void NoiseEstimationNeon(NsxInst_t* inst, } // Filter the data in the frequency domain, and create spectrum. -static void PrepareSpectrumNeon(NsxInst_t* inst, int16_t* freq_buf) { +void WebRtcNsx_PrepareSpectrumNeon(NsxInst_t* inst, int16_t* freq_buf) { // (1) Filtering. @@ -455,7 +455,7 @@ static void PrepareSpectrumNeon(NsxInst_t* inst, int16_t* freq_buf) { } // Denormalize the input buffer. -static __inline void DenormalizeNeon(NsxInst_t* inst, int16_t* in, int factor) { +void WebRtcNsx_DenormalizeNeon(NsxInst_t* inst, int16_t* in, int factor) { int16_t* ptr_real = &inst->real[0]; int16_t* ptr_in = &in[0]; @@ -494,9 +494,9 @@ static __inline void DenormalizeNeon(NsxInst_t* inst, int16_t* in, int factor) { // For the noise supress process, synthesis, read out fully processed segment, // and update synthesis buffer. -static void SynthesisUpdateNeon(NsxInst_t* inst, - int16_t* out_frame, - int16_t gain_factor) { +void WebRtcNsx_SynthesisUpdateNeon(NsxInst_t* inst, + int16_t* out_frame, + int16_t gain_factor) { int16_t* ptr_real = &inst->real[0]; int16_t* ptr_syn = &inst->synthesisBuffer[0]; const int16_t* ptr_window = &inst->window[0]; @@ -605,9 +605,9 @@ static void SynthesisUpdateNeon(NsxInst_t* inst, } // Update analysis buffer for lower band, and window data before FFT. -static void AnalysisUpdateNeon(NsxInst_t* inst, - int16_t* out, - int16_t* new_speech) { +void WebRtcNsx_AnalysisUpdateNeon(NsxInst_t* inst, + int16_t* out, + int16_t* new_speech) { int16_t* ptr_ana = &inst->analysisBuffer[inst->blockLen10ms]; int16_t* ptr_out = &inst->analysisBuffer[0]; @@ -682,9 +682,9 @@ static void AnalysisUpdateNeon(NsxInst_t* inst, // Create a complex number buffer (out[]) as the intput (in[]) interleaved with // zeros, and normalize it. -static __inline void CreateComplexBufferNeon(NsxInst_t* inst, - int16_t* in, - int16_t* out) { +void WebRtcNsx_CreateComplexBufferNeon(NsxInst_t* inst, + int16_t* in, + int16_t* out) { int16_t* ptr_out = &out[0]; int16_t* ptr_in = &in[0]; @@ -723,12 +723,3 @@ static __inline void CreateComplexBufferNeon(NsxInst_t* inst, ); } } - -void WebRtcNsx_InitNeon(void) { - WebRtcNsx_NoiseEstimation = NoiseEstimationNeon; - WebRtcNsx_PrepareSpectrum = PrepareSpectrumNeon; - WebRtcNsx_SynthesisUpdate = SynthesisUpdateNeon; - WebRtcNsx_AnalysisUpdate = AnalysisUpdateNeon; - WebRtcNsx_Denormalize = DenormalizeNeon; - WebRtcNsx_CreateComplexBuffer = CreateComplexBufferNeon; -} diff --git a/src/modules/audio_processing/ns/nsx_core_neon_offsets.c b/src/modules/audio_processing/ns/nsx_core_neon_offsets.c new file mode 100644 index 000000000..ee64a5903 --- /dev/null +++ b/src/modules/audio_processing/ns/nsx_core_neon_offsets.c @@ -0,0 +1,34 @@ +/* + * 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 "nsx_core.h" + +#include + +// Define offset variables that will be compiled and abstracted to constant +// defines, which will then only be used in ARM assembly code. +int offset_nsx_anaLen = offsetof(NsxInst_t, anaLen); +int offset_nsx_anaLen2 = offsetof(NsxInst_t, anaLen2); +int offset_nsx_normData = offsetof(NsxInst_t, normData); +int offset_nsx_analysisBuffer = offsetof(NsxInst_t, analysisBuffer); +int offset_nsx_synthesisBuffer = offsetof(NsxInst_t, synthesisBuffer); +int offset_nsx_blockLen10ms = offsetof(NsxInst_t, blockLen10ms); +int offset_nsx_window = offsetof(NsxInst_t, window); +int offset_nsx_real = offsetof(NsxInst_t, real); +int offset_nsx_imag = offsetof(NsxInst_t, imag); +int offset_nsx_noiseSupFilter = offsetof(NsxInst_t, noiseSupFilter); +int offset_nsx_magnLen = offsetof(NsxInst_t, magnLen); +int offset_nsx_noiseEstLogQuantile = offsetof(NsxInst_t, noiseEstLogQuantile); +int offset_nsx_noiseEstQuantile = offsetof(NsxInst_t, noiseEstQuantile); +int offset_nsx_qNoise = offsetof(NsxInst_t, qNoise); +int offset_nsx_stages = offsetof(NsxInst_t, stages); +int offset_nsx_blockIndex = offsetof(NsxInst_t, blockIndex); +int offset_nsx_noiseEstCounter = offsetof(NsxInst_t, noiseEstCounter); +int offset_nsx_noiseEstDensity = offsetof(NsxInst_t, noiseEstDensity); diff --git a/src/modules/audio_processing/ns/nsx_defines.h b/src/modules/audio_processing/ns/nsx_defines.h index cd1e3bf59..ef4d297b9 100644 --- a/src/modules/audio_processing/ns/nsx_defines.h +++ b/src/modules/audio_processing/ns/nsx_defines.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * 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 @@ -11,49 +11,53 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_ -#define ANAL_BLOCKL_MAX 256 // max analysis block length -#define HALF_ANAL_BLOCKL 129 // half max analysis block length + 1 +#define ANAL_BLOCKL_MAX 256 /* Max analysis block length */ +#define HALF_ANAL_BLOCKL 129 /* Half max analysis block length + 1 */ #define SIMULT 3 #define END_STARTUP_LONG 200 #define END_STARTUP_SHORT 50 -#define FACTOR_Q16 (WebRtc_Word32)2621440 // 40 in Q16 -#define FACTOR_Q7 (WebRtc_Word16)5120 // 40 in Q7 -#define FACTOR_Q7_STARTUP (WebRtc_Word16)1024 // 8 in Q7 -#define WIDTH_Q8 3 // 0.01 in Q8 (or 25 ) -//PARAMETERS FOR NEW METHOD -#define DD_PR_SNR_Q11 2007 // ~= Q11(0.98) DD update of prior SNR -#define ONE_MINUS_DD_PR_SNR_Q11 41 // DD update of prior SNR -#define SPECT_FLAT_TAVG_Q14 4915 // (0.30) tavg parameter for spectral flatness measure -#define SPECT_DIFF_TAVG_Q8 77 // (0.30) tavg parameter for spectral flatness measure -#define PRIOR_UPDATE_Q14 1638 // Q14(0.1) update parameter of prior model -#define NOISE_UPDATE_Q8 26 // 26 ~= Q8(0.1) update parameter for noise -// probability threshold for noise state in speech/noise likelihood -#define ONE_MINUS_PROB_RANGE_Q8 205 // 205 ~= Q8(0.8) -#define HIST_PAR_EST 1000 // histogram size for estimation of parameters -//FEATURE EXTRACTION CONFIG -//bin size of histogram +#define FACTOR_Q16 2621440 /* 40 in Q16 */ +#define FACTOR_Q7 5120 /* 40 in Q7 */ +#define FACTOR_Q7_STARTUP 1024 /* 8 in Q7 */ +#define WIDTH_Q8 3 /* 0.01 in Q8 (or 25 ) */ + +/* PARAMETERS FOR NEW METHOD */ +#define DD_PR_SNR_Q11 2007 /* ~= Q11(0.98) DD update of prior SNR */ +#define ONE_MINUS_DD_PR_SNR_Q11 41 /* DD update of prior SNR */ +#define SPECT_FLAT_TAVG_Q14 4915 /* (0.30) tavg parameter for spectral flatness measure */ +#define SPECT_DIFF_TAVG_Q8 77 /* (0.30) tavg parameter for spectral flatness measure */ +#define PRIOR_UPDATE_Q14 1638 /* Q14(0.1) Update parameter of prior model */ +#define NOISE_UPDATE_Q8 26 /* 26 ~= Q8(0.1) Update parameter for noise */ + +/* Probability threshold for noise state in speech/noise likelihood. */ +#define ONE_MINUS_PROB_RANGE_Q8 205 /* 205 ~= Q8(0.8) */ +#define HIST_PAR_EST 1000 /* Histogram size for estimation of parameters */ + +/* FEATURE EXTRACTION CONFIG */ +/* Bin size of histogram */ #define BIN_SIZE_LRT 10 -//scale parameters: multiply dominant peaks of the histograms by scale factor to obtain -// thresholds for prior model -#define FACTOR_1_LRT_DIFF 6 //for LRT and spectral difference (5 times bigger) -//for spectral_flatness: used when noise is flatter than speech (10 times bigger) +/* Scale parameters: multiply dominant peaks of the histograms by scale factor to obtain. */ +/* Thresholds for prior model */ +#define FACTOR_1_LRT_DIFF 6 /* For LRT and spectral difference (5 times bigger) */ +/* For spectral_flatness: used when noise is flatter than speech (10 times bigger). */ #define FACTOR_2_FLAT_Q10 922 -//peak limit for spectral flatness (varies between 0 and 1) -#define THRES_PEAK_FLAT 24 // * 2 * BIN_SIZE_FLAT_FX -//limit on spacing of two highest peaks in histogram: spacing determined by bin size -#define LIM_PEAK_SPACE_FLAT_DIFF 4 // * 2 * BIN_SIZE_DIFF_FX -//limit on relevance of second peak: +/* Peak limit for spectral flatness (varies between 0 and 1) */ +#define THRES_PEAK_FLAT 24 /* * 2 * BIN_SIZE_FLAT_FX */ +/* Limit on spacing of two highest peaks in histogram: spacing determined by bin size. */ +#define LIM_PEAK_SPACE_FLAT_DIFF 4 /* * 2 * BIN_SIZE_DIFF_FX */ +/* Limit on relevance of second peak */ #define LIM_PEAK_WEIGHT_FLAT_DIFF 2 -#define THRES_FLUCT_LRT 10240 //=20 * inst->modelUpdate; fluctuation limit of LRT feat. -//limit on the max and min values for the feature thresholds -#define MAX_FLAT_Q10 38912 // * 2 * BIN_SIZE_FLAT_FX -#define MIN_FLAT_Q10 4096 // * 2 * BIN_SIZE_FLAT_FX -#define MAX_DIFF 100 // * 2 * BIN_SIZE_DIFF_FX -#define MIN_DIFF 16 // * 2 * BIN_SIZE_DIFF_FX -//criteria of weight of histogram peak to accept/reject feature -#define THRES_WEIGHT_FLAT_DIFF 154//(int)(0.3*(inst->modelUpdate)) for flatness and difference -// -#define STAT_UPDATES 9 // Update every 512 = 1 << 9 block -#define ONE_MINUS_GAMMA_PAUSE_Q8 13 // ~= Q8(0.05) update for conservative noise estimate -#define GAMMA_NOISE_TRANS_AND_SPEECH_Q8 3 // ~= Q8(0.01) update for transition and noise region -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_ +#define THRES_FLUCT_LRT 10240 /* = 20 * inst->modelUpdate; fluctuation limit of LRT feat. */ +/* Limit on the max and min values for the feature thresholds */ +#define MAX_FLAT_Q10 38912 /* * 2 * BIN_SIZE_FLAT_FX */ +#define MIN_FLAT_Q10 4096 /* * 2 * BIN_SIZE_FLAT_FX */ +#define MAX_DIFF 100 /* * 2 * BIN_SIZE_DIFF_FX */ +#define MIN_DIFF 16 /* * 2 * BIN_SIZE_DIFF_FX */ +/* Criteria of weight of histogram peak to accept/reject feature */ +#define THRES_WEIGHT_FLAT_DIFF 154 /*(int)(0.3*(inst->modelUpdate)) for flatness and difference */ + +#define STAT_UPDATES 9 /* Update every 512 = 1 << 9 block */ +#define ONE_MINUS_GAMMA_PAUSE_Q8 13 /* ~= Q8(0.05) Update for conservative noise estimate */ +#define GAMMA_NOISE_TRANS_AND_SPEECH_Q8 3 /* ~= Q8(0.01) Update for transition and noise region */ + +#endif /* WEBRTC_MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_ */