dervisakyuz
asked on
a c++ code must be writen in java
Hi all;
i have to implement this c++ code into java. code is;
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
#define TAPS (80*8)
typedef signed short MONO;
typedef struct { signed short l; signed short r; }
STEREO;
float dB2q(float dB) { return powf(10.0f, dB / 20.0f); }
float q2dB(float q) { return 20.0f * log10f(q); }
int main(int argc, char *argv[])
{
STEREO inbuf[TAPS], outbuf[TAPS];
fprintf(stderr, "usage: aec_test [ambient in dB] <in.raw >out.raw\n");
AEC aec;
if (argc >= 2) {
aec.setambient(MAXPCM*dB2q (atof(argv [1])));
}
int taps;
while (taps = fread(inbuf, sizeof(STEREO), TAPS, stdin)) {
int i;
for (i = 0; i < taps; ++i) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
fwrite(outbuf, sizeof(STEREO), taps, stdout);
}
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0f);
fprintf(stderr, "Ambient = %2.0f dB\n", ambientdB);
fflush(NULL);
return 0;
}
i have to implement this c++ code into java. code is;
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
#define TAPS (80*8)
typedef signed short MONO;
typedef struct { signed short l; signed short r; }
STEREO;
float dB2q(float dB) { return powf(10.0f, dB / 20.0f); }
float q2dB(float q) { return 20.0f * log10f(q); }
int main(int argc, char *argv[])
{
STEREO inbuf[TAPS], outbuf[TAPS];
fprintf(stderr, "usage: aec_test [ambient in dB] <in.raw >out.raw\n");
AEC aec;
if (argc >= 2) {
aec.setambient(MAXPCM*dB2q
}
int taps;
while (taps = fread(inbuf, sizeof(STEREO), TAPS, stdin)) {
int i;
for (i = 0; i < taps; ++i) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
fwrite(outbuf, sizeof(STEREO), taps, stdout);
}
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0f);
fprintf(stderr, "Ambient = %2.0f dB\n", ambientdB);
fflush(NULL);
return 0;
}
What do you have a problem with ? Do you know C++ ? Do you know Java ?
>> i have to implement this c++ code into java. code is;
then do it
then do it
ASKER
i know both java and c++ very little.
because of this reason i cant do it.This my problem and i want to help
thanks
because of this reason i cant do it.This my problem and i want to help
thanks
So, you can't start at all, or you started, but couldn't continue ? Show us what you have and we'll point you in the right direction ...
ASKER
for example how can i use inbuf or outbuf in java
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
and what about fread? can i use in java?
You could eg. use the readFully() member of the DataInput interface (implemented by DataInputStream eg.) :
http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataInput.html
this will let you read a given number of bytes from an input stream, just like fread does.
http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataInput.html
this will let you read a given number of bytes from an input stream, just like fread does.
ASKER
hi again i try but i cant do it.
could you write it for me please?
thanks.
could you write it for me please?
thanks.
What do you have now ? I prefer you do the most work yourself (with our help) ... that way you learn the most from this problem. So show me the code you have, and I'll help you along ...
ASKER
ok. here is the all code :
Appendix A. The C++ Source Code
/***************** A.1 APPENDIX aec.h *****************/
/* aec.h
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Acoustic Echo Cancellation NLMS-pw algorithm
*
* Version 1.3 filter created with www.dsptutor.freeuk.com
*/
#ifndef _AEC_H /* include only once */
// use double if your CPU does software-emulation of float
typedef float REAL;
/* dB Values */
const REAL M0dB = 1.0f;
const REAL M3dB = 0.71f;
const REAL M6dB = 0.50f;
const REAL M9dB = 0.35f;
const REAL M12dB = 0.25f;
const REAL M18dB = 0.125f;
const REAL M24dB = 0.063f;
/* dB values for 16bit PCM */
/* MxdB_PCM = 32767 * 10 ^(x / 20) */
const REAL M10dB_PCM = 10362.0f;
const REAL M20dB_PCM = 3277.0f;
const REAL M25dB_PCM = 1843.0f;
const REAL M30dB_PCM = 1026.0f;
const REAL M35dB_PCM = 583.0f;
const REAL M40dB_PCM = 328.0f;
const REAL M45dB_PCM = 184.0f;
const REAL M50dB_PCM = 104.0f;
const REAL M55dB_PCM = 58.0f;
const REAL M60dB_PCM = 33.0f;
const REAL M65dB_PCM = 18.0f;
const REAL M70dB_PCM = 10.0f;
const REAL M75dB_PCM = 6.0f;
const REAL M80dB_PCM = 3.0f;
const REAL M85dB_PCM = 2.0f;
const REAL M90dB_PCM = 1.0f;
const REAL MAXPCM = 32767.0f;
/* Design constants (Change to fine tune the algorithms */
/* The following values are for hardware AEC and studio quality
* microphone */
/* maximum NLMS filter length in taps. A longer filter length gives
* better Echo Cancellation, but slower convergence speed and
* needs more CPU power (Order of NLMS is linear) */
#define NLMS_LEN (80*8)
/* convergence speed. Range: >0 to <1 (0.2 to 0.7). Larger values give
* more AEC in lower frequencies, but less AEC in higher frequencies. */
const REAL Stepsize = 0.7f;
/* minimum energy in xf. Range: M70dB_PCM to M50dB_PCM. Should be equal
* to microphone ambient Noise level */
const REAL Min_xf = M75dB_PCM;
/* Double Talk Detector Speaker/Microphone Threshold. Range <=1
* Large value (M0dB) is good for Single-Talk Echo cancellation,
* small value (M12dB) is good for Doulbe-Talk AEC */
const REAL GeigelThreshold = M6dB;
/* Double Talk Detector hangover in taps. Not relevant for Single-Talk
* AEC */
const int Thold = 30 * 8;
/* for Non Linear Processor. Range >0 to 1. Large value (M0dB) is good
* for Double-Talk, small value (M12dB) is good for Single-Talk */
const REAL NLPAttenuation = M12dB;
/* Below this line there are no more design constants */
/* Exponential Smoothing or IIR Infinite Impulse Response Filter */
class IIR_HP {
REAL x;
public:
IIR_HP() { x = 0.0f; };
REAL highpass(REAL in) {
const REAL a0 = 0.01f; /* controls Transfer Frequency */
/* Highpass = Signal - Lowpass. Lowpass = Exponential Smoothing */
x += a0 * (in - x);
return in - x;
};
};
/* 13 taps FIR Finite Impulse Response filter
* Coefficients calculated with
* www.dsptutor.freeuk.com/KaiserFilterDesign/KaiserFilterDesign.html
*/
class FIR_HP13 {
REAL z[14];
public:
FIR_HP13() { memset(this, 0, sizeof(FIR_HP13)); };
REAL highpass(REAL in) {
const REAL a[14] = {
// Kaiser Window FIR Filter, Filter type: High pass
// Passband: 300.0 - 4000.0 Hz, Order: 12
// Transition band: 100.0 Hz, Stopband attenuation: 10.0 dB
-0.043183226f, -0.046636667f, -0.049576525f, -0.051936015f,
-0.053661242f, -0.054712527f, 0.82598513f, -0.054712527f,
-0.053661242f, -0.051936015f, -0.049576525f, -0.046636667f,
-0.043183226f, 0.0f
};
memmove(z+1, z, 13*sizeof(REAL));
z[0] = in;
REAL sum0 = 0.0, sum1 = 0.0;
int j;
for (j = 0; j < 14; j+= 2) {
// optimize: partial loop unrolling
sum0 += a[j] * z[j];
sum1 += a[j+1] * z[j+1];
}
return sum0+sum1;
}
};
/* Recursive single pole IIR Infinite Impulse response filter
* Coefficients calculated with
* http://www.dsptutor.freeuk.com/IIRFilterDesign/IIRFiltDes102.html
*/
class IIR1 {
REAL x, y;
public:
IIR1() { memset(this, 0, sizeof(IIR1)); };
REAL highpass(REAL in) {
// Chebyshev IIR filter, Filter type: HP
// Passband: 3700 - 4000.0 Hz
// Passband ripple: 1.5 dB, Order: 1
const REAL a0 = 0.105831884f;
const REAL a1 = -0.105831884;
const REAL b1 = 0.78833646f;
REAL out = a0 * in + a1 * x + b1 * y;
x = in;
y = out;
return out;
}
};
/* Recursive two pole IIR Infinite Impulse Response filter
* Coefficients calculated with
* http://www.dsptutor.freeuk.com/IIRFilterDesign/IIRFiltDes102.html
*/
class IIR2 {
REAL x[2], y[2];
public:
IIR2() { memset(this, 0, sizeof(IIR2)); };
REAL highpass(REAL in) {
// Butterworth IIR filter, Filter type: HP
// Passband: 2000 - 4000.0 Hz, Order: 2
const REAL a[] = { 0.29289323f, -0.58578646f, 0.29289323f };
const REAL b[] = { 1.3007072E-16f, 0.17157288f };
REAL out =
a[0] * in +
a[1] * x[0] +
a[2] * x[1] -
b[0] * y[0] -
b[1] * y[1];
x[1] = x[0];
x[0] = in;
y[1] = y[0];
y[0] = out;
return out;
}
};
// Extention in taps to reduce mem copies
#define NLMS_EXT (10*8)
// block size in taps to optimize DTD calculation
#define DTD_LEN 16
class AEC {
// Time domain Filters
IIR_HP hp00, hp1; // DC-level remove Highpass)
FIR_HP13 hp0; // 300Hz cut-off Highpass
IIR1 Fx, Fe; // pre-whitening Highpass for x, e
// Geigel DTD (Double Talk Detector)
REAL max_max_x; // max(|x[0]|, .. |x[L-1]|)
int hangover;
// optimize: less calculations for max()
REAL max_x[NLMS_LEN / DTD_LEN];
int dtdCnt;
int dtdNdx;
// NLMS-pw
REAL x[NLMS_LEN + NLMS_EXT]; // tap delayed loudspeaker signal
REAL xf[NLMS_LEN + NLMS_EXT]; // pre-whitening tap delayed signal
REAL w[NLMS_LEN]; // tap weights
int j; // optimize: less memory copies
int lastupdate; // optimize: iterative dotp(x,x)
double dotp_xf_xf; // double to avoid loss of precision
double Min_dotp_xf_xf;
REAL s0avg;
public:
AEC();
/* Geigel Double-Talk Detector
*
* in d: microphone sample (PCM as REALing point value)
* in x: loudspeaker sample (PCM as REALing point value)
* return: 0 for no talking, 1 for talking
*/
int dtd(REAL d, REAL x);
/* Normalized Least Mean Square Algorithm pre-whitening (NLMS-pw)
* The LMS algorithm was developed by Bernard Widrow
* book: Widrow/Stearns, Adaptive Signal Processing, Prentice-Hall, 1985
*
* in mic: microphone sample (PCM as REALing point value)
* in spk: loudspeaker sample (PCM as REALing point value)
* in update: 0 for convolve only, 1 for convolve and update
* return: echo cancelled microphone sample
*/
REAL nlms_pw(REAL mic, REAL spk, int update);
/* Acoustic Echo Cancellation and Suppression of one sample
* in d: microphone signal with echo
* in x: loudspeaker signal
* return: echo cancelled microphone signal
*/
int AEC::doAEC(int d, int x);
float AEC::getambient() {
return s0avg;
};
void AEC::setambient(float Min_xf) {
dotp_xf_xf = Min_dotp_xf_xf = NLMS_LEN * Min_xf * Min_xf;
};
};
#define _AEC_H
#endif
/***************** A.2 APPENDIX aec.cpp *****************/
/* aec.cpp
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Acoustic Echo Cancellation NLMS-pw algorithm
*
* Version 1.3 filter created with www.dsptutor.freeuk.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
/* Vector Dot Product */
REAL dotp(REAL a[], REAL b[]) {
REAL sum0 = 0.0, sum1 = 0.0;
int j;
for (j = 0; j < NLMS_LEN; j+= 2) {
// optimize: partial loop unrolling
sum0 += a[j] * b[j];
sum1 += a[j+1] * b[j+1];
}
return sum0+sum1;
}
AEC::AEC()
{
max_max_x = 0.0f;
hangover = 0;
memset(max_x, 0, sizeof(max_x));
dtdCnt = dtdNdx = 0;
memset(x, 0, sizeof(x));
memset(xf, 0, sizeof(xf));
memset(w, 0, sizeof(w));
j = NLMS_EXT;
lastupdate = 0;
s0avg = M80dB_PCM;
setambient(Min_xf);
}
REAL AEC::nlms_pw(REAL mic, REAL spk, int update)
{
REAL d = mic; // desired signal
x[j] = spk;
xf[j] = Fx.highpass(spk); // pre-whitening of x
// calculate error value
// (mic signal - estimated mic signal from spk signal)
REAL e = d - dotp(w, x + j);
REAL ef = Fe.highpass(e); // pre-whitening of e
// optimize: iterative dotp(xf, xf)
dotp_xf_xf += (xf[j]*xf[j] - xf[j+NLMS_LEN-1]*xf[j+NLMS _LEN-1]);
if (update) {
// calculate variable step size
REAL mikro_ef = Stepsize * ef / dotp_xf_xf;
// update tap weights (filter learning)
int i;
for (i = 0; i < NLMS_LEN; i += 2) {
// optimize: partial loop unrolling
w[i] += mikro_ef*xf[i+j];
w[i+1] += mikro_ef*xf[i+j+1];
}
}
if (--j < 0) {
// optimize: decrease number of memory copies
j = NLMS_EXT;
memmove(x+j+1, x, (NLMS_LEN-1)*sizeof(REAL)) ;
memmove(xf+j+1, xf, (NLMS_LEN-1)*sizeof(REAL)) ;
}
return e;
}
int AEC::dtd(REAL d, REAL x)
{
// optimized implementation of max(|x[0]|, |x[1]|, .., |x[L-1]|):
// calculate max of block (DTD_LEN values)
x = fabsf(x);
if (x > max_x[dtdNdx]) {
max_x[dtdNdx] = x;
if (x > max_max_x) {
max_max_x = x;
}
}
if (++dtdCnt >= DTD_LEN) {
dtdCnt = 0;
// calculate max of max
max_max_x = 0.0f;
for (int i = 0; i < NLMS_LEN/DTD_LEN; ++i) {
if (max_x[i] > max_max_x) {
max_max_x = max_x[i];
}
}
// rotate Ndx
if (++dtdNdx >= NLMS_LEN/DTD_LEN) dtdNdx = 0;
max_x[dtdNdx] = 0.0f;
}
// The Geigel DTD algorithm with Hangover timer Thold
if (fabsf(d) >= GeigelThreshold * max_max_x) {
hangover = Thold;
}
if (hangover) --hangover;
return (hangover > 0);
}
int AEC::doAEC(int d, int x)
{
REAL s0 = (REAL)d;
REAL s1 = (REAL)x;
// Mic Highpass Filter - to remove DC
s0 = hp00.highpass(s0);
// Mic Highpass Filter - telephone users are used to 300Hz cut-off
s0 = hp0.highpass(s0);
// ambient mic level estimation
s0avg += 1e-4f*(fabsf(s0) - s0avg);
// Spk Highpass Filter - to remove DC
s1 = hp1.highpass(s1);
// Double Talk Detector
int update = !dtd(s0, s1);
// Acoustic Echo Cancellation
s0 = nlms_pw(s0, s1, update);
// Acoustic Echo Suppression
if (update) {
// Non Linear Processor (NLP): attenuate low volumes
s0 *= NLPAttenuation;
}
// Saturation
if (s0 > MAXPCM) {
return (int)MAXPCM;
} else if (s0 < -MAXPCM) {
return (int)-MAXPCM;
} else {
return (int)roundf(s0);
}
}
/***************** A.3 APPENDIX aec_test.cpp *****************/
/* aec_test.cpp
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Test stub for Acoustic Echo Cancellation NLMS-pw algorithm
* Author: Andre Adrian, DFS Deutsche Flugsicherung
* <Andre.Adrian@dfs.de>
*
* compile
c++ -O2 -o aec_test aec_test.cpp aec.cpp -lm
*
* Version 1.3 set/get ambient in dB
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
#define TAPS (80*8)
typedef signed short MONO;
typedef struct {
signed short l;
signed short r;
} STEREO;
float dB2q(float dB)
{
/* Dezibel to Ratio */
return powf(10.0f, dB / 20.0f);
}
float q2dB(float q)
{
/* Ratio to Dezibel */
return 20.0f * log10f(q);
}
/* Read a raw audio file (8KHz sample frequency, 16bit PCM, stereo)
* from stdin, echo cancel it and write it to stdout
*/
int main(int argc, char *argv[])
{
STEREO inbuf[TAPS], outbuf[TAPS];
fprintf(stderr, "usage: aec_test [ambient in dB] <in.raw >out.raw\n");
AEC aec;
if (argc >= 2) {
aec.setambient(MAXPCM*dB2q (atof(argv [1])));
}
int taps;
while (taps = fread(inbuf, sizeof(STEREO), TAPS, stdin)) {
int i;
for (i = 0; i < taps; ++i) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
fwrite(outbuf, sizeof(STEREO), taps, stdout);
}
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0f);
fprintf(stderr, "Ambient = %2.0f dB\n", ambientdB);
fflush(NULL);
return 0;
}
thanks
dervis
Appendix A. The C++ Source Code
/***************** A.1 APPENDIX aec.h *****************/
/* aec.h
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Acoustic Echo Cancellation NLMS-pw algorithm
*
* Version 1.3 filter created with www.dsptutor.freeuk.com
*/
#ifndef _AEC_H /* include only once */
// use double if your CPU does software-emulation of float
typedef float REAL;
/* dB Values */
const REAL M0dB = 1.0f;
const REAL M3dB = 0.71f;
const REAL M6dB = 0.50f;
const REAL M9dB = 0.35f;
const REAL M12dB = 0.25f;
const REAL M18dB = 0.125f;
const REAL M24dB = 0.063f;
/* dB values for 16bit PCM */
/* MxdB_PCM = 32767 * 10 ^(x / 20) */
const REAL M10dB_PCM = 10362.0f;
const REAL M20dB_PCM = 3277.0f;
const REAL M25dB_PCM = 1843.0f;
const REAL M30dB_PCM = 1026.0f;
const REAL M35dB_PCM = 583.0f;
const REAL M40dB_PCM = 328.0f;
const REAL M45dB_PCM = 184.0f;
const REAL M50dB_PCM = 104.0f;
const REAL M55dB_PCM = 58.0f;
const REAL M60dB_PCM = 33.0f;
const REAL M65dB_PCM = 18.0f;
const REAL M70dB_PCM = 10.0f;
const REAL M75dB_PCM = 6.0f;
const REAL M80dB_PCM = 3.0f;
const REAL M85dB_PCM = 2.0f;
const REAL M90dB_PCM = 1.0f;
const REAL MAXPCM = 32767.0f;
/* Design constants (Change to fine tune the algorithms */
/* The following values are for hardware AEC and studio quality
* microphone */
/* maximum NLMS filter length in taps. A longer filter length gives
* better Echo Cancellation, but slower convergence speed and
* needs more CPU power (Order of NLMS is linear) */
#define NLMS_LEN (80*8)
/* convergence speed. Range: >0 to <1 (0.2 to 0.7). Larger values give
* more AEC in lower frequencies, but less AEC in higher frequencies. */
const REAL Stepsize = 0.7f;
/* minimum energy in xf. Range: M70dB_PCM to M50dB_PCM. Should be equal
* to microphone ambient Noise level */
const REAL Min_xf = M75dB_PCM;
/* Double Talk Detector Speaker/Microphone Threshold. Range <=1
* Large value (M0dB) is good for Single-Talk Echo cancellation,
* small value (M12dB) is good for Doulbe-Talk AEC */
const REAL GeigelThreshold = M6dB;
/* Double Talk Detector hangover in taps. Not relevant for Single-Talk
* AEC */
const int Thold = 30 * 8;
/* for Non Linear Processor. Range >0 to 1. Large value (M0dB) is good
* for Double-Talk, small value (M12dB) is good for Single-Talk */
const REAL NLPAttenuation = M12dB;
/* Below this line there are no more design constants */
/* Exponential Smoothing or IIR Infinite Impulse Response Filter */
class IIR_HP {
REAL x;
public:
IIR_HP() { x = 0.0f; };
REAL highpass(REAL in) {
const REAL a0 = 0.01f; /* controls Transfer Frequency */
/* Highpass = Signal - Lowpass. Lowpass = Exponential Smoothing */
x += a0 * (in - x);
return in - x;
};
};
/* 13 taps FIR Finite Impulse Response filter
* Coefficients calculated with
* www.dsptutor.freeuk.com/KaiserFilterDesign/KaiserFilterDesign.html
*/
class FIR_HP13 {
REAL z[14];
public:
FIR_HP13() { memset(this, 0, sizeof(FIR_HP13)); };
REAL highpass(REAL in) {
const REAL a[14] = {
// Kaiser Window FIR Filter, Filter type: High pass
// Passband: 300.0 - 4000.0 Hz, Order: 12
// Transition band: 100.0 Hz, Stopband attenuation: 10.0 dB
-0.043183226f, -0.046636667f, -0.049576525f, -0.051936015f,
-0.053661242f, -0.054712527f, 0.82598513f, -0.054712527f,
-0.053661242f, -0.051936015f, -0.049576525f, -0.046636667f,
-0.043183226f, 0.0f
};
memmove(z+1, z, 13*sizeof(REAL));
z[0] = in;
REAL sum0 = 0.0, sum1 = 0.0;
int j;
for (j = 0; j < 14; j+= 2) {
// optimize: partial loop unrolling
sum0 += a[j] * z[j];
sum1 += a[j+1] * z[j+1];
}
return sum0+sum1;
}
};
/* Recursive single pole IIR Infinite Impulse response filter
* Coefficients calculated with
* http://www.dsptutor.freeuk.com/IIRFilterDesign/IIRFiltDes102.html
*/
class IIR1 {
REAL x, y;
public:
IIR1() { memset(this, 0, sizeof(IIR1)); };
REAL highpass(REAL in) {
// Chebyshev IIR filter, Filter type: HP
// Passband: 3700 - 4000.0 Hz
// Passband ripple: 1.5 dB, Order: 1
const REAL a0 = 0.105831884f;
const REAL a1 = -0.105831884;
const REAL b1 = 0.78833646f;
REAL out = a0 * in + a1 * x + b1 * y;
x = in;
y = out;
return out;
}
};
/* Recursive two pole IIR Infinite Impulse Response filter
* Coefficients calculated with
* http://www.dsptutor.freeuk.com/IIRFilterDesign/IIRFiltDes102.html
*/
class IIR2 {
REAL x[2], y[2];
public:
IIR2() { memset(this, 0, sizeof(IIR2)); };
REAL highpass(REAL in) {
// Butterworth IIR filter, Filter type: HP
// Passband: 2000 - 4000.0 Hz, Order: 2
const REAL a[] = { 0.29289323f, -0.58578646f, 0.29289323f };
const REAL b[] = { 1.3007072E-16f, 0.17157288f };
REAL out =
a[0] * in +
a[1] * x[0] +
a[2] * x[1] -
b[0] * y[0] -
b[1] * y[1];
x[1] = x[0];
x[0] = in;
y[1] = y[0];
y[0] = out;
return out;
}
};
// Extention in taps to reduce mem copies
#define NLMS_EXT (10*8)
// block size in taps to optimize DTD calculation
#define DTD_LEN 16
class AEC {
// Time domain Filters
IIR_HP hp00, hp1; // DC-level remove Highpass)
FIR_HP13 hp0; // 300Hz cut-off Highpass
IIR1 Fx, Fe; // pre-whitening Highpass for x, e
// Geigel DTD (Double Talk Detector)
REAL max_max_x; // max(|x[0]|, .. |x[L-1]|)
int hangover;
// optimize: less calculations for max()
REAL max_x[NLMS_LEN / DTD_LEN];
int dtdCnt;
int dtdNdx;
// NLMS-pw
REAL x[NLMS_LEN + NLMS_EXT]; // tap delayed loudspeaker signal
REAL xf[NLMS_LEN + NLMS_EXT]; // pre-whitening tap delayed signal
REAL w[NLMS_LEN]; // tap weights
int j; // optimize: less memory copies
int lastupdate; // optimize: iterative dotp(x,x)
double dotp_xf_xf; // double to avoid loss of precision
double Min_dotp_xf_xf;
REAL s0avg;
public:
AEC();
/* Geigel Double-Talk Detector
*
* in d: microphone sample (PCM as REALing point value)
* in x: loudspeaker sample (PCM as REALing point value)
* return: 0 for no talking, 1 for talking
*/
int dtd(REAL d, REAL x);
/* Normalized Least Mean Square Algorithm pre-whitening (NLMS-pw)
* The LMS algorithm was developed by Bernard Widrow
* book: Widrow/Stearns, Adaptive Signal Processing, Prentice-Hall, 1985
*
* in mic: microphone sample (PCM as REALing point value)
* in spk: loudspeaker sample (PCM as REALing point value)
* in update: 0 for convolve only, 1 for convolve and update
* return: echo cancelled microphone sample
*/
REAL nlms_pw(REAL mic, REAL spk, int update);
/* Acoustic Echo Cancellation and Suppression of one sample
* in d: microphone signal with echo
* in x: loudspeaker signal
* return: echo cancelled microphone signal
*/
int AEC::doAEC(int d, int x);
float AEC::getambient() {
return s0avg;
};
void AEC::setambient(float Min_xf) {
dotp_xf_xf = Min_dotp_xf_xf = NLMS_LEN * Min_xf * Min_xf;
};
};
#define _AEC_H
#endif
/***************** A.2 APPENDIX aec.cpp *****************/
/* aec.cpp
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Acoustic Echo Cancellation NLMS-pw algorithm
*
* Version 1.3 filter created with www.dsptutor.freeuk.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
/* Vector Dot Product */
REAL dotp(REAL a[], REAL b[]) {
REAL sum0 = 0.0, sum1 = 0.0;
int j;
for (j = 0; j < NLMS_LEN; j+= 2) {
// optimize: partial loop unrolling
sum0 += a[j] * b[j];
sum1 += a[j+1] * b[j+1];
}
return sum0+sum1;
}
AEC::AEC()
{
max_max_x = 0.0f;
hangover = 0;
memset(max_x, 0, sizeof(max_x));
dtdCnt = dtdNdx = 0;
memset(x, 0, sizeof(x));
memset(xf, 0, sizeof(xf));
memset(w, 0, sizeof(w));
j = NLMS_EXT;
lastupdate = 0;
s0avg = M80dB_PCM;
setambient(Min_xf);
}
REAL AEC::nlms_pw(REAL mic, REAL spk, int update)
{
REAL d = mic; // desired signal
x[j] = spk;
xf[j] = Fx.highpass(spk); // pre-whitening of x
// calculate error value
// (mic signal - estimated mic signal from spk signal)
REAL e = d - dotp(w, x + j);
REAL ef = Fe.highpass(e); // pre-whitening of e
// optimize: iterative dotp(xf, xf)
dotp_xf_xf += (xf[j]*xf[j] - xf[j+NLMS_LEN-1]*xf[j+NLMS
if (update) {
// calculate variable step size
REAL mikro_ef = Stepsize * ef / dotp_xf_xf;
// update tap weights (filter learning)
int i;
for (i = 0; i < NLMS_LEN; i += 2) {
// optimize: partial loop unrolling
w[i] += mikro_ef*xf[i+j];
w[i+1] += mikro_ef*xf[i+j+1];
}
}
if (--j < 0) {
// optimize: decrease number of memory copies
j = NLMS_EXT;
memmove(x+j+1, x, (NLMS_LEN-1)*sizeof(REAL))
memmove(xf+j+1, xf, (NLMS_LEN-1)*sizeof(REAL))
}
return e;
}
int AEC::dtd(REAL d, REAL x)
{
// optimized implementation of max(|x[0]|, |x[1]|, .., |x[L-1]|):
// calculate max of block (DTD_LEN values)
x = fabsf(x);
if (x > max_x[dtdNdx]) {
max_x[dtdNdx] = x;
if (x > max_max_x) {
max_max_x = x;
}
}
if (++dtdCnt >= DTD_LEN) {
dtdCnt = 0;
// calculate max of max
max_max_x = 0.0f;
for (int i = 0; i < NLMS_LEN/DTD_LEN; ++i) {
if (max_x[i] > max_max_x) {
max_max_x = max_x[i];
}
}
// rotate Ndx
if (++dtdNdx >= NLMS_LEN/DTD_LEN) dtdNdx = 0;
max_x[dtdNdx] = 0.0f;
}
// The Geigel DTD algorithm with Hangover timer Thold
if (fabsf(d) >= GeigelThreshold * max_max_x) {
hangover = Thold;
}
if (hangover) --hangover;
return (hangover > 0);
}
int AEC::doAEC(int d, int x)
{
REAL s0 = (REAL)d;
REAL s1 = (REAL)x;
// Mic Highpass Filter - to remove DC
s0 = hp00.highpass(s0);
// Mic Highpass Filter - telephone users are used to 300Hz cut-off
s0 = hp0.highpass(s0);
// ambient mic level estimation
s0avg += 1e-4f*(fabsf(s0) - s0avg);
// Spk Highpass Filter - to remove DC
s1 = hp1.highpass(s1);
// Double Talk Detector
int update = !dtd(s0, s1);
// Acoustic Echo Cancellation
s0 = nlms_pw(s0, s1, update);
// Acoustic Echo Suppression
if (update) {
// Non Linear Processor (NLP): attenuate low volumes
s0 *= NLPAttenuation;
}
// Saturation
if (s0 > MAXPCM) {
return (int)MAXPCM;
} else if (s0 < -MAXPCM) {
return (int)-MAXPCM;
} else {
return (int)roundf(s0);
}
}
/***************** A.3 APPENDIX aec_test.cpp *****************/
/* aec_test.cpp
*
* Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
*
* Test stub for Acoustic Echo Cancellation NLMS-pw algorithm
* Author: Andre Adrian, DFS Deutsche Flugsicherung
* <Andre.Adrian@dfs.de>
*
* compile
c++ -O2 -o aec_test aec_test.cpp aec.cpp -lm
*
* Version 1.3 set/get ambient in dB
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "aec.h"
#define TAPS (80*8)
typedef signed short MONO;
typedef struct {
signed short l;
signed short r;
} STEREO;
float dB2q(float dB)
{
/* Dezibel to Ratio */
return powf(10.0f, dB / 20.0f);
}
float q2dB(float q)
{
/* Ratio to Dezibel */
return 20.0f * log10f(q);
}
/* Read a raw audio file (8KHz sample frequency, 16bit PCM, stereo)
* from stdin, echo cancel it and write it to stdout
*/
int main(int argc, char *argv[])
{
STEREO inbuf[TAPS], outbuf[TAPS];
fprintf(stderr, "usage: aec_test [ambient in dB] <in.raw >out.raw\n");
AEC aec;
if (argc >= 2) {
aec.setambient(MAXPCM*dB2q
}
int taps;
while (taps = fread(inbuf, sizeof(STEREO), TAPS, stdin)) {
int i;
for (i = 0; i < taps; ++i) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
fwrite(outbuf, sizeof(STEREO), taps, stdout);
}
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0f);
fprintf(stderr, "Ambient = %2.0f dB\n", ambientdB);
fflush(NULL);
return 0;
}
thanks
dervis
And what Java code do you have atm ? Where do your current problems lie ?
ASKER
i convert line by line into java. Now i cant organize whoole java code.
and the last part ,test part, i cant do it.
do u think it is very difficult?
up to monday(tomorrow) i have to finish due to graduate.otherwise i will fail:(
thanks
and the last part ,test part, i cant do it.
do u think it is very difficult?
up to monday(tomorrow) i have to finish due to graduate.otherwise i will fail:(
thanks
So, you've got the C++ classes converted to Java, and they're working ?
For the main() part in the C++ code, here's a start for you :
class AECTest {
/* Read a raw audio file (8KHz sample frequency, 16bit PCM, stereo)
* from stdin, echo cancel it and write it to stdout
*/
public static void main(String[] args) {
// TODO : define these two arrays : inbuf[TAPS], outbuf[TAPS] depending on how you defined STEREO in your code
if (args.length != 3) {
System.err.println("usage: AECTest [ambient in dB] in.raw out.raw\n");
return;
}
AEC aec = new AEC(); // the AEC class you already converted to Java
aec.setambient(MAXPCM * dB2q(Float.parseFloat(args [0])));
int taps;
FileInputStream inFileStream = new FileInputStream(args[1]);
DataInputStream inDataStream = new DataInputStream(inFileStre am);
FileOutputStream outFileStream = new FileOutputStream(args[2]);
DataOutputStream outDataStream = new DataOutputStream(outFileSt ream);
while (inDataStream.available() !=0) {
byte [] inbuf_bytes = new byte[TAPS * 4];
inDataStream.readFully(inb uf_bytes, 0, TAPS * 4);
// TODO : store number of actually read taps in the taps variable !! Use try-catch mechanism to catch exceptions !!
// TODO : convert the inbuf_bytes buffer to an array of STEREO (inbuf buffer)
int i;
for (i = 0; i < taps; i++) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
// TODO : convert the outbuf buffer to an array of bytes (outbuf_bytes buffer)
byte [] outbuf_bytes = new byte[taps * 4];
outDataStream.write(outbuf _bytes, 0, taps * 4);
// TODO : catch exceptions !!
}
inDataStream.close();
inFileStream.close();
outDataStream.close();
outFileStream.close();
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0);
System.err.println("Ambien t = " + ambientdB + " dB");
return;
}
public static float dB2q(float dB) {
/* Dezibel to Ratio */
return Math.pow(10.0, dB / 20.0);
}
public static float q2dB(float q) {
/* Ratio to Dezibel */
return 20.0 * (Math.log(q) / Math.log(10));
}
}
There's still some work for you to do, clearly marked by
// TODO : ...
And you should add exception handling where needed. Btw, this code is NOT tested, so you'll probably get some compiler errors, but I'm sure you can handle those ...
For the main() part in the C++ code, here's a start for you :
class AECTest {
/* Read a raw audio file (8KHz sample frequency, 16bit PCM, stereo)
* from stdin, echo cancel it and write it to stdout
*/
public static void main(String[] args) {
// TODO : define these two arrays : inbuf[TAPS], outbuf[TAPS] depending on how you defined STEREO in your code
if (args.length != 3) {
System.err.println("usage:
return;
}
AEC aec = new AEC(); // the AEC class you already converted to Java
aec.setambient(MAXPCM * dB2q(Float.parseFloat(args
int taps;
FileInputStream inFileStream = new FileInputStream(args[1]);
DataInputStream inDataStream = new DataInputStream(inFileStre
FileOutputStream outFileStream = new FileOutputStream(args[2]);
DataOutputStream outDataStream = new DataOutputStream(outFileSt
while (inDataStream.available() !=0) {
byte [] inbuf_bytes = new byte[TAPS * 4];
inDataStream.readFully(inb
// TODO : store number of actually read taps in the taps variable !! Use try-catch mechanism to catch exceptions !!
// TODO : convert the inbuf_bytes buffer to an array of STEREO (inbuf buffer)
int i;
for (i = 0; i < taps; i++) {
int s0 = inbuf[i].l; /* left channel microphone */
int s1 = inbuf[i].r; /* right channel speaker */
/* and do NLMS */
s0 = aec.doAEC(s0, s1);
/* copy back */
outbuf[i].l = 0; /* left channel silence */
outbuf[i].r = s0; /* right channel echo cancelled mic */
}
// TODO : convert the outbuf buffer to an array of bytes (outbuf_bytes buffer)
byte [] outbuf_bytes = new byte[taps * 4];
outDataStream.write(outbuf
// TODO : catch exceptions !!
}
inDataStream.close();
inFileStream.close();
outDataStream.close();
outFileStream.close();
float ambient = aec.getambient();
float ambientdB = q2dB(ambient / 32767.0);
System.err.println("Ambien
return;
}
public static float dB2q(float dB) {
/* Dezibel to Ratio */
return Math.pow(10.0, dB / 20.0);
}
public static float q2dB(float q) {
/* Ratio to Dezibel */
return 20.0 * (Math.log(q) / Math.log(10));
}
}
There's still some work for you to do, clearly marked by
// TODO : ...
And you should add exception handling where needed. Btw, this code is NOT tested, so you'll probably get some compiler errors, but I'm sure you can handle those ...
ASKER
Infinity08 you are very helpful expert. thanks for all your help.
This is a perfect answer and very good reference for me.
Be happy and succesfull.
After i finish i will post the whole code and add your name :)
Again thank you very much.
Best regards
Dervis
This is a perfect answer and very good reference for me.
Be happy and succesfull.
After i finish i will post the whole code and add your name :)
Again thank you very much.
Best regards
Dervis
Good luck with your project !
ASKER
i really try lots of times but i cant do it.
// TODO : define these two arrays : inbuf[TAPS], outbuf[TAPS] depending on how you defined STEREO in your code
STEREO [] inbuf = new STEREO [TAPS] ;
STEREO [] outbuf= new STEREO [TAPS] ;
others still remain.
no good book or sth. to learn by myself.
// TODO : define these two arrays : inbuf[TAPS], outbuf[TAPS] depending on how you defined STEREO in your code
STEREO [] inbuf = new STEREO [TAPS] ;
STEREO [] outbuf= new STEREO [TAPS] ;
others still remain.
no good book or sth. to learn by myself.
// TODO : store number of actually read taps in the taps variable !! Use try-catch mechanism to catch exceptions !!
you can retrieve the length of an array easily to do this.
Catching exceptions is needed because readFully throws exceptions. Check the online Java API for more information :
http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataInputStream.html
// TODO : convert the inbuf_bytes buffer to an array of STEREO (inbuf buffer)
this depends on the way you defined STEREO ... you'll have to take 4 bytes at a time from the buffer, and put the corresponding l and r values in the STEREO array.
// TODO : convert the outbuf buffer to an array of bytes (outbuf_bytes buffer)
inverse operation of the previous
// TODO : catch exceptions !!
Same as earlier : exceptions need to be caught !
you can retrieve the length of an array easily to do this.
Catching exceptions is needed because readFully throws exceptions. Check the online Java API for more information :
http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataInputStream.html
// TODO : convert the inbuf_bytes buffer to an array of STEREO (inbuf buffer)
this depends on the way you defined STEREO ... you'll have to take 4 bytes at a time from the buffer, and put the corresponding l and r values in the STEREO array.
// TODO : convert the outbuf buffer to an array of bytes (outbuf_bytes buffer)
inverse operation of the previous
// TODO : catch exceptions !!
Same as earlier : exceptions need to be caught !