Need simple sound

FoxyBrown via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jul 6 11:18:43 PDT 2017


On Thursday, 6 July 2017 at 14:41:32 UTC, Sebastiaan Koppe wrote:
> On Thursday, 6 July 2017 at 13:28:26 UTC, FoxyBrown wrote:
>> On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe 
>> wrote:
>>> 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.
>
> The example I posted earlier did work on my Mac.
>
> I will try your example + dll loader on Windows later today. 
> Nice loader btw.

I went ahead and simplified the DLL import
import portaudio;
import std.conv, std.stdio;
import core.stdc.stdio;

alias BOOL = ubyte;
alias DWORD = uint;

// New
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);
	}
}



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





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_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;

			//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;


			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;
}



More information about the Digitalmars-d-learn mailing list