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
_______________________________________________
Pd-list@iem.at mailing list
UNSUBSCRIBE and account-management -> 
http://lists.puredata.info/listinfo/pd-list

Reply via email to