Re: [Jack-Devel] Introducing delay into simple_client.c
Hello all,
Thanks again for the help. I've managed to put together an initial
solution, though this doesn't utilize ringbuffers yet. It is as follows:
//Counter variables
int i = 0;
int j = 0;
//Length of delay (i.e. size of audio buffer)
int n = 250;
//Audio buffer array
jack_default_audio_sample_t **prev;
int process (jack_nframes_t nframes, void *arg)
{
//Initialize audio buffer array
if( prev == NULL ){
prev = malloc(sizeof(jack_default_audio_sample_t *)*n);
for(i = 0; i < n; i++){
prev[i] = malloc(nframes*sizeof(jack_default_audio_sample_t));
}
i = 0;
}
//For the first n process callbacks, store the input to the audio buffer
and do not output anything
if (i<n){
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *)
jack_port_get_buffer (input_port, nframes);
memcpy (prev[i], in, sizeof (jack_default_audio_sample_t) *
nframes);
i++;
}
//For all proceeding callbacks, output starting from the beginning of
the audio buffer, and store new input into recently played output of the
audio buffer.
else {
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *)
jack_port_get_buffer (output_port, nframes);
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *)
jack_port_get_buffer (input_port, nframes);
memcpy (out, prev[j], sizeof (jack_default_audio_sample_t) * nframes);
memcpy (prev[j], in, sizeof (jack_default_audio_sample_t) * nframes);
j++;
if (j == n){ j = 0; } //reset j
}
return 0;
}
Jason
On Tue, Oct 30, 2012 at 11:02 AM, Jason Martyn <[hidden]> wrote:
> Thanks both,
>
> Robin: Actually, this makes perfect sense. I occasionally forget what
> pointers are actually doing :). As for the ringbuffer, I'll check it
> out. Thanks for the tip.
>
> Stéphane: Cool! And Stanford produced a users manual with examples.
> I'll check it out, but for the time being I'd like to see if I could
> implement something like this directly with JACK.
>
> I'll report back when I get something,
>
> Jason
>
> On Tue, Oct 30, 2012 at 3:27 AM, Stéphane Letz <[hidden]> wrote:
> >
> > Le 30 oct. 2012 à 10:17, Robin Gareus a écrit :
> >
> >> On 10/30/2012 07:59 AM, Jason Martyn wrote:
> >>> Hi everyone,
> >>>
> >>> I'm brand new to JACK and its implementation, so please bear with me.
> >>> I'm looking to modify the example script simple_client.c to introduce
> >>> a predetermined time delay from the input to the output. I.e.,
> >>> unmodified, simple_client.c simply copies the input to the output, and
> >>> instead, I would like to take the input, delay it by t seconds, and
> >>> then send it to the output.
> >>>
> >>> To do this, I thought I would declare an array of type
> >>> jack_default_audio_sample_t and then store the input into that array
> >>> until the critical time where it should start playing it to the
> >>> output. The new input then overwrites the old input by cycling through
> >>> the array from the beginning.
> >>>
> >>> Here's my process callback (with comments on my reasoning):
> >>>
> >>> //Initialize counting integers
> >>> int i = 0;
> >>> int j = 0;
> >>>
> >>> //Initialize storage array
> >>> jack_default_audio_sample_t *prev[200]; //Note: 200 is just a test
> number
> >>>
> >>> int process (jack_nframes_t nframes, void *arg)
> >>> {
> >>> //For the first 200 cycles, store input into array, don't output
> anything
> >>> if (i<200){
> >>>
> >>> prev[i] = (jack_default_audio_sample_t *) jack_port_get_buffer
> >>> (input_port, nframes);
> >>> i++;
> >>> }
> >>>
> >>> //For all following cycles, play the input, starting from the
> >>> beginning of the array
> >>> else {
> >>>
> >>> jack_default_audio_sample_t *out = (jack_default_audio_sample_t *)
> >>> jack_port_get_buffer (output_port, nframes);
> >>> memcpy (out, prev[j], sizeof (jack_default_audio_sample_t) *
> >>> nframes); //Note: j is the new counting variable
> >>>
> >>> //Overwrite recently played input with new input:
> >>> prev[j] = (jack_default_audio_sample_t *) jack_port_get_buffer
> >>> (input_port, nframes);
> >>> j++;
> >>>
> >>> //Reset array counter to 0 when it reaches the end
> >>> if (j = 200){ j = 0; } //reset j
> >>> }
> >>>
> >>> return 0;
> >>> }
> >>>
> >>> If this looks way off (as in I'm missing the point of how JACK, etc.
> >>> works), I'd appreciate any resources that might help me get started
> >>> with regards to understanding how this all works. I have gone through
> >>> the tutorials listed on the JACK site, and have a lot of troubles
> >>> trying to find anything else.
> >>>
> >>> Regards,
> >>> Jason
> >>
> >> Hi Jason,
> >>
> >> welcome aboard! The issue with above code is
> >> prev[i] = jack_port_get_buffer(..);
> >>
> >> The buffer returned by jack_port_get_buffer() is only valid for the
> >> current process cycle. You need to memcpy() that to a temp. queue.
> >>
> >> While easy in principle, things can get a bit complicated because the
> >> period size can change. When the delay-line buffer wraps-around and the
> >> delay-line buffer-size is not an exact multiple of the period-size, you
> >> will need two memcpy()s for writing and two for reading to make it
> seamless.
> >>
> >> While it's a good exercise to code that, the easiest way is to use
> >> libjack's ringbuffer which does exactly that:
> >> http://jackaudio.org/files/docs/html/ringbuffer_8h.html
> >>
> >> HTH,
> >> robin
> >
> >
> > Using Faust :
> >
> > process = @(1000); (here constant delay of 1000 samples)
> >
> > Using the online compiler: http://faust.grame.fr/, you can easily
> produce JACK based component...
> >
> > Stéphane
> >
> >
>
1351846544.22266_0.ltw:2,a <CAMMKq3S=myruupii0QeHd_4+_7t60hgqiBy=ZpyzJ_kvgeRAEQ at mail dot gmail dot com>