Skip to content

question about callback api #4

@shakfu

Description

@shakfu

Hi, first of all, thanks for sharing your excellent project. There's really is nothing as comprehensive out there!

I have a question about the callback api since I'm in the midst of a preliminary effort to try to cythonize libpd and enable sound input/ouput via portaudio.

Your example, 'test_playback.py', which I got to work, shows how numpy generated data can be use to generate sound.

In my case, I have an libpd api sound generation function libpd_process_double which I think I have to embed in the portaudio callback as follows:

cimport libpd
cimport libportaudio
from cpython cimport array

from libc.stdio cimport printf, fprintf, stderr, FILE

DEF N_TICKS = 1
DEF SAMPLE_RATE = 44100
DEF CHANNELS_IN = 1
DEF CHANNELS_OUT = 2
DEF BLOCKSIZE = 64
DEF IN_BUF = CHANNELS_IN * BLOCKSIZE
DEF OUT_BUF = CHANNELS_OUT * BLOCKSIZE


cdef struct UserAudioData:
    # one input channel, two output channels
    double inbuf[N_TICKS * BLOCKSIZE * CHANNELS_IN]
    # block size 64, one tick per buffer
    double outbuf[N_TICKS * BLOCKSIZE * CHANNELS_OUT]
    # stereo outputs are interlaced, s[0] = RIGHT, s[1] = LEFT, etc..

# globals
cdef UserAudioData data

cdef int audio_callback(const void *inputBuffer, void *outputBuffer,
    unsigned long framesPerBuffer,
    const libportaudio.PaStreamCallbackTimeInfo* timeInfo,
    libportaudio.PaStreamCallbackFlags statusFlags,
    void *userData ):
    """Called by the PortAudio engine when audio is needed.
    
    It may called at interrupt level on some machines so don't do anything
    that could mess up the system like calling malloc() or free().
    """
    # Cast data passed through stream to our structure.
    cdef UserAudioData *data = <UserAudioData*>userData
    cdef float *out = <float*>outputBuffer
    cdef unsigned int i;
    
    libpd.libpd_process_double(N_TICKS, data.inbuf, data.outbuf)
    
    # dsp perform routine
    for i in range(framesPerBuffer * CHANNELS_OUT):
        if (i % 2):
            out[i] = data.outbuf[i]
        else:
            out[i] = data.outbuf[i]
    return 0

Any attempts to have libpd_process_double write to UserAudioData outside the callback just doesn't work properly in this case.

I would love to use your library which has a much more robust cythonized wrapping of the portaudio api. However I can't decide if I need to write my own version of your <PaStreamCallback*>_stream_callback which is handled by StreamCallback to address my use case. I would appreciate any advice to this end.

Thanks in advance for any help!

S

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions