Need simple sound

FoxyBrown via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jul 6 06:28:26 PDT 2017


On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe wrote:
> On Wednesday, 5 July 2017 at 05:34:37 UTC, FoxyBrown wrote:
>> On Tuesday, 4 July 2017 at 20:37:44 UTC, Sebastiaan Koppe 
>> wrote:
>>> Portaudio is simple as well. And nice cross platform.
>>
>> are there any bindings?
>
> Sure, see http://code.dlang.org/packages/portaudio

So, after a bit of work I can get port audio to work but the 
callback never seems to be called(no audio, never hits bp). Shows 
all the devices and seems to run fine otherwise. Tried all the 
devices I I have. The default stream doesn't work either.



Here is the following code:



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

alias BOOL = ubyte;
alias DWORD = uint;

struct dllimport
{
   string dllName;
}

template hasAttribute(alias sym, T)
{
	static bool helper()
	{
		foreach(a; __traits(getAttributes, sym))
		{
			if(is(a == T) || __traits(compiles, typeof(a)) && is(typeof(a) 
== T))
				return true;
		}
		return false;
	}
	enum bool hasAttribute = helper();
}

template getAttribute(alias sym, T)
{
	static T helper()
	{
		foreach(a; __traits(getAttributes, sym))
		{
			static if(is(a == T) || __traits(compiles, typeof(a)) && 
is(typeof(a) == T))
				return a;
		}
		assert(0, "attribute " ~ T.stringof ~ " not found");
	}
	enum T getAttribute = helper();
}

void doImport(alias T)()
{
	import core.sys.windows.windows, std.conv;
	bool isDLLLoaded = false;
	HINSTANCE dll;
	foreach(m; __traits(allMembers, T))
	{		
		static if(__traits(compiles, typeof(__traits(getMember, T, m))))
		{			
			static if(hasAttribute!(__traits(getMember, T, m), dllimport))
			{
				auto dllName =  getAttribute!(__traits(getMember, T, m), 
dllimport).dllName;
				if (!isDLLLoaded)
				{
					writeln("Loading DLL `"~dllName~"'...");
					isDLLLoaded = true;
					dll = LoadLibrary(to!wstring(dllName~"\0").ptr);
					if (dll == null)
					{
						// ERROR, handle
						writeln("Error, aborting!");
						return;
					}

				}
				auto q = GetProcAddress(dll, m);
				mixin(m~" = cast(typeof("~m~"))q;");

				//func(m, getAttribute!(__traits(getMember, T, m), 
dllimport).dllName, cast(void**)&__traits(getMember, T, m));
			}
		}
	}
}

mixin template DllImportFunctions()
{
	struct DllImporter
	{
		shared static this()
		{
			doImport!(__traits(parent, DllImporter))();
		}

		static loadFunction(string name, const(char)[] dllName, void** 
addr)
		{
			printf("import %.*s from %.*s into %llx\n", name.length, 
name.ptr, dllName.length, dllName.ptr, addr);
		}
	}
}


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

}

mixin DllImportFunctions;



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


extern(C) int sawtooth(const(void)* inputBuffer, void* 
outputBuffer, size_t framesPerBuffer, 
const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags 
statusFlags, void *userData)
{
     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()
{
     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 = 15;
			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_OpenDefaultStream(&stream,      0,       2, 
paFloat32, SAMPLE_RATE, paFramesPerBufferUnspecified, &sawtooth, 
&phase_data)) != paNoError) goto Lerror;
		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);

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

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



More information about the Digitalmars-d-learn mailing list