after much dithering and distraction I have now incorporated Neil Smith's JAudioLibs into Beads as the one-stop-shop for AudioIO. I'm posting an experimental release here:
http://www.beadsproject.net/downloads/beads_processing_jaudiolibs_experimental_release20120111.zip
There is one essential difference. The constructor "new AudioContext()" is no longer allowed and AudioContext must be passed an AudioIO in its constructor. However, I've put together two convenience factory methods as follows for the two audio IO solutions provided, so you can just replace the constructor in your projects with one of the following:
AudioContext ac = Beads.javaSound();
AudioContext ac = Beads.jack();
Or for a bit more control do it yourself:
AudioContext ac = new AudioContext(AudioServerIO.JavaSound(), 512, myIOAudioFormat());
I have to admit that this refactoring took ages for no good reason except that I got completely paralysed deciding the best way to implement this. I hope I've cracked this now and can get back to making improvements to the library. Many thanks to Neil! I'm really grateful for being able to use Jack without requiring Java to load any native libraries, and for getting rid of the JavaSound clicks on OS X.
A few other notes:
This is a branch of the SVN repository, source code is here:
http://www.beadsproject.net/svn/beads/Branches/RefactorAudioIO
The source code has been shuffled around so that the various IO options are stored in a separate src folder called src/beads_io. The core Beads library (in src/beads_main) has no dependencies on any particular IO, but the compiled package beads.jar contains the current preferred options (as above). (Next step will be to do the same with JavaSound dependencies concerning file IO).
I haven't responded to Evan's requests to create a decent interface for selecting devices via JavaSound. Neil's JavasoundAudioServer.create() method does accept a String arg called device but I haven't played with that yet. Could it be the answer?
This error is thrown when the system is killed (JavaSound, haven't tried Jack):
java(2445,0xb19b7000) malloc: *** error for object 0x71696e55: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
I was being inconsistent about numbering input channels in the past. The rule is (should be) that when you refer to an input channel by a number the numbering starts from 1, as you would on a mixing desk. The method getAudioInput(int[]); in AudioContext should never get given a zero. Typically you'd want something like: ac.getAudioInput(new int[] {1,2}); Hopefully those inconsistencies are gone now (except probably in my own projects, and yours).
To use the Jack audio IO you need to install Jack and run the Jack server. At present Jack is run with whatever signal vector size you choose and Beads has to conform to that vector size in order to work, otherwise… well not much.
On my Mac, JavaSound vector sizes less than 256 are buzzy, but 512 is click free (an improvement!). Low latency programs should use Jack anyway so this will be considered acceptable.
Great news! I won't have a chance to have a detailed look for a
little while, but initial thoughts look good. I'm particularly
pleased that you've not hidden the capability of using alternative
AudioServer implementations, because I'm hoping we'll get some more
soon. This also opens up the possibility to embed Beads within the
Praxis audio graph - I might finally get around to that live-coding
Beads experiment now! :-)
Few comments interspersed below -
On 11 January 2012 05:14, Oliver Bown <ol...@icarus.nu> wrote:
> Greetings,
>
> after much dithering and distraction I have now incorporated Neil Smith's JAudioLibs into Beads as the one-stop-shop for AudioIO. I'm posting an experimental release here:
>
> http://www.beadsproject.net/downloads/beads_processing_jaudiolibs_experimental_release20120111.zip
>
Is this missing JNA?
> There is one essential difference. The constructor "new AudioContext()" is no longer allowed and AudioContext must be passed an AudioIO in its constructor. However, I've put together two convenience factory methods as follows for the two audio IO solutions provided, so you can just replace the constructor in your projects with one of the following:
>
What about deprecating "new AudioContext()" but using reflection to
load the JavaSound server - no direct dependencies, but also no
breakage of older code?
> AudioContext ac = Beads.javaSound();
> AudioContext ac = Beads.jack();
>
> Or for a bit more control do it yourself:
>
> AudioContext ac = new AudioContext(AudioServerIO.JavaSound(), 512, myIOAudioFormat());
>
For clarification for anyone reading the above, there's a slight typo
I think - need a 'new' in front of AudioServerIO.JavaSound()
> I have to admit that this refactoring took ages for no good reason except that I got completely paralysed deciding the best way to implement this.
Now ain't that a familiar feeling! :-)
> I hope I've cracked this now and can get back to making improvements to the library. Many thanks to Neil! I'm really grateful for being able to use Jack without requiring Java to load any native libraries, and for getting rid > of the JavaSound clicks on OS X.
No problem. And I knew you'd get around to integrating it eventually! :-P
To clarify something for others. Use of JNA doesn't mean that Java is
not loading native libraries - it means that neither JAudioLibs, Beads
or you have to worry about it - you just have to have JNA on the
classpath, which loads its single native library automatically from
its own jar. What this does mean is that if you want to use Jack, you
still need permissions to load native code - eg. Jack output won't
work from an unsigned applet for a start, though why you'd want to do
that I don't know.
> I haven't responded to Evan's requests to create a decent interface for selecting devices via JavaSound. Neil's JavasoundAudioServer.create() method does accept a String arg called device but I haven't played with that yet. Could it be the answer?
>
Yep! You've already got it. If you use the
AudioServerIO.JavaSound(String device) constructor, you can pass in
the name of an audio mixer (ie. equivalent to JavaSound's
MixerInfo.getName() ) Actually, you don't have to pass in the whole
mixer name - it checks if the mixer name contains the String you
passed in.
The lookup code is here -
http://code.google.com/p/praxis/source/browse/audio.servers.javasound/src/org/jaudiolibs/audioservers/javasound/JavasoundAudioServer.java#407
if you're interested in how it works (no, no idea why those methods
throw different Exceptions!)
The code handles the fact that input & output mixers are different on
Windows, though you have to be careful that the String you pass in
matches both. There is also a create method in JavasoundAudioServer
which takes the actual input and output Mixer objects - this isn't
wrapped in Beads yet though.
> This error is thrown when the system is killed (JavaSound, haven't tried Jack):
> java(2445,0xb19b7000) malloc: *** error for object 0x71696e55: pointer being freed was not allocated
> *** set a breakpoint in malloc_error_break to debug
>
This is probably a JavaSound issue, and by recollection a known one,
which I saw when testing Praxis on a Mac. If you didn't see this with
your previous JavaSound code in Beads, then we may need to do some
hunting to find out why it's being triggered now. It seems to happen
when the line is closed.
> To use the Jack audio IO you need to install Jack and run the Jack server. At present Jack is run with whatever signal vector size you choose and Beads has to conform to that vector size in order to work, otherwise… well not much.
>
That seemed like the right (and simplest) thing to do for now, but
there may be options to allow the user to choose what action to take
ie. fail, run Beads with Jack's vector size, or attempt to change
Jack's vector size.
> On my Mac, JavaSound vector sizes less than 256 are buzzy, but 512 is click free (an improvement!). Low latency programs should use Jack anyway so this will be considered acceptable.
>
That's good news, as long as we can get that malloc bug fixed above,
that gives fairly useful latency on all 3 JavaSound platforms.
Did you have to shift to TimingMode.FramePosition to achieve that,
though? If so, we might need to consider checking the OS at runtime -
TimingMode.Estimated may be better on Windows and Linux. I'll try to
do some more testing.
On my laptop, I can get down to vector sizes of 128 (and sometimes 64)
on Linux and Windows 7. I have to say that Windows feels slightly
less responsive though, which makes me think there's a little extra
buffering in the OS. Need to code a latency checker sometime.
If you want to play with hacking on the JavaSound code, you could see
if replacing Thread.sleep(1) with Thread.yield() (or nothing at all)
in the loops here -
http://code.google.com/p/praxis/source/browse/audio.servers.javasound/src/org/jaudiolibs/audioservers/javasound/JavasoundAudioServer.java#219
- gives you better performance on Mac.
Best wishes,
Neil
--
Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net
--
You received this message because you are subscribed to the Google Groups "beadsproject" group.
To post to this group, send email to beadsp...@googlegroups.com.
To unsubscribe from this group, send email to beadsproject...@googlegroups.com.
Bearing in mind I wrote that code a good few months ago and haven't
looked at it since! :-)
It should pick up the number of input and output channels from the
Beads IOAudioFormat. However, it looks like you'll have to use the
longer constructor for the AudioContext.
Replace Beads.jack() with something like -
new AudioContext(new AudioServerIO.Jack(), bufferSize, new
IOAudioFormat(sampleRate, bitDepth, inputs, outputs));
Make sure that the bufferSize and sampleRate match JACK. Set inputs
and outputs to how many channels you want. Put 16 for bitDepth - it
should be ignored anyway.
Hopefully that's correct - not tested!
In answer to your question #1, use of JNA should remove all need to
fiddle with dll's, as long as you've got JNA in the classpath. Not
sure what all the preferences were used for. Main thing not possible
at the moment is autoconnect - coming soon in JAudioLibs though Ollie
will need to integrate with Beads.
Best wishes,
Neil
Hi,
Bearing in mind I wrote that code a good few months ago and haven't
looked at it since! :-)
It should pick up the number of input and output channels from the
Beads IOAudioFormat. However, it looks like you'll have to use the
longer constructor for the AudioContext.
Replace Beads.jack() with something like -
Hopefully! :-)
Try adding -
import org.jaudiolibs.beads.*;
N
Anyone playing with this experimental release, please see the
forwarded email from the JAudioLibs mailing list below. In
particular, the new release provides much improved performance with
JACK, when used with JNA 3.4.0+ Anyone using this might benefit from
joining the JAudioLibs mailing list at
http://groups.google.com/group/jaudiolibs
Ollie - any thoughts on making this release more official?
Best wishes,
Neil
------
Hi All,
JAudioLibs v1.0.120123 is now available from
http://code.google.com/p/java-audio-utils
There's only one major change in this release - the addition of
JNAJack support for JNA's new CallbackThreadInitializer, which was
specifically requested for JNAJack, and brings a huge performance
boost. Use of JNA 3.4.0+ is now highly recommended, and JNAJack will
emit a warning if an earlier version of JNA is detected (though it
will still work).
There are no API changes.
Full release notes are available at
http://code.google.com/p/java-audio-utils/wiki/ReleaseNotes
As you may have guessed from the version number, this is actually the
code from the January release of Praxis. The delay in releasing
separately was caused by a) the desire to test and b) a manic couple
of months! ;-)
Barring bug fixes, this will probably be the last 1.0 version. Some
major API improvements and additional sub-projects are in the works,
of which more in the near future.
yes let's do it. Next week is relatively clear so I'll have an attack at it. I've been getting very good performance with the RefactorAudioIO branch on my new machine, with 100s of oscillators running easily at low frame sizes, and very friendly behaviour in terms of the interaction between Jack and Beads. All good.
Ollie
Great news! :-)
I'm coding myself most of this week and next (new Praxis release in
the offing), so drop me an email if you want to check anything.
One addition that would be useful would be an easier way of specifying
the number of input and output channels, as per Andrew's issue last
month. This would work for JavaSound too, though I think it may only
be Linux that offers multichannel JavaSound devices. There was also
my earlier suggestion to not break existing code by making the no-arg
AudioContext constructor use the JavaSound IO, possibly using
reflection to try and find it?
If you get a chance while looking at this, could you also have a look
at CPU / min-latency difference between the new version of JNAJack
(with JNA 3.4.0) and the older version. I've only done a comparison
on Linux so far, so be interesting to know what sort of improvement it
gives elsewhere.
Once the next Praxis is out, I'll have a look at a PortAudioIO - promise! :-)
Best wishes,
Neil
Having said that, I have some plans for JAudioLibs 1.1 that would
allow arbitrary extensions in the configuration data passed between
client and server. There will be some sort of class to control
autoconnect behaviour, but I had also been wondering about some sort
of connection matrix object that could handle arbitrary connections.
Best wishes,
Neil