Code:
#include "pa.h"
#include "tdoa.h"
#include "ds.h"
#include "parse-option.h"
#include <chrono>
using namespace std;
using namespace std::chrono;
struct paConfig
{
int channels;
int margin;
};
void paFunc(const float* in, float* out, long frames, void* data){
auto start = high_resolution_clock::now();
int num_channel = 2;
int margin = 6;
float *out_pcm = (float *)calloc(sizeof(float), frames);
int *tdoa = (int *)calloc(sizeof(int), num_channel);
// rearrange channel data
float *in_data = (float *)calloc(sizeof(float),
frames * num_channel);
float *beam_data = (float *)calloc(sizeof(float),
frames * num_channel);
for (int j = 0; j < num_channel; j++) {
for (int k = 0; k < frames; k++) {
in_data[j + k] = in[k * num_channel + j];
}
for (int k = 0; k < frames; k++) {
beam_data[j + k] = in[k * num_channel + j];
}
}
// calc delay
int tao = margin < frames / 2 ? margin : frames / 2;
GccPhatTdoa(in_data, num_channel, frames, 0, tao, tdoa);
for (int j = 0; j < num_channel; j++) {
printf("%d ", tdoa[j]);
}
printf("\n");
DelayAndSum(beam_data, num_channel, frames, tdoa, out_pcm);
float max = 0.0;
float average = 0.0;
for (int k = 0; k < frames; k++) {
out[k] = out_pcm[k];
float val = out_pcm[k];
if( val < 0 ) val = -val; /* ABS */
if( val > max )
{
max = val;
}
average += val;
}
average = average / (float)frames;
printf("sample max amplitude = %f\n", max );
printf("sample average = %f\n", average );
auto stop = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(stop - start);
printf("milliseconds = %ld\n", duration);
free(beam_data);
free(in_data);
free(out_pcm);
free(tdoa);
}
int main(int argc, char *argv[]) {
const char *usage = "Do delay and sum beamforming\n"
"Usage: apply-delay-and-sum input_device output_device\n";
ParseOptions po(usage);
int input_device = 1;
po.Register("input_device", &input_device,
"multichannel input device index");
int output_device = 1;
po.Register("output_device", &output_device,
"single channel output device index");
int frames = 4000;
po.Register("frames", &frames,
"frame buffer size");
int channels = 2;
po.Register("channels", &channels,
"mic input channels");
int margin = 16;
po.Register("margin", &margin,
"constraint for tdoa estimation");
int sample_rate = 44100;
po.Register("sample_rate", &sample_rate,
"sample rate");
po.Read(argc, argv);
//if (po.NumArgs() != 2) {
//po.PrintUsage();
//exit(1);
//}
struct paConfig config;
config.channels = channels;
config.margin = margin;
Pa a(paFunc, channels, 1, sample_rate, frames, NULL);
a.listDevices();
a.getDeviceInfo(input_device);
a.getDeviceInfo(output_device);
printf("input=%d output=%d frames=%d channels=%d margin=%d sample_rate=%d", input_device, output_device, frames, channels, margin, sample_rate);
a.setInputDevice(input_device);
a.setOutputDevice(output_device);
a.start(Pa::waitForKey);
return 0;
}
Currently the callback call has the userdata set to Null.