danomatika / ofxPd

(maintained) a Pure Data addon for OpenFrameworks using libpd
Other
202 stars 45 forks source link

Issue with Jack #61

Closed TradDog closed 7 years ago

TradDog commented 7 years ago

Hi,

I have read your comment on audio API being best targeted at the general openFrameworks forum. However, the issue I have does not seem to be an openFramework issue on its own.

Here is why I think so.

I followed these instructions: https://forum.openframeworks.cc/t/openframeworks-with-linux-jack/4242/30 and the audioOutputExample works on my installation with jack.

I recompiled Rtaudio in particular and installed it in OF_ROOT/libs/rtAudio.

I compile the pdExample with: PROJECT_DEFINES = __UNIX_JACK__ in the project config.make. When running, I get the following output:

SuspendRefNum error
JackClient::Execute error name = RtApiJack
[verbose] Pd: inited
[verbose] Pd:  samplerate: 44100
[verbose] Pd:  channels in: 0
[verbose] Pd:  channels out: 2
[verbose] Pd:  ticks: 16
[verbose] Pd:  block size: 64
[verbose] Pd:  calc buffer size: 1024
[verbose] Pd:  queued: no
[verbose] Pd: audio processing on
...The non audio stuff works well...
BEGIN Instance Test
RtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!
Server is not running

A few remarks:

I manage to have the libpd/samples/cpp/pdtest_rtaudio to work. I would like to use OF though.

Any suggestion is welcome.

Best

Trad

danomatika commented 7 years ago

ofxPd uses the OF sound stream for input, so this is an issue more with OF than with ofxPd. ofxPd (as with libpd) does not include it's own audio libraries for audio IO.

If the audioOutputExample works, then the ofxPd examples should work, although I've not tested with jack. I would double check the init settings to see if the settings are accepted by jack.

TradDog commented 7 years ago

I´ll double check again.

TradDog commented 7 years ago

I am pretty new to OF. So I had a lot to cover to even start investigating.

Here´s what I did. I created a new OF project with the OF ProjectCreator. I started with replicating the audioOutputExample by copying the code (a good way to understand what it does). Compiled it with make and ran it. It works and I can hear the sound. I then started to add to the ofApp.h/cpp files the code to replicate pdExample.

The logic of sound handling is slightly different between the two examples. pdExample follows what seems a more classic way of handling the audio: the in and out audio streams are actually base classes of the ofApp and are initialised with ofSoundStreamSetup. In contrast, in the audioOutupExample, a stream is created directly.

Now, I comment the puredata initialisation and code and leave the audio buffers created as in pdExample along with the example code for the audio-output from audioOutputExample:

This is the setup function:

void ofApp::setup(){
    ofBackground(34, 34, 34);

    // 2 output channels,
    // 0 input channels
    // 22050 samples per second
    // 512 samples per buffer
    // 4 num buffers (latency)

    int bufferSize      = 1024;
    sampleRate          = 44100;
    phase               = 0;
    phaseAdder          = 0.0f;
    phaseAdderTarget    = 0.0f;
    volume              = 0.1f;
    bNoise              = false;

    lAudio.assign(bufferSize, 0.0);
    rAudio.assign(bufferSize, 0.0);
    // 
    ///                           This was as in audioOutputExample
   //
    //soundStream.setup(this, 2, 0, sampleRate, bufferSize, 4);
    // use ofFmodSetBuffersize(bufferSize) to set the buffersize in fmodx prior to loading a file.
    ofSoundStreamSetup(2, 0, this, 44100, 1024, 3);

//          THE FOLLOWING IS COMMENTED OUT TO START WITH
//        if(!pd.init(2, 0, 44100, 64, false)) {
//                OF_EXIT_APP(1);
//        }
}

and here is the audioOut function (by the way in pdExample, the deprecated audioRequested and audioReceived functions are used):

void ofApp::audioOut(float * output, int bufferSize, int nChannels){
  //   pd.audioOut(output, bufferSize, nChannels);
        //pan = 0.5f;
        float leftScale = 1 - pan;
        float rightScale = pan;

        // sin (n) seems to have trouble when n is very large, so we
        // keep phase in the range of 0-TWO_PI like this:
        while (phase > TWO_PI){
                phase -= TWO_PI;
        }

        if ( bNoise == true){
                // ---------------------- noise --------------
                for (int i = 0; i < bufferSize; i++){
                        lAudio[i] = output[i*nChannels    ] = ofRandom(0, 1) * volume * leftScale;
                        rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale;
                }
        } else {
                phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget;
                for (int i = 0; i < bufferSize; i++){
                        phase += phaseAdder;
                        float sample = sin(phase);
                        lAudio[i] = output[i*nChannels    ] = sample * volume * leftScale;
                        rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale;
                }
        }

}

I can hear the sound.

Final experiment: I uncomment the pdinit part. I get the errors:

SuspendRefNum error
JackClient::Execute error name = RtApiJack
RtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!
Server is not running

and I get no sound after this although no other code is modified.

I have managed to have an IDE compiling the code (QTcreator). So I inspected the code. The error is happening line 1232 of PureData s_inter.c in the function sys_startgui. setuid(getuid()); /* lose setuid priveliges */

Independently, I can see that PureData is compiled with APIDUMMY flag, which seems to follow the logic that PureData is delegating the audio handling to OF.

I am not sure where to go from here. Strangely enough I do not have a similar problem using the C++ example with RTAudio in libpd.

Best regards

Trad.

TradDog commented 7 years ago

Hi,

I revisited the issue as the fact that ofxPD is threadsafe upon passing a simple boolean parameter is a huge time saver. I still have not figured out the real issue but I fell upon a work-around.

If libpd is initialised after the sound stream, everything works as it should. I would not be able to explain why though.

I close the issue. If someone wants to comment further, send me a message and I'll re-open the thread.

Best

Trad.