Re: [Jack-Devel] Introducing delay into simple_client.c

PrevNext  Index
DateFri, 02 Nov 2012 02:55:17 -0600
From Jason Martyn <[hidden] at gmail dot com>
To[hidden] at lists dot jackaudio dot org
In-Reply-ToJason Martyn Re: [Jack-Devel] Introducing delay into simple_client.c
Follow-UpPaul Davis 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
> >
> >
>
PrevNext  Index

1351846544.22266_0.ltw:2,a <CAMMKq3S=myruupii0QeHd_4+_7t60hgqiBy=ZpyzJ_kvgeRAEQ at mail dot gmail dot com>