changing processing callback in a running client

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

changing processing callback in a running client

philippe-62
Hello jack users and developpers,

I'm yet to start my second jackd client, a volume/level adjust and
matrixing for multichannel HiFi, and want two functionailities in this
client:

- first a level calibration phase during which I send a pink noise to
the output, and measure the level via a microphone and the same jack
client that the signal sender.

- once done, I will collect stereo stream on two inputs, and do
"standard" DSP stuff on the signal, before sending it to the jack
client ouputs.

My question:

Am I better designing the two functionalities in the same process
callback and selecting them with an if, or,

Is there a facility inside jack to unregister a process callback
cleanly (without crashing anything, nor get a loud plop or hiss in the
speakers) ??

Thanks for the tip.

--
Ph. Strauss
_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

Paul Davis
On Thu, Aug 5, 2010 at 1:14 PM, philippe <[hidden email]> wrote:

> Am I better designing the two functionalities in the same process
> callback and selecting them with an if, or,
>
> Is there a facility inside jack to unregister a process callback
> cleanly (without crashing anything, nor get a loud plop or hiss in the
> speakers) ??

better with an if() but you can always set the callback to NULL and
then reset it again later.
_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

Gabriel M. Beddingfield-2
In reply to this post by philippe-62


On Thu, 5 Aug 2010, philippe wrote:

> - first a level calibration phase during which I send a pink noise to
> the output, and measure the level via a microphone and the same jack
> client that the signal sender.
>
> - once done, I will collect stereo stream on two inputs, and do
> "standard" DSP stuff on the signal, before sending it to the jack
> client ouputs.

So, if this were on a time-line.... you do the calibration
first (for a few seconds)... and after that you run your
regular program ("never" doing the calibration again)??

> My question:
>
> Am I better designing the two functionalities in the same process
> callback and selecting them with an if, or,

Maybe...

> Is there a facility inside jack to unregister a process callback
> cleanly (without crashing anything, nor get a loud plop or hiss in the
> speakers) ??

Yes.  You have to:

   1. De-activate your client (you lose all existing
      connections and you "disappear")

   2. Set the new process callback using the standard
      function.

   3. Activate your client.

Another option (which is just a glorified "if" statement) is
to internally use a function pointer for your callback.
When you need to change the callback, you do an atomic
pointer swap.

-gabriel

_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

Paul Davis
On Thu, Aug 5, 2010 at 1:27 PM, Gabriel M. Beddingfield
<[hidden email]> wrote:
> Another option (which is just a glorified "if" statement) is to internally
> use a function pointer for your callback. When you need to change the
> callback, you do an atomic pointer swap.

to clarify what gabriel means:

a) set the "actual" jack process callback to "foo"
b) within foo, execute (*a_pointer_to_the_secret_callback)(nframes, arg);
c) when needed, atomic swap a_pointer_to_the_secret_callback between
foo1 and foo2

--p
_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

philippe-62
In reply to this post by Gabriel M. Beddingfield-2
On Thu, Aug 5, 2010 at 7:27 PM, Gabriel M. Beddingfield
<[hidden email]> wrote:

>
>
> On Thu, 5 Aug 2010, philippe wrote:
>
>> - first a level calibration phase during which I send a pink noise to
>> the output, and measure the level via a microphone and the same jack
>> client that the signal sender.
>>
>> - once done, I will collect stereo stream on two inputs, and do
>> "standard" DSP stuff on the signal, before sending it to the jack
>> client ouputs.
>
> So, if this were on a time-line.... you do the calibration first (for a few
> seconds)... and after that you run your regular program ("never" doing the
> calibration again)??

exactly !

>> My question:
>>
>> Am I better designing the two functionalities in the same process
>> callback and selecting them with an if, or,
>
> Maybe...
>
>> Is there a facility inside jack to unregister a process callback
>> cleanly (without crashing anything, nor get a loud plop or hiss in the
>> speakers) ??
>
> Yes.  You have to:
>
>  1. De-activate your client (you lose all existing
>     connections and you "disappear")
>
>  2. Set the new process callback using the standard
>     function.
>
>  3. Activate your client.
>
> Another option (which is just a glorified "if" statement) is to internally
> use a function pointer for your callback. When you need to change the
> callback, you do an atomic pointer swap.

ok, thanks a lot Gabriel and Paul, will probably go the deactivate way
as anyway the inbound ports change in both situation (from the single
calibration mic to the CD or whatever stereo inputs).

> -gabriel
_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

Fons Adriaensen-2
In reply to this post by philippe-62
On Thu, Aug 05, 2010 at 07:14:23PM +0200, philippe wrote:

> My question:
>
> Am I better designing the two functionalities in the same process
> callback and selecting them with an if, or,
>
> Is there a facility inside jack to unregister a process callback
> cleanly (without crashing anything, nor get a loud plop or hiss in the
> speakers) ??

The first would certainly be much simpler, and I see no problems
with it - the 'if' is not going to kill performance. Just make it
call one of two separate functions, this keeps your code clean.

The other could get quite complicated because you have to coordinate
things between jack's realtime thread and a non-realtime one.

I have a few apps that do similar things. They don't change the
process() callback, but have to switch between configurations without
creating loud plops in the speakers. The procedure is as follows:

Let 'X' be some non-realtime thread, and 'P' the process() callback.

P has three modes:

  PASSIVE: just returns 0.
  SILENCE: write silence to all outputs.
  PROCESS: normal operation.

1.  P is in PROCESS mode.

2,  X sets a flag to indicate that P should switch to the 'SILENCE' mode,
    and waits for response.
3.  On the next callback P goes to SILENCE mode and sets a flag to inform
    X of the change.
4.  X disconnect all ports.
5.  X sets a flag to indicate that P should switch to the 'PASSIVE' mode,
    and waits for response.
6.  On the next callback P goes to PASSIVE mode and sets a flag to inform
    X of the change.
7.  X destroys all ports.

8.  X creates new ports.
9.  X sets a flag to indicate that P should switch to the 'SILENCE' mode,
    and waits for response.
10. On the next callback P goes to SILENCE mode and sets a flag to inform
    X of the change.
11. X connects the ports.
12  X sets a flag to indicate that P should switch to the 'PROCESS' mode,
    and waits for response.
13. On the next callback P goes to PROCESS mode and sets a flag to inform
    X of the change.

14. We are back in business.

In your case X would deactivate jack, set a new callback, and re-
activate jack between steps 7 and 8.

The if() *is* simpler...

Now if you don't need to change ports, and *if* jack allows you to
change the process() pointer from within that callback, things could
be simpler. But I don't think doing this is allowed.

Ciao,

--
FA

There are three of them, and Alleline.

_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

Hermann Meyer
In reply to this post by philippe-62
Am Donnerstag, den 05.08.2010, 19:47 +0200 schrieb philippe:

> [....]
>
> ok, thanks a lot Gabriel and Paul, will probably go the deactivate way
> as anyway the inbound ports change in both situation (from the single
> calibration mic to the CD or whatever stereo inputs).
>

We use a switch statement to switch between different process
callbacks  

        // retrieve engine state from GUI
        const EngineState estate = checky;

        //------------ determine processing type
        unsigned short process_type = ZEROIZE_BUFFERS;

        if (gx_jack::NO_CONNECTION == 0) { // ports connected
                switch (estate) {
                case kEngineOn:
                        process_type = PROCESS_BUFFERS;
                        break;

                case kEngineBypass:
                        process_type = JUSTCOPY_BUFFERS;
                        break;

                default: // engine off or whatever: zeroize
                        break;
                }
        }

        //------------ main processing routine
        switch (process_type) {

        case PROCESS_BUFFERS:
                process_buffers(count, input, output0);
                break;

                // --------- just copy input to outputs
        case JUSTCOPY_BUFFERS:
           (void)memcpy( output0, input, sizeof(float)*count);
                break;


                // ------- zeroize buffers
        case ZEROIZE_BUFFERS:
        default:

                // no need of loop.
                (void)memset(output0, 0, count*sizeof(float));
                break;
        }
}

its simple and work well.

greats  hermann

_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
Reply | Threaded
Open this post in threaded view
|

Re: changing processing callback in a running client

philippe-62
In reply to this post by Fons Adriaensen-2
ok ok I see better, the if or switch route seems much clearer it seems.

will take this one finally.

thanks to Fons (nice explanation) and Hermann,

(Fons: I got a subdir called kokkinzita on my HD since a year or so
with your work which will most probably inspire me later on 8-)

BTW I found the jack.* (jack dot star) tools a really nice set of C
code to get example/inspiration for writing a first, relatively simple
jack client.

http://slavepianos.org/rd/f/207983/
by rohan drape.

On Thu, Aug 5, 2010 at 7:58 PM,  <[hidden email]> wrote:

> On Thu, Aug 05, 2010 at 07:14:23PM +0200, philippe wrote:
>
>> My question:
>>
>> Am I better designing the two functionalities in the same process
>> callback and selecting them with an if, or,
>>
>> Is there a facility inside jack to unregister a process callback
>> cleanly (without crashing anything, nor get a loud plop or hiss in the
>> speakers) ??
>
> The first would certainly be much simpler, and I see no problems
> with it - the 'if' is not going to kill performance. Just make it
> call one of two separate functions, this keeps your code clean.
>
> The other could get quite complicated because you have to coordinate
> things between jack's realtime thread and a non-realtime one.
>
> I have a few apps that do similar things. They don't change the
> process() callback, but have to switch between configurations without
> creating loud plops in the speakers. The procedure is as follows:
>
> Let 'X' be some non-realtime thread, and 'P' the process() callback.
>
> P has three modes:
>
>  PASSIVE: just returns 0.
>  SILENCE: write silence to all outputs.
>  PROCESS: normal operation.
>
> 1.  P is in PROCESS mode.
>
> 2,  X sets a flag to indicate that P should switch to the 'SILENCE' mode,
>    and waits for response.
> 3.  On the next callback P goes to SILENCE mode and sets a flag to inform
>    X of the change.
> 4.  X disconnect all ports.
> 5.  X sets a flag to indicate that P should switch to the 'PASSIVE' mode,
>    and waits for response.
> 6.  On the next callback P goes to PASSIVE mode and sets a flag to inform
>    X of the change.
> 7.  X destroys all ports.
>
> 8.  X creates new ports.
> 9.  X sets a flag to indicate that P should switch to the 'SILENCE' mode,
>    and waits for response.
> 10. On the next callback P goes to SILENCE mode and sets a flag to inform
>    X of the change.
> 11. X connects the ports.
> 12  X sets a flag to indicate that P should switch to the 'PROCESS' mode,
>    and waits for response.
> 13. On the next callback P goes to PROCESS mode and sets a flag to inform
>    X of the change.
>
> 14. We are back in business.
>
> In your case X would deactivate jack, set a new callback, and re-
> activate jack between steps 7 and 8.
>
> The if() *is* simpler...
>
> Now if you don't need to change ports, and *if* jack allows you to
> change the process() pointer from within that callback, things could
> be simpler. But I don't think doing this is allowed.
>
> Ciao,
>
> --
> FA
>
> There are three of them, and Alleline.
>
> _______________________________________________
> Jack-Devel mailing list
> [hidden email]
> http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
>
_______________________________________________
Jack-Devel mailing list
[hidden email]
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org