Florian,
Just gave your dry and wet sample a quick listen. It
sounds promising. I'm looking forward to giving it a
more serious run.
ron
--- Florian Schmidt <mista.tapas(a)gmx.net> wrote:
Hi,
i implemented a small convolution engine for jack..
grab it at
http://affenbande.org/~tapas/jack_convolve-0.0.1.tgz
untar
make
./jack_convolve responsefile.wav
It creates as many in/out ports as the response file
has channels. Uses
fftw3f and libsndfile. Will add libsamplerate
support in near future.
So for now, make sure the samplerate of jack and the
response file
match.
Here's a ca 1 sec 48khz (resampled from 96khz)
stereo response file of a
room:
http://affenbande.org/~tapas/FrontFacing%20TLM170.wav
It's from this package:
http://www.noisevault.com/index.php?page=3&action=file&file_id=130
which has 96khz responses..
Consumes ca. 25-30% cpu load on my 1.2ghz athlon at
jack buffer size 2048
[;)]
So there's plenty room for optimization (and some
return value checking
will be added too ;)).. If you know some tricks, let
me know.. The
sourcecode is pasted below for easier reference.
Flo
P.S.: thanks to mario lang for collaborating and
giving some hints
towards using fftw3f instead of fftw and some other
optimizations..
P.P.S.: oh yeah, example sound, here you go
[hydrogen dry then with
output of jack_convolve mixed to it]:
http://affenbande.org/~tapas/jack_conv_ex1.ogg
And here the convoluted signal alone:
http://affenbande.org/~tapas/jack_conv_ex2.ogg
P.P.S.: known issues:
- won't handle samplerate or buffersize changes
gracefully
- will bring your machine to a crawl ;)
jack_convolve.cc:
---------------
/*
Copyright (C) 2004 Florian Schmidt
This program is free software; you can
redistribute it and/or modify
it under the terms of the GNU Lesser General
Public License as published by
the Free Software Foundation; either version 2.1
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 Lesser General Public License for more
details.
You should have received a copy of the GNU
Lesser General Public License
along with this program; if not, write to the
Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
$Id: types_8h-source.html,v 1.1 2004/04/27
18:21:48 joq Exp $
*/
#include <jack/jack.h>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sndfile.h>
#include <vector>
#include <cmath>
#include <fftw3.h>
jack_client_t *client;
std::vector<jack_port_t *> iports;
std::vector<jack_port_t *> oports;
jack_nframes_t jack_buffer_size;
int chunks_per_channel;
// channel chunk data
std::vector<std::vector <fftwf_complex*> > chunks;
// the buffers for the fft
float *fft_float;
fftwf_complex *fft_complex;
// the plan
fftwf_plan fft_plan_forward;
fftwf_plan fft_plan_backward;
float normalize_factor;
// per channel we need a ringbuffer holding the fft
results of the
// audio periods passed to us by jackd.
// each needs to be sized jack_buffer_size *
chunks_per_channel (see main())
std::vector<fftwf_complex *> ringbuffers;
// this gets advanced by jack_buffer_size after each
process() callback
unsigned int ringbuffer_index = 0;
// a vector to hold the jack buffer pointers.. these
get resized
// during init in main
std::vector<jack_default_audio_sample_t *> ibuffers;
std::vector<jack_default_audio_sample_t *> obuffers;
// channel data
std::vector<jack_default_audio_sample_t *>overlaps;
int process(jack_nframes_t frames, void *arg) {
// std::cout << " " << ringbuffer_index;
// get pointer[s] to the buffer[s]
int channels = chunks.size();
for (int channel = 0; channel < channels;
++channel) {
ibuffers[channel] =
((jack_default_audio_sample_t*)jack_port_get_buffer(iports[channel],
frames));
obuffers[channel] =
((jack_default_audio_sample_t*)jack_port_get_buffer(oports[channel],
frames));
}
for (int channel = 0; channel < channels;
++channel) {
// copy input buffer to fft buffer
for (int frame = 0; frame < jack_buffer_size;
++frame) {
fft_float[frame] =
(float)(ibuffers[channel][frame]);
fft_float[frame+jack_buffer_size] = 0.0;
}
// fft the input[s]
fftwf_execute(fft_plan_forward);
// store the new result into the ringbuffer for
this channel
for (int frame = 0; frame < jack_buffer_size * 2;
++frame) {
ringbuffers[channel][ringbuffer_index+frame][0] =
fft_complex[frame][0] / normalize_factor;
ringbuffers[channel][ringbuffer_index+frame][1] =
fft_complex[frame][1] / normalize_factor;
}
// zero our buffer for the inverse FFT, so we can
simply += the
// values in the next step.
for (int frame = 0; frame < jack_buffer_size * 2;
++frame) {
fft_complex[frame][0] = 0;
fft_complex[frame][1] = 0;
}
=== message truncated ===
__________________________________
Do you Yahoo!?
Take Yahoo! Mail with you! Get it on your mobile phone.
http://mobile.yahoo.com/maildemo