I just merged a new module that I have been working on into trunk. The module is app_jack. It provides interfaces between Asterisk and JACK (Jack Audio Connection Kit). A description of JACK from their website:
Have you ever wanted to take the audio output of one piece of software and send it to another? How about taking the output of that same program and send it to two others, then record the result in the first program? If so, JACK may be what you’ve been looking for.
JACK is a low-latency audio server, written for POSIX conformant operating systems such as GNU/Linux and Apple’s OS X. It can connect a number of different applications to an audio device, as well as allowing them to share audio between themselves. Its clients can run in their own processes (ie. as normal applications), or can they can run within the JACK server (ie. as a “plugin”).
I recently learned about PureData, so very quickly I wanted to be able to get phone calls in and out of Pd (PureData). After exploring various options, JACK turned out to be the obvious choice for providing audio transport between Asterisk and Pd. I have been wanting to build some interesting applications in Pd that do audio analysis and manipulation, but I had some infrastructure work to complete first.
So, I wrote app_jack. This module provides two interfaces between Asterisk and JACK. The first is an Asterisk application, JACK(). The second interface is a dialplan function, JACK_HOOK().
JACK() Application
This is the simpler of the two interfaces. When the JACK() application is executed in the Asterisk dialplan, two JACK ports get created. There is an input and output port that acts as the endpoint of a phone call. The audio from the channel goes out of the output port that gets created. Whatever audio that comes in on the input port is what gets sent back to the caller. This would allow for some advanced voice applications that interact with the audio of the call and run as a separate application.
Example:
exten => 1234,1,Answer
exten => 1234,n,JACK()
For more information, see the built in documentation for the application from the Asterisk CLI:
*CLI> core show application JACK
JACK_HOOK() Function
This interface is a little bit more complex, but it is the much more interesting one, in my opinion. The JACK_HOOK function creates an audiohook and attaches it to the channel. In this case, instead of the JACK interface being the endpoint of the phone call, it is simply hooked in to the audio path for a phone call to something else. Audio that comes from a caller gets sent out the JACK output port, and whatever audio that comes back in on the input port gets sent on as the caller’s audio. This allows for cool applications that do analysis and manipulation of the audio in a phone call. One example is that I can now write custom vocoders in Pd.
For more information about the syntax for using JACK_HOOK, see the built in documentation from the Asterisk CLI:
*CLI> core show function JACK_HOOK
Here is a simple example for enabling a JACK_HOOK for a call:
exten => _1NXXNXXXXXX,1,Answer
exten => _1NXXNXXXXXX,n,Set(JACK_HOOK(manipulate)=on)
exten => _1NXXNXXXXXX,n,Dial(IAX2/myprovider/${EXTEN})
This also inspired me to write a new CLI command, “core set chanvar”, which lets you set a channel variable or function from the Asterisk CLI. You can use it to turn on a JACK_HOOK for an existing call from the CLI.
*CLI> core set chanvar SIP/poly1-ab23jadf234 JACK_HOOK(manipulate) on
Another way to enable a JACK_HOOK for an existing call would be by using the manager interface. For example:
Action: SetVar
Channel: SIP/123-f234kjsdfz
Variable: JACK_HOOK(manipulate)
Value: on
Enjoy! Please let me know if you find this interesting or useful. I would also be happy to consider any suggestions for enhancements.
Pingback: app_jack: Interface entre Asterisk y JACK at Mi Brain-Training Personal
We’re all using freeswitch[0], now;)
Asterisk has deep core serious limitations in audio quality as it’s not able to do more than 8kHz audio.
I’ve been using VOIP and JACK for some years now and I’m glad I don’t have to suffer with asterisk any more.
[0]http://freeswitch.org
In any case, JACK support belongs on the VOIP client, in my opinion.
Pingback: SinoLogic » Más ventajas en la futura versión de Asterisk 1.6
Esben:
Actually, Asterisk has native support for 16 kHz audio, as well.
I also agree that jack support on the client side has its own set of interesting applications. However, that does not discount the fact that it is very possible to develop cool voice applications on the server side that use jack.
Russell, I’d just like to say that you are my hero for creating this functionality. I’m not a strong programmer and I am glad that modules like this exist that allow for me to get to the audio in a trivial manner. Under the current application, is it possible to tell Jack_hook to connect to more than one output, and is it okay to switch the output connection while the call is “jacked”?
It is not possible to tell JACK_HOOK() to connect to more than one input and one output port. I’m honestly not a Jack expert, but it seems like you might be able to accomplish that by telling Asterisk to connect to one port, that in turns is connected to a number of things. Also, there is no problem with moving around what the channel is connected to. That is a feature of Jack itself, and not due to anything I have done.
I’m glad you enjoy the feature. 🙂
russell,
is the app_jack module available for asterisk 1.4? if not how can i achieve what app_jack does in asterisk 1.4?
it is for our place of worship to allow elederly and infirm worshippers to have a 2 way participation in meetings
many thanks
hi russell, I was trying to enable app_jack appication (menuconfig) but it requires resample library. Where is it?
thank you
(Debian Etch)
You can get it from Digium svn:
svn co http://svn.digium.com/svn/thirdparty/libresample/trunk
Hi russel. Finally I can test JACK application. Great job!!!! I was able to “map” extensions to output audio channels. Each extension is mapped to one channel left or right. Asterisk and Jack can make a powerful paging system.
But, I’ve note that there is a long delay between voip phone and output channel (around 500ms). Do you get same delay?
Thanks,
Thanks for the feedback, sergio.
I would expect some amount of delay, as there is some buffering between Asterisk and jack, but 500ms seems a bit high. I haven’t looked at this code in quite a while, though …
Thanks Russell.
Today I’ve done some test using softphones (zoiper, ekiga, sjphone) and voip terminals (siemens, 3com) and have note that delay using a voip terminals reduce to 260ms (I’m using audio editor software to record my voice and see delay). Anyway this time is not faster enough for paging system due to feedback.
Ummmm! As soon I can I will measure delay in “normal communication” between voip terminals (to see delay without Jack interfaces).
Keep you informed
Sergio
Hi Russell, finally I’ve the delay between
different equipments (voip phones, softphones, jack interfaces and console using alsa and oss)
Voip to voip phone call has a delay of 40ms.
Softphone (sjphone or zoiper) to voip phone has a delay of 80ms.
Dialing to jack interfaces (JACK(i(playback_1))) or dialing to console (Dial(CONSOLE/alsa/1)) it takes same delay, about 250ms. I think the problem is due to asterisk architecture and not jack interfaces.
Thank you and good job,
Sergio
I have tried to find this function in both a Trixbox installation and AsteriskNow. Both installations are running Asterisk 1.6 and when I issue the command core show function JACK_HOOK NOTHING is there on either installation. I have spent the last couple of days looking for a possible solution with no avail. Anybody know of a module that I may be missing? According to what I read this is suppose to be a core function in Asterik 1.6.
Hey Russel !
Thanks for this cool app, we’re using it in a student radio telephone system to hook up with the professional audio cards.
Using Asterisk as a client is just a bit overkill though, and we will switch to a jackd compatible VoIP client as soon as someone is willing to develop the feature. No luck so far.
Anyway, we also noticed a delay, but strangely, only one way, and quite annoying, as it is almost 1 second ! This delay is non existent without JACK.
We’re using it with a realtime kernel (RT PREEMPT), as jackd requires it if you want to achieve very low latency.
But we’re still having this strange delay. I’ll investigate more, and report.
Hello there,
Is there a way to specify several JACK ports to connect to at the same time ?
It would be a very simple way to downmix a 2 channels audio stream to a single Asterisk call from JACK.
One would simply loop through the list of requested ports and call jack_connect() with them.
Thanks for your help.
Hi,
I have been able to connect to Jack_hook interface successfully, but in my case I need that caller should be on the fly be able to switch off jack. that means I want a capability to turn jack routing during the call.
I tried by adding a feature in features.xml file as:
change_to_jack0 => #0,self/caller,Set(JACK_HOOK(manipulate)=off)
but when I press #0, although the jack is disconnected but it does not restore the previous state i.e. the voice channel from caller to callee transmits nothing.
I want it to transmit the original voice.
I would suggest asking for suggestions on the asterisk users mailing list, or filing an issue on the asterisk bug tracker if you think something is broken.
Hi Russell
I am an artist working with Asterisk and PD to create telephone audio pieces. Unfortunately I am not a programmer! I would be really grateful if you could provide me with an indication as to how one might, using the asterisk dial plan, pass audio from a caller to a jack channel and then return it to the caller post processing. I understand your Jack application in Asterisk creates an input and output channel but I cannot figure out how to access these channels in Jack. I already have Asterisk and the Jack module loaded but I am unable to verify if the Jack command in the dial plan is actually doing what it should do. I apologise for being such a non technical person.