Le lundi 23 février 2009 à 23:02 +0100, yohannes a écrit :
> hello everybody,
>
> maybe sounds absurd:
>
> is it possible to cancel an whole signal of an mic input through
> phase-canceling?
>
> if yes, how can i do dat in pd?
>
Hi yohannes,
maybe you are looking for something like an acoustic echo canceller.
Speex has one:
http://www.speex.org/docs/manual/speex-manual/node4.html#SECTION00450000000000000000
maec~.c is a more than ugly very first attempt for an external quickly
written to give speex a try.
I had quite good results, close to 20dB rejection, with only one micro
and only one speaker. Rejection is close to nothing with 2 speakers. As
I need a good rejection with 5 speakers I gave up.
All the best,
Joël
/*
*
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "m_pd.h"
#include "speex/speex_echo.h"
/* pd's samplerate */
float fs;
unsigned int frame_size = 64; // Pd block size;
unsigned int filter_length = 4410; // 100ms @ 44.1Kz
static t_class *maec_class;
typedef struct _maec
{
t_object x_obj;
t_float f;
} t_maec;
spx_int16_t *input_frame;
spx_int16_t *echo_frame;
spx_int16_t *output_frame;
spx_int16_t *deco_in, *deco_out;
SpeexEchoState *echo_state;
SpeexDecorrState *deco_state;
static t_int *maec_perform(t_int *w)
{
/* Achtung !!!
* inlet and outlet buffer share the same memory !!!
*/
int n, i, j;
n = (int)(w[15]);
t_maec *obj = (t_maec *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *echo = (t_float *)(w[3]);
t_float *in1 = (t_float *)(w[4]);
t_float *in2 = (t_float *)(w[5]);
t_float *in3 = (t_float *)(w[6]);
t_float *in4 = (t_float *)(w[7]);
t_float *in5 = (t_float *)(w[8]);
t_float *out = (t_float *)(w[9]);
t_float *out1 = (t_float *)(w[10]);
t_float *out2 = (t_float *)(w[11]);
t_float *out3 = (t_float *)(w[12]);
t_float *out4 = (t_float *)(w[13]);
t_float *out5 = (t_float *)(w[14]);
/*
for (i = 0, j = 0 ; i<n; i++) {
deco_in[j++] = (spx_int16_t) floorf(0x7fff * in1[i] + 0.5);
deco_in[j++] = (spx_int16_t) floorf(0x7fff * in2[i] + 0.5);
deco_in[j++] = (spx_int16_t) floorf(0x7fff * in3[i] + 0.5);
deco_in[j++] = (spx_int16_t) floorf(0x7fff * in4[i] + 0.5);
deco_in[j++] = (spx_int16_t) floorf(0x7fff * in5[i] + 0.5);
// echo_frame[i] =(spx_int16_t) floorf(0x7fff/5.0 * (in1[i]+in2[i]+in3[i]+in4[i]+in5[i] +0.5));
}
speex_decorrelate(deco_state, deco_in, deco_out, 50);
for (i=0, j=0; i<n; i++){
echo_frame[i] =(spx_int16_t) floorf((deco_out[j]+deco_out[j+1]+deco_out[j+2]+deco_out[j+3]+deco_out[j+4])/5.0) +0.5;
j+=5;
}*/
for (i = 0; i<n ; i++) {
input_frame[i] = (spx_int16_t) (floorf((32767.0 * in[i]) + 0.5));
echo_frame[i] = (spx_int16_t) (floorf((32767.0 * echo[i]) + 0.5));
}
speex_echo_cancellation(echo_state, input_frame, echo_frame, output_frame);
for (i = 0; i<n; i++) {
out[i] = (t_float) output_frame[i] / (float) 0x7fff;
}
/* for (i = 0, j = 0; i<n; i++) {
out1[i] = (t_float) deco_out[j++] / (float) 0x7fff;
out2[i] = (t_float) deco_out[j++] / (float) 0x7fff;
out3[i] = (t_float) deco_out[j++] / (float) 0x7fff;
out4[i] = (t_float) deco_out[j++] / (float) 0x7fff;
out5[i] = (t_float) deco_out[j++] / (float) 0x7fff;
// out5[i] = (t_float) echo_frame[i]/ (float) 0x7fff;
}*/
return (w+16);
}
static void maec_dsp(t_maec *x, t_signal **sp)
{
dsp_add(maec_perform, 15, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec,
sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, sp[9]->s_vec, sp[10]->s_vec, sp[11]->s_vec,
sp[12]->s_vec, sp[0]->s_n);
}
static void *maec_new(t_symbol *s, int argc, t_atom *argv)
{
t_maec *x = (t_maec *)pd_new(maec_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}
void maec_length(t_maec *x, t_float f)
{
speex_echo_state_reset(echo_state);
deco_state = speex_decorrelate_new(fs, 5, frame_size);
echo_state = speex_echo_state_init_mc(frame_size, f, 1, 1);
speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &fs);
post("%f/n", f);
}
void maec_tilde_setup(void)
{
fs = 44100; // sys_getsr();
maec_class = class_new(gensym("maec~"), (t_newmethod)maec_new, 0, sizeof(t_maec), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(maec_class, t_maec, f);
class_addmethod(maec_class, (t_method)maec_dsp, gensym("dsp"), 0);
class_addfloat(maec_class, (t_method)maec_length);
input_frame = getbytes(frame_size * sizeof(spx_int16_t));
echo_frame = getbytes(frame_size * sizeof(spx_int16_t));
output_frame = getbytes(frame_size * sizeof(spx_int16_t));
deco_in = getbytes(frame_size * 5 * sizeof(spx_int16_t));
deco_out = getbytes(frame_size * 5 * sizeof(spx_int16_t));
deco_state = speex_decorrelate_new(fs, 5, frame_size);
echo_state = speex_echo_state_init_mc(frame_size, filter_length, 1, 1);
speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &fs);
}
NAME=maec~
CSYM=maec~
current: pd_linux
# ----------------------- NT -----------------------
pd_nt: $(NAME).dll $(NAMEB).dll
.SUFFIXES: .dll
PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
VC="C:\Program Files\Microsoft Visual Studio\Vc98"
PDNTINCLUDE = /I. /I\tcl\include /I\ftp\pd\src /I$(VC)\include
PDNTLDIR = $(VC)\lib
PDNTLIB = $(PDNTLDIR)\libc.lib \
$(PDNTLDIR)\oldnames.lib \
$(PDNTLDIR)\kernel32.lib \
\ftp\pd\bin\pd.lib
.c.dll:
cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
# ----------------------- IRIX 5.x -----------------------
pd_irix5: $(NAME).pd_irix5 $(NAMEB).pd_irix5
.SUFFIXES: .pd_irix5
SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
SGIINCLUDE = -I../../src
.c.pd_irix5:
cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
rm $*.o
# ----------------------- IRIX 6.x -----------------------
pd_irix6: $(NAME).pd_irix6 $(NAMEB).pd_irix6
.SUFFIXES: .pd_irix6
SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
-Ofast=ip32
.c.pd_irix6:
cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
rm $*.o
# ----------------------- LINUX i386 -----------------------
pd_linux: $(NAME).pd_linux
.SUFFIXES: .pd_linux
LINUXCFLAGS = -g -I/usr/local/include -DPD -DUNIX -O2 -funroll-loops -fomit-frame-pointer \
-Wall -W -Wshadow -Wstrict-prototypes -fPIC \
-Wno-unused -Wno-parentheses -Wno-switch
LINUXINCLUDE = -I../../src
.c.pd_linux:
cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
ld -export_dynamic -shared -o $*.pd_linux $*.o -L/usr/local/lib -lc -lm -lspeexdsp
strip --strip-unneeded $*.pd_linux
rm -f $*.o ../$*.pd_linux
ln -s speex~/$*.pd_linux ..
# ----------------------------------------------------------
install:
cp help-*.pd ../../doc/5.reference
clean:
rm -f *.o *.pd_* so_locations
_______________________________________________
[email protected] mailing list
UNSUBSCRIBE and account-management ->
http://lists.puredata.info/listinfo/pd-list