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