/*
cw_binaural~: a binaural synthesis external for pure data
by David Doukhan - david.doukhan@gmail.com - http://perso.limsi.fr/doukhan
and Anne Sedes - sedes.anne@gmail.com
Copyright (C) 2009-2011 David Doukhan and Anne Sedes
For more details, see CW_binaural~, a binaural synthesis external for Pure Data
David Doukhan and Anne Sedes, PDCON09
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "binaural_processor.hpp"
#include "logstring.hpp"
static t_class *cw_binaural_tilde_class;
typedef struct _cw_binaural_tilde
{
t_object x_obj;
BinauralProcessor *bp;
float default_input;
} t_cw_binaural_tilde;
t_int *cw_binaural_tilde_perform(t_int *w)
{
t_cw_binaural_tilde *x = (t_cw_binaural_tilde *)(w[1]);
// 3 signal input: signal, azimuth and elevation
t_sample *input = (t_sample *)(w[2]);
t_sample *azimuths = (t_sample *)(w[3]);
t_sample *elevations = (t_sample *)(w[4]);
// 2 signal outputs: for the left and right ear
t_sample *left_output = (t_sample *)(w[5]);
t_sample *right_output = (t_sample *)(w[6]);
int n = (int)(w[7]);
x->bp->process(input, azimuths, elevations, left_output, right_output, n);
return (w+8);
}
void cw_binaural_tilde_dsp(t_cw_binaural_tilde *x, t_signal **sp)
{
dsp_add(cw_binaural_tilde_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec,
sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec,
sp[0]->s_n);
}
// called when the message listen_db is sent to the object
void cw_binaural_set_listen_db(t_cw_binaural_tilde *x, t_symbol *hrtf_path)
{
try
{
x->bp->set_listen_db(string(hrtf_path->s_name));
}
catch (int n) {}
logstring2pdterm();
}
// called when the message cipic_db is sent to the object
void cw_binaural_set_cipic_db(t_cw_binaural_tilde *x, t_symbol *hrtf_path)
{
try
{
x->bp->set_cipic_db(string(hrtf_path->s_name));
}
catch (int n) {}
logstring2pdterm();
}
// convert a symbol to boolean
static bool symb2bool(t_symbol* symb)
{
string s(symb->s_name);
for (size_t i = 0; i < s.length(); ++i)
s[i] = toupper(s[i]);
return s == "TRUE";
}
// called when the message sethrtf is sent to the object
// message allowing to load any hrtf database
// hrtf_path correspond to the path to the directory storing the hrtf as wav files
// fname_regex is a regex representing the name of files containing impulse responses
// it should contain a group for each parameter to extract (azimuth and elevation)
// az_first tells wether the first group corresponds to azimuth or not
// vertical_polar_coords is set to true if the database is expressed in vertical polar
// coordinates, if set to false, it refers interaural polar coordinates
void cw_binaural_set_hrtf_db(t_cw_binaural_tilde *x,
t_symbol *symb_hrtf_path,
t_symbol *symb_fname_regex,
t_symbol *symb_az_first,
t_symbol *symb_vertical_polar_coords)
{
string hrtf_path(symb_hrtf_path->s_name);
string fname_regex(symb_fname_regex->s_name);
bool az_first = symb2bool(symb_az_first);
bool vertical_polar_coords = symb2bool(symb_vertical_polar_coords);
// Pd does not allows to transmit backslashes in messages,
// so we replace each occurence of double slashes with a back slash
size_t found;
while ((found = fname_regex.find("//")) != string::npos)
fname_regex.replace(found, 2, 1, '\\');
try
{
x->bp->set_hrtf(hrtf_path, fname_regex, az_first, vertical_polar_coords);
}
catch (int n) {}
logstring2pdterm();
}
void cw_binaural_tilde_free(t_cw_binaural_tilde *x)
{
if (x->bp)
delete x->bp;
logstring2pdterm();
}
void *cw_binaural_tilde_new(t_symbol *obj_name, int argc, t_atom *argv)
{
// default creation arguments
int impulse_response_size = 128;
std::string filtering_method = std::string("RIFF");
std::string delay_method = std::string("Hermite4");
// parsing creation arguments
switch (argc < 3 ? argc : 3)
{
case 3:
delay_method = std::string(atom_getsymbol(argv + 2)->s_name);
case 2:
filtering_method = std::string(atom_getsymbol(argv + 1)->s_name);
case 1:
impulse_response_size = (int) atom_getfloat(argv);
default:
break;
}
// creating object
t_cw_binaural_tilde *x = (t_cw_binaural_tilde *)pd_new(cw_binaural_tilde_class);
x->default_input = 0;
x->bp = NULL;
try
{
// call to the constructor
x->bp = new BinauralProcessor(impulse_response_size, filtering_method, delay_method);
}
catch (int n)
{
x->bp = 0;
logstring2pdterm();
return (void*) 0;
}
// azimuth inlet
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
// elevation inlet
inlet_new(&x->x_obj , &x->x_obj.ob_pd, &s_signal, &s_signal);
// left outlet
outlet_new(&x->x_obj, &s_signal);
// right outlet
outlet_new(&x->x_obj, &s_signal);
logstring2pdterm();
return (void *)x;
}
extern "C"
#ifdef WIN32
__declspec(dllexport) void cw_binaural_tilde_setup(void)
#else
void cw_binaural_tilde_setup(void)
#endif
{
// creation of the cw_binaural~ instance
cw_binaural_tilde_class =
class_new(gensym("cw_binaural~"),
(t_newmethod)cw_binaural_tilde_new,
(t_method) cw_binaural_tilde_free, sizeof(t_cw_binaural_tilde),
CLASS_DEFAULT,
A_GIMME, 0);
// sound processing
class_addmethod(cw_binaural_tilde_class,
(t_method)cw_binaural_tilde_dsp, gensym("dsp"), (t_atomtype) 0);
// management of messages used to set a listen database
class_addmethod(cw_binaural_tilde_class,
(t_method)cw_binaural_set_listen_db,
gensym("listen_db"),
A_DEFSYMBOL, (t_atomtype) 0);
// management of messages used to set a CIPIC database
class_addmethod(cw_binaural_tilde_class,
(t_method)cw_binaural_set_cipic_db,
gensym("cipic_db"),
A_DEFSYMBOL, (t_atomtype) 0);
// management of messages used to set any database
class_addmethod(cw_binaural_tilde_class,
(t_method)cw_binaural_set_hrtf_db,
gensym("set_hrtf_db"),
A_DEFSYMBOL, A_DEFSYMBOL, A_DEFSYMBOL, A_DEFSYMBOL, (t_atomtype) 0);
CLASS_MAINSIGNALIN(cw_binaural_tilde_class, t_cw_binaural_tilde, default_input);
}