You wrote a thread a while back about your callbacks not being called and you had a fix.

http://www.digitalmars.com/d/archives/digitalmars/D/learn/Anyone_using_Portaudio_22343.html

I'm trying to get portAudio to work on my machine and it seems everything passes yet my callbacks are not being called.


I do not know if it is the same issue you had or what. Could you describe your fixes, if you remember? You said it was alias issues, my source uses alias, so maybe I have the updated one.

Also, using paPrimeOutputBuffersUsingStreamCallback causes an access violation ;/

Here are some dll's I'm using

https://github.com/spatialaudio/portaudio-binaries



I'm including the two files needed to compile what I have in case you(or anyone else) decide to help figure this out:

Make sure to change the dll location in the DLL_PortAudio struct and set the appropriate audio interface to use(I have it set to 12, but have tried every value on my system with no luck).


module mPortAudio;
import std.stdio, std.conv;


enum PaError : int
{       
    NoError = 0,
    NotInitialized = -10000,
    UnanticipatedHostError,
    InvalidChannelCount,
    InvalidSampleRate,
    InvalidDevice,
    InvalidFlag,
    SampleFormatNotSupported,
    BadIODeviceCombination,
    InsufficientMemory,
    BufferTooBig,
    BufferTooSmall,
    NullCallback,
    BadStreamPtr,
    TimedOut,
    InternalError,
    DeviceUnavailable,
    IncompatibleHostApiSpecificStreamInfo,
    StreamIsStopped,
    StreamIsNotStopped,
    InputOverflowed,
    OutputUnderflowed,
    HostApiNotFound,
    InvalidHostApi,
    CanNotReadFromACallbackStream,
    CanNotWriteToACallbackStream,
    CanNotReadFromAnOutputOnlyStream,
    CanNotWriteToAnInputOnlyStream,
    IncompatibleStreamHostApi,
    BadBufferPtr,
        FormatIsSupported = 0,
};

enum PaSampleFormat : ulong
{
        Float32      = 0x00000001,
        Int32        = 0x00000002,
        Int24        = 0x00000004,
        Int16        = 0x00000008,
        Int8         = 0x00000010,
        UInt8        = 0x00000020,
        CustomFormat = 0x00010000,
        NonInterleaved = 0x80000000
}

enum PaHostApiTypeId : int
{
        InDevelopment=0,
        DirectSound=1,
        MME=2,
        ASIO=3,
        SoundManager=4,
        CoreAudio=5,
        OSS=7,
        ALSA=8,
        AL=9,
        BeOS=10,
        WDMKS=11,
        JACK=12,
        WASAPI=13,
        AudioScienceHPI=14
};


enum PaStreamCallbackResult : int
{
paContinue=0, /**< Signal that the stream should continue invoking the callback and processing audio. */ paComplete=1, /**< Signal that the stream should stop invoking the callback and finish once all output samples have played. */ paAbort=2 /**< Signal that the stream should stop invoking the callback and finish as soon as possible. */
};





enum PaStreamFlags : ulong
{
        NoFlag = 0,
        ClipOff = 0x00000001,
        DitherOff = 0x00000002,
        NeverDropInput = 0x00000004,
        PrimeOutputBuffersUsingStreamCallback = 0x00000008,
        PlatformSpecificFlags = 0xFFFF0000,
}

alias void PaStream;
enum paFramesPerBufferUnspecified = 0;
enum PaStreamCallbackFlags : ulong
{
        InputUnderflow = 0x00000001,
        InputOverflow = 0x00000002,
        OutputUnderflow = 0x00000004,
        OutputOverflow = 0x00000008,
        PrimingOutput = 0x00000010,
}



alias extern(C) int function(const(void) *input, void *output, ulong frameCount, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) PaStreamCallback;
alias void function( void *userData ) PaStreamFinishedCallback;

alias int PaDeviceIndex;
enum paNoDevice = cast(PaDeviceIndex)-1;
enum paUseHostApiSpecificDeviceSpecification = cast(PaDeviceIndex)-2;
alias int PaHostApiIndex;
alias double PaTime;


struct PaHostApiInfo
{
    int structVersion;
    PaHostApiTypeId type;
    const(char) *name;
    int deviceCount;
    PaDeviceIndex defaultInputDevice;
    PaDeviceIndex defaultOutputDevice;
};

struct PaDeviceInfo
{
    int structVersion;
    const(char) *name;
    PaHostApiIndex hostApi;
    int maxInputChannels;
    int maxOutputChannels;
    PaTime defaultLowInputLatency;
    PaTime defaultLowOutputLatency;
    PaTime defaultHighInputLatency;
    PaTime defaultHighOutputLatency;
    double defaultSampleRate;
};

struct PaStreamCallbackTimeInfo
{
    PaTime inputBufferAdcTime;
    PaTime currentTime;
    PaTime outputBufferDacTime;
};

struct PaStreamInfo
{
    int structVersion;
    PaTime inputLatency;
    PaTime outputLatency;
    double sampleRate;
};


struct PaHostErrorInfo
{
    PaHostApiTypeId hostApiType;
    long errorCode;
    const(char) *errorText;
};

struct PaStreamParameters
{
    PaDeviceIndex device;
    int channelCount;
    PaSampleFormat sampleFormat;
    PaTime suggestedLatency;
    void *hostApiSpecificStreamInfo;
};
























struct DLL_PortAudio
{
        @("DLLImport") public static extern(Windows)
        {
                @(r"D:\D\DLLs\portaudio_x86.dll")
                {
                        int function() Pa_GetVersion;
                        const(char)* function() Pa_GetVersionText;
                        const(char) *function(PaError errorCode) 
Pa_GetErrorText;
                        PaError function() Pa_Initialize;
                        PaError function() Pa_Terminate;
                        PaHostApiIndex function() Pa_GetHostApiCount;
                        PaHostApiIndex function() Pa_GetDefaultHostApi;
const(PaHostApiInfo)* function(PaHostApiIndex hostApi) Pa_GetHostApiInfo; PaHostApiIndex function(PaHostApiTypeId type) Pa_HostApiTypeIdToHostApiIndex; PaDeviceIndex function(PaHostApiIndex hostApi, int hostApiDeviceIndex) Pa_HostApiDeviceIndexToDeviceIndex;
                        const(PaHostErrorInfo)* function() 
Pa_GetLastHostErrorInfo;
                        PaDeviceIndex function() Pa_GetDeviceCount;
                        PaDeviceIndex function() Pa_GetDefaultInputDevice;
                        PaDeviceIndex function() Pa_GetDefaultOutputDevice;
const(PaDeviceInfo)* function(PaDeviceIndex device) Pa_GetDeviceInfo; PaError function(PaStream *stream, PaStreamFinishedCallback streamFinishedCallback) Pa_SetStreamFinishedCallback;
                        PaError function(PaStream *stream) Pa_StartStream;
                        PaError function(PaStream *stream) Pa_StopStream;
                        PaError function(PaStream *stream) Pa_AbortStream;
                        PaError function(PaStream *stream) Pa_IsStreamStopped;
                        PaError function(PaStream *stream) Pa_IsStreamActive;
PaError function(PaStream* stream, void *buffer, ulong frames) Pa_ReadStream; const(PaStreamInfo)* function(PaStream *stream) Pa_GetStreamInfo;
                        PaTime function(PaStream *stream) Pa_GetStreamTime;
                        double function(PaStream* stream) Pa_GetStreamCpuLoad;
PaError function(PaStream* stream, const void *buffer, ulong frames) Pa_WriteStream;
                        long function(PaStream* stream) 
Pa_GetStreamReadAvailable;
                        long function(PaStream* stream) 
Pa_GetStreamWriteAvailable;
                        PaError function(PaSampleFormat format) 
Pa_GetSampleSize;
                        void function(long msec) Pa_Sleep;
PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback streamCallback, void *userData) Pa_OpenStream; PaError function(PaStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, ulong framesPerBuffer, PaStreamCallback streamCallback, void *userData) Pa_OpenDefaultStream;
                        PaError function(PaStream *stream) Pa_CloseStream;
PaError function(const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate) Pa_IsFormatSupported;
                }
        }
}



// Fixes static functions and function pointers to point to their specified DLL's
static this()
{
        version(Windows)
        {
                import DLLImport;
                ImportDLLs!DLL_PortAudio;
        }
}











struct Phase
{
    float left=0, right=0;
}





bool callbackCalled = false;
extern(C) int sawtooth(const(void)* inputBuffer, void* outputBuffer, ulong framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
        callbackCalled = true;
    auto phase = cast(Phase*)userData;
    auto pout = cast(float*)outputBuffer;
    enum vol = 1f;

    foreach(i; 0 .. framesPerBuffer)
    {
        *pout++ = vol * phase.left;
        *pout++ = vol * phase.right;

        phase.left += 0.01f;
        if (phase.left >= 1.0f) phase.left -= 2.0f;

        phase.right += 0.03f;
        if (phase.right >= 1.0f) phase.right -= 2.0f;
    }
    return 1;
}

int main()
{
        import core.stdc.stdio, std.stdio, std.conv;
        with(DLL_PortAudio)
        {
                enum NUM_SECONDS = 5;

                PaStream* stream;
                PaError err;
                Phase phase_data;


                
                if ((err = Pa_Initialize()) == PaError.NoError)
                {
                        
writeln("---------------------------------------------------------------------------");

                        auto numDevices = Pa_GetDeviceCount();
                        if(numDevices < 0)
                        {
                                printf("ERROR: Pa_CountDevices returned 
0x%x\n", numDevices);
                                err = cast(PaError)numDevices;
                                goto Lerror;
                        }


                        for(auto i = 0; i < numDevices; i++ )
                        {       
                                auto deviceInfo = Pa_GetDeviceInfo(i);
                                auto deviceApiInfo = 
Pa_GetHostApiInfo(deviceInfo.hostApi);
write("Device "~to!string(i)~" > "~to!string(deviceInfo.name)~", "~to!string(deviceInfo.maxInputChannels)~", "~to!string(deviceInfo.maxOutputChannels)~", "~to!string(deviceInfo.defaultLowOutputLatency)~","~to!string(deviceInfo.defaultHighOutputLatency)~", "~to!string(deviceInfo.defaultSampleRate)~", "~to!string(deviceInfo.hostApi));
                                
write(", "~to!string(deviceApiInfo.name)~", "~to!string(deviceApiInfo.type));
                                writeln();
                                
                        }

                        double sampleRate = 44100;
                        PaStreamParameters* input; // = new 
PaStreamParameters();
                        if (input != null)
                        {
                                input.device = 12;
                                auto id = Pa_GetDeviceInfo(input.device);
                                input.hostApiSpecificStreamInfo = null;
                                input.channelCount = id.maxInputChannels;
                                input.sampleFormat = PaSampleFormat.Float32;
input.suggestedLatency = (id.defaultLowInputLatency + id.defaultHighInputLatency)/2;
                                sampleRate = id.defaultSampleRate;
                        }

                        PaStreamParameters* output = new PaStreamParameters();
                        if (output != null)
                        {
                                output.device = 12;
                                auto od = Pa_GetDeviceInfo(output.device);
                                output.hostApiSpecificStreamInfo = null;
                                output.channelCount = od.maxOutputChannels;
                                output.sampleFormat = PaSampleFormat.Float32;
output.suggestedLatency = (od.defaultLowOutputLatency + od.defaultHighOutputLatency)/2;
                                sampleRate = od.defaultSampleRate;
                        } else
                        {
                                writeln("ERROR: Invalid output stream 
Parameters");
                                return -1;
                        }


Pa_SetStreamFinishedCallback(&stream, (data) { writeln("WFWFWEFWEFWEF"); });
                        writeln("Opening Device!");
                                                
if ((err = Pa_OpenStream(&stream, input, output, sampleRate, cast(ulong)paFramesPerBufferUnspecified, cast(PaStreamFlags)(PaStreamFlags.NoFlag + 0*PaStreamFlags.PrimeOutputBuffersUsingStreamCallback), &sawtooth, &phase_data)) != PaError.NoError) goto Lerror;

                        writeln("Starting Device!");
if ((err = Pa_StartStream(stream)) != PaError.NoError) goto Lerror;

                        Pa_Sleep(NUM_SECONDS * 1000);

                        writeln("Stopping Device!");
if ((err = Pa_StopStream(stream)) != PaError.NoError) goto Lerror; if ((err = Pa_CloseStream(stream)) != PaError.NoError) goto Lerror;
                        if ((err = Pa_Terminate()) != PaError.NoError) goto 
Lerror;

                        if (!callbackCalled) writeln("Callback was not 
called!");
                        writeln("DONE!");
                        getchar();
                        return 0;
                } else
                {
                        Lerror:
                                writeln(to!string(Pa_GetErrorText(err)));
                                getchar();
                                return 1;
                }
        }
        return 0;
}


















module DLLImport;

void ImportDLLs(T)()
{
        version(Windows)
        {
                import core.sys.windows.windows, std.conv, std.meta, std.traits;
                HINSTANCE[string] DLLs;
        
                foreach(fname; __traits(allMembers, T))
                {       
                        mixin("enum isf = isFunction!(T."~fname~");");
                        mixin("enum isfp = isFunctionPointer!(T."~fname~");");
                        mixin("enum attrs = __traits(getAttributes, 
T."~fname~");");                
static if ((isf || isfp) && attrs.length == 2 && attrs[0] == "DLLImport")
                        {
                                auto dllName = attrs[1];
                                if (dllName !in DLLs)
                                        DLLs[dllName] = 
LoadLibrary(to!wstring(dllName~"\0").ptr);

                                auto dll = DLLs[dllName];
                                if (dll == null)
                                        assert(0, "Cannot load DLL 
`"~dllName~"'");

                                auto func = GetProcAddress(dll, fname);

                                mixin("import "~moduleName!(T)~";");
                                static if (isf)
mixin("auto p = cast(void**)&"~T.stringof~"."~fname~"; *p = cast(typeof(p))func;");
                                else static if (isfp)
mixin(""~T.stringof~"."~fname~" = cast(typeof("~T.stringof~"."~fname~"))func;");
                                else
                                        static assert("DLLImport Error");
                        }
                
                }
        }
}

Reply via email to