Good afternoon,
# PlatformI'm currently running processing sketches (compiled on windows for linux ARM) on a minimalistic raspberry pi zero setup. Raspbian jessie lite and LXDE, with all unnecessary components removed, is used. The sketches are run with oracle jre 8. This all works fine and boots very quick.
Now i want to do some audio playback and tried several processing libraries. Beads turned out to be the most flexible, while all others had some basic things missing or wouldn't run properly on the raspberry. There is no doubt that the java virtual machine is not the optimum thing for the rapberry pi zero, but I want to try what's possible. Later probably a raspberry pi 3 will be used. If someone interested I could post a guide for this setup routine.
# Goal
I want to loop multiple audio files at once, where each volume can be controlled individually in real-time. Only 2-3 will be audible at the same time.
Here is a simplified processing code, which runs fine:
import beads.*;
// global variables, objects ...
String[] filepath = new String[5];
Sample[] sample = new Sample[5];
SamplePlayer[] player = new SamplePlayer[5];
Gain[] gain = new Gain[5];
AudioContext ac;
void setup() {
size(800,600,P2D);
frameRate(5);
background(0);
ac = new AudioContext();
for (int i = 0; i < filepath.length; i++) {
filepath[i] = sketchPath("sounds/sound ("+i+").wav");
sample[i] = SampleManager.sample(filepath[i]);
player[i] = new SamplePlayer(ac, sample[i]);
player[i].setKillOnEnd(false);
player[i].setLoopType(SamplePlayer.LoopType.LOOP_FORWARDS); // enable looping
player[i].pause(false); // pause playback
gain[i] = new Gain(ac, 1, 1.0); // construct gain object
gain[i].addInput(player[i]); // connect each sample player to each gain object
ac.out.addInput(gain[i]); // connect each gain to the main output
}
ac.start();
}
void draw(){
/* (...)
change and update volume
(...) */
}
# Q1
So I create an array of multiple SamplePlayer. Each has its volume control and if the volume is 0, playback is paused. Does pausing playback save some CPU time?
#Q2 In the beads manuals' examples the sample manager is not used, samples are loaded directly:
(...)
SamplePlayer sp;
sp = new SamplePlayer(ac, new Sample(sourceFile));
(...)
If I do it this way, I get an error "Unhandled exception type IOException".
Why? Do I have to use the SampleManager?
# Q3When I load more files, audio starts to get distorted (clicks/stuttering). The gain of each SamplePlayer is already adjusted to 0.2. Running top shows that 200mb ram are free and java uses not more than 45% cpu time, pulse audio uses ~10%.
So what could cause this problem? It doesn't seem to be a performance problem.
I remember running PureData on an Rasberry Pi 2 and I could play many files at one time.
Sometimes it even gets stuck. Audio stops, cpu % drops and player[i].getPosition() won't increase anymore.
# Q4
When loading more and larger files, I get and Error. On my Windows machine I can reproduce it when placing a delay(5000) inside the setup() loop after calling frameRate().
If I place the frameRate() at the last line of setup() or delete it, gives me a similar erro, but works. Player[i].getPosition() increases, but audio output is very chopped and distorted.
RunnableTask.run(): A caught exception occured on thread main-Display-.x11_:0-2-EDT-1: RunnableTask[enqueued true[executed false, flushed false], tTotal 1 ms, tExec 0 ms, tQueue 1 ms, attachment null, throwable java.lang.RuntimeException: Waited 5000ms for: <d4edc0, 5797b5>[count 1, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-Display-.x11_:0-2-EDT-1>]
java.lang.RuntimeException: Waited 5000ms for: <d4edc0, 5797b5>[count 1, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-Display-.x11_:0-2-EDT-1>
at jogamp.common.util.locks.RecursiveLockImpl01Unfairish.lock(RecursiveLockImpl01Unfairish.java:198)
at jogamp.newt.WindowImpl.getLocationOnScreen(WindowImpl.java:1159)
at jogamp.newt.driver.x11.X11UnderlayTracker.windowMoved(X11UnderlayTracker.java:141)
at jogamp.newt.WindowImpl.consumeWindowEvent(WindowImpl.java:4386)
at jogamp.newt.WindowImpl.sendWindowEvent(WindowImpl.java:4317)
at jogamp.newt.WindowImpl.positionChanged(WindowImpl.java:4558)
at jogamp.newt.WindowImpl.sizePosMaxInsetsVisibleChanged(WindowImpl.java:4865)
at jogamp.newt.driver.x11.DisplayDriver.DispatchMessages0(Native Method)
at jogamp.newt.driver.x11.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:112)
at jogamp.newt.WindowImpl.waitForVisible(WindowImpl.java:4449)
at jogamp.newt.WindowImpl.waitForVisible(WindowImpl.java:4443)
at jogamp.newt.WindowImpl.createNative(WindowImpl.java:777)
at jogamp.newt.WindowImpl.setVisibleActionImpl(WindowImpl.java:1248)
at jogamp.newt.WindowImpl$VisibleAction.run(WindowImpl.java:1318)
at com.jogamp.common.util.RunnableTask.run(RunnableTask.java:127)
at jogamp.newt.DefaultEDTUtil$NEDT.run(DefaultEDTUtil.java:375)
DefaultEDT.run(): Caught exception occured on thread main-Display-.x11_:0-2-EDT-1: RunnableTask[enqueued false[executed true, flushed false], tTotal 8185 ms, tExec 8184 ms, tQueue 1 ms, attachment null, throwable java.lang.RuntimeException: Waited 5000ms for: <d4edc0, 5797b5>[count 1, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-Display-.x11_:0-2-EDT-1>]
java.lang.RuntimeException: Waited 5000ms for: <d4edc0, 5797b5>[count 1, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-Display-.x11_:0-2-EDT-1>
at jogamp.common.util.locks.RecursiveLockImpl01Unfairish.lock(RecursiveLockImpl01Unfairish.java:198)
at jogamp.newt.WindowImpl.getLocationOnScreen(WindowImpl.java:1159)
at jogamp.newt.driver.x11.X11UnderlayTracker.windowMoved(X11UnderlayTracker.java:141)
at jogamp.newt.WindowImpl.consumeWindowEvent(WindowImpl.java:4386)
at jogamp.newt.WindowImpl.sendWindowEvent(WindowImpl.java:4317)
at jogamp.newt.WindowImpl.positionChanged(WindowImpl.java:4558)
at jogamp.newt.WindowImpl.sizePosMaxInsetsVisibleChanged(WindowImpl.java:4865)
at jogamp.newt.driver.x11.DisplayDriver.DispatchMessages0(Native Method)
at jogamp.newt.driver.x11.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:112)
at jogamp.newt.WindowImpl.waitForVisible(WindowImpl.java:4449)
at jogamp.newt.WindowImpl.waitForVisible(WindowImpl.java:4443)
at jogamp.newt.WindowImpl.createNative(WindowImpl.java:777)
at jogamp.newt.WindowImpl.setVisibleActionImpl(WindowImpl.java:1248)
at jogamp.newt.WindowImpl$VisibleAction.run(WindowImpl.java:1318)
at com.jogamp.common.util.RunnableTask.run(RunnableTask.java:127)
at jogamp.newt.DefaultEDTUtil$NEDT.run(DefaultEDTUtil.java:375)
JavaSoundAudioIO: Chosen mixer is default [default].# Q5
How can the audio context be change? For example I would need only 2 Output channels and 8-bit resolution. I tried this, but somethings is wrong:
ac = new AudioContext(new AudioIO, 512, new IOAudioFormat(44100.0, 16, 0, 2));
Are there any other Ideas on how to do this better? Could the chopped audio be a problem of pulseaudio instead?
Many many thank!