libpd
Embedding Pure Data as a DSP library
Get it:
git clone git://gitorious.org/pdlib/libpd.git
Build it:
make libs/libpd.so
Test it with PulseAudio:
/* C example of using libpd with pulseaudio * RECORD & PLAYBACK * * gcc -c main.c `pkg-config --cflags libpulse-simple` -o main.o "-I." "-I/home/psc/src/libpd/libpd_wrapper" "-I/home/psc/src/libpd/pure-data/src" * gcc -o myapp main.o "-L." -O2 `pkg-config --libs libpulse-simple` /home/psc/src/libpd/libs/libpd.so * * http://www.workinprogress.ca/libpd */ #include <stdio.h> // libpd #include "z_libpd.h" // pulseaudio #include <pulse/simple.h> #include <pulse/error.h> #include <pulse/gccmacro.h> #define NUMBERSECOND 10 #define SAMPLE_RATE 44100 #define NBCHANNEL 2 #define BLOCKSIZE 64 #define TICK 1 //libpd catch [print] function void pdprint(const char *s) { printf("%s", s); } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: %s file folder\nexample: ./libpd echo.pd ./\n", argv[0]); return -1; } // libpd libpd_printhook = (t_libpd_printhook) pdprint; libpd_init(); libpd_init_audio(NBCHANNEL, NBCHANNEL, SAMPLE_RATE, TICK); // input channel, output channel, sr, tick per buffer // compute audio [; pd dsp 1( libpd_start_message(); libpd_add_float(1.0f); libpd_finish_message("pd", "dsp"); // open patch [; pd open file folder( libpd_start_message(); libpd_add_symbol(argv[1]); libpd_add_symbol(argv[2]); libpd_finish_message("pd", "open"); // pulseaudio // puredata use PA_SAMPLE_FLOAT32LE static const pa_sample_spec ss = { .format = PA_SAMPLE_FLOAT32LE, .rate = SAMPLE_RATE, .channels = NBCHANNEL, }; // low-latency setting pa_buffer_attr ba; ba.tlength = pa_usec_to_bytes(50*1000, &ss); ba.minreq = pa_usec_to_bytes(0, &ss); ba.maxlength = pa_usec_to_bytes(50*1000, &ss); ba.fragsize = sizeof(uint32_t) -1; //Adjust this value if it's glitchy pa_simple *s = NULL; pa_simple *r = NULL; // init pulseaudio int error; if (!(r = pa_simple_new(NULL, "pdlib", PA_STREAM_RECORD, NULL, argv[1], &ss, NULL, &ba, &error))) { fprintf(stderr, __FILE__": pa_simple_new() - record failed: %s\n", pa_strerror(error)); goto problem; } if (!(s = pa_simple_new(NULL, "pdlib", PA_STREAM_PLAYBACK, NULL, argv[1], &ss, NULL, &ba, &error))) { fprintf(stderr, __FILE__": pa_simple_new() - playback failed: %s\n", pa_strerror(error)); goto problem; } // now run pd for ten seconds (logical time) int i; float inbuf[NBCHANNEL * BLOCKSIZE * TICK], outbuf[NBCHANNEL * BLOCKSIZE * TICK]; for (i = 0; i < NUMBERSECOND * SAMPLE_RATE / (BLOCKSIZE * TICK); i++) { // pulseaudio input if (pa_simple_read(r, inbuf, sizeof(t_float) * BLOCKSIZE * NBCHANNEL * TICK, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); goto problem; } // libpd process dsp libpd_process_float(inbuf, outbuf); // pulseaudio output if (pa_simple_write(s, outbuf, sizeof(t_float) * BLOCKSIZE * NBCHANNEL * TICK, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error)); goto problem; } /* //pulseaudio - report latency pa_usec_t latency; if ((latency = pa_simple_get_latency(s, &error)) == (pa_usec_t) -1) { fprintf(stderr, __FILE__": pa_simple_get_latency() failed: %s\n", pa_strerror(error)); goto problem; } fprintf(stderr, "%0.0f usec \r", (float)latency); */ } /* Make sure that every single sample was played */ if (pa_simple_drain(s, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(error)); goto problem; } pa_simple_free(s); pa_simple_free(r); return 0; problem: if (s) { pa_simple_free(s); } if (r) { pa_simple_free(r); } fprintf( stderr, "An error occured" ); return -1; }
Test it with PortAudio:
/* C example of using libpd with portaudio * RECORD & PLAYBACK * * gcc -c main.c `pkg-config --cflags portaudio-2.0` -o main.o "-I." "-I/home/psc/src/libpd/libpd_wrapper" "-I/home/psc/src/libpd/pure-data/src" * gcc -o myapp main.o "-L." -O2 `pkg-config --libs portaudio-2.0` /home/psc/src/libpd/libs/libpd.so */ #include <stdio.h> // libpd #include "z_libpd.h" // portaudio #include "portaudio.h" #define NUMBERSECOND 10 #define SAMPLE_RATE 44100 #define NBCHANNEL 2 #define BLOCKSIZE 64 #define TICK 1 //libpd catch [print] function void pdprint(const char *s) { printf("%s", s); } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: %s file folder\nexample: ./libpd echo.pd ./\n", argv[0]); return -1; } // libpd libpd_printhook = (t_libpd_printhook) pdprint; libpd_init(); libpd_init_audio(NBCHANNEL, NBCHANNEL, SAMPLE_RATE, TICK); // input channel, output channel, sr, tick per buffer // compute audio [; pd dsp 1( libpd_start_message(); libpd_add_float(1.0f); libpd_finish_message("pd", "dsp"); // open patch [; pd open file folder( libpd_start_message(); libpd_add_symbol(argv[1]); libpd_add_symbol(argv[2]); libpd_finish_message("pd", "open"); // portaudio PaStreamParameters inputParameters, outputParameters; PaStream *stream; PaError err; err = Pa_Initialize(); if( err != paNoError ) goto error; // input inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ if (inputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default input device.\n"); goto error; } inputParameters.channelCount = NBCHANNEL; inputParameters.sampleFormat = paFloat32; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; // output outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } outputParameters.channelCount = NBCHANNEL; outputParameters.sampleFormat = paFloat32; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, &inputParameters, &outputParameters, SAMPLE_RATE, BLOCKSIZE, paClipOff, /* paClipOff, */ /* we won't output out of range samples so don't bother clipping them */ NULL, NULL); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; // now run pd for ten seconds (logical time) int i; float inbuf[NBCHANNEL * BLOCKSIZE * TICK], outbuf[NBCHANNEL * BLOCKSIZE * TICK]; for (i = 0; i < NUMBERSECOND * SAMPLE_RATE / (BLOCKSIZE * TICK); i++) { // portaudio input err = Pa_ReadStream(stream, inbuf, BLOCKSIZE * TICK); if( err != paNoError ) goto error; // libpd process dsp libpd_process_float(inbuf, outbuf); // portaudio output err = Pa_WriteStream(stream, outbuf, BLOCKSIZE * TICK); if( err != paNoError ) goto error; } //portaudio - stop stream, close, and terminate err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return 0; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return -1; }
Want libpd.a?
mkdir staticlib
cp libpd_wrapper/*.o pure-data/src/*.o staticlib/
ar rcs libpd.a *.o
compile your program with:
-Wl,–export-dynamic -Wl,–whole-archive ./libpd.a -Wl,–no-whole-archive
WxWidgets C++ GUI example (wxlibpd)


Download project (codelite) & exectuable (linux – gtk):
wxlibpd
Documentation:
http://gitorious.org/pdlib/pages/Libpd