Heres a better version that automatically generates a class wrapping the portaudio.dll. Need portaudio.di(possibly renamed to portaudio.d and imported). Still same problem as original though.


import portaudio;
import std.conv, std.stdio;
import core.stdc.stdio;

alias BOOL = ubyte;
alias DWORD = uint;

auto BuildDLLClassFromCHeader(alias modulename, string name)()
{
        import std.traits, std.algorithm, std.meta;
auto s = "extern (C) class " ~name~"\n{\n\timport ___import = "~moduleName!modulename~";\n";
        mixin("import "~moduleName!modulename~";");
        foreach(m; AliasSeq!(__traits(allMembers, modulename)))
        {               
mixin("alias member = " ~ fullyQualifiedName!(modulename) ~ "." ~ m ~ ";");
                static if (is(typeof(member) == function))
                        static if (functionLinkage!member != "C")
                                continue;
                        else
s ~= "\tpublic static typeof(___import."~__traits(identifier, member)~")* "~__traits(identifier, member)~";\n";
        }
        
        return s ~ "}";
}

void DllImport(alias T)(string dllName)
{
        import core.sys.windows.windows, std.conv, std.meta;
        auto dll = LoadLibrary(to!wstring(dllName~"\0").ptr);
        if (dll == null)
                assert(0, "Cannot load DLL `"~dllName~"'");

        foreach(fname; __traits(derivedMembers, T))
        {               
                auto func = GetProcAddress(dll, fname);
enum s = "auto p = cast(void**)&"~T.stringof~"."~fname~"; *p = cast(typeof(p))func;";
                mixin(s);
        }
}


mixin(BuildDLLClassFromCHeader!(portaudio, "PortAudioDLL")());








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

bool test = false;
extern(C) int sawtooth(const(void)* inputBuffer, void* outputBuffer, size_t framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
        test = true;
    auto phase = cast(Phase*)userData;
    auto pout = cast(float*)outputBuffer;
    enum vol = 0.2f;
    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 0;
}

int main()
{
        DllImport!PortAudioDLL("portaudio_x86.dll");
        with(PortAudioDLL)
        {
                enum NUM_SECONDS = 5;

                PaStream* stream;
                PaError err;
                Phase phase_data;
        
                

                if ((err = Pa_Initialize()) == paNoError)
                {
                        
writeln("---------------------------------------------------------------------------");

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

                
                        for(auto i = 0; i < numDevices; i++ )
                        {       
                                auto deviceInfo = Pa_GetDeviceInfo(i);
writeln("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));
                        }

                        double sampleRate = 44100;
                        PaStreamParameters* input;
                        if (input != null)
                        {
                                input.device = 0;
                                auto id = Pa_GetDeviceInfo(input.device);
                                input.hostApiSpecificStreamInfo = null;
                                input.channelCount = id.maxInputChannels;
                                input.sampleFormat = paFloat32;
input.suggestedLatency = (id.defaultLowInputLatency + id.defaultHighInputLatency)/2;
                                sampleRate = id.defaultSampleRate;
                        }
                        PaStreamParameters* output = new PaStreamParameters();
                        if (output != null)
                        {
                                output.device = 9;
                                auto od = Pa_GetDeviceInfo(output.device);
                                output.hostApiSpecificStreamInfo = null;
                                output.channelCount = od.maxOutputChannels;
                                output.sampleFormat = paFloat32;
output.suggestedLatency = (od.defaultLowOutputLatency + od.defaultHighOutputLatency)/2;
                                sampleRate = od.defaultSampleRate;
                        }
if ((err = Pa_OpenStream(&stream, input, output, sampleRate, paFramesPerBufferUnspecified, paNoFlag, &sawtooth, &phase_data)) != paNoError) goto Lerror;



                        if ((err = Pa_StartStream(stream)) != paNoError) goto 
Lerror;

                        Pa_Sleep(NUM_SECONDS * 1000);

                        writeln(test);
                        if ((err = Pa_StopStream(stream)) != paNoError) goto 
Lerror;
                        if ((err = Pa_CloseStream(stream)) != paNoError) goto 
Lerror;
                        if ((err = Pa_Terminate()) != paNoError) goto Lerror;

                        writeln("DONE");
                        getchar();
                        return 0;
                } else
                {
                        Lerror:
                                writeln(to!string(Pa_GetErrorText(err)));
                                getchar();
                                return 1;
                }
        }
        return 0;
}

Reply via email to