Initial import

git-svn-id: http://moon:8086/svn/software/trunk/libsrc/asiosdk2@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-07-19 07:44:42 +00:00
commit 562920dd85
83 changed files with 14225 additions and 0 deletions
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+526
View File
@@ -0,0 +1,526 @@
// hostsample.cpp : a simple ASIO host example.
// - instantiates the driver
// - get the information from the driver
// - built up some audio channels
// - plays silence for 20 seconds
// - destruct the driver
// Note: This sample cannot work with the "ASIO DirectX Driver" as it does
// not have a valid Application Window handle, which is used as sysRef
// on the Windows platform.
#include <stdio.h>
#include <string.h>
#include "asiosys.h"
#include "asio.h"
#include "asiodrivers.h"
// name of the ASIO device to be used
#if WINDOWS
// #define ASIO_DRIVER_NAME "ASIO Multimedia Driver"
#define ASIO_DRIVER_NAME "ASIO Sample"
#elif MAC
// #define ASIO_DRIVER_NAME "Apple Sound Manager"
#define ASIO_DRIVER_NAME "ASIO Sample"
#endif
#define TEST_RUN_TIME 20.0 // run for 20 seconds
enum {
// number of input and outputs supported by the host application
// you can change these to higher or lower values
kMaxInputChannels = 32,
kMaxOutputChannels = 32
};
// internal data storage
typedef struct DriverInfo
{
// ASIOInit()
ASIODriverInfo driverInfo;
// ASIOGetChannels()
long inputChannels;
long outputChannels;
// ASIOGetBufferSize()
long minSize;
long maxSize;
long preferredSize;
long granularity;
// ASIOGetSampleRate()
ASIOSampleRate sampleRate;
// ASIOOutputReady()
bool postOutput;
// ASIOGetLatencies ()
long inputLatency;
long outputLatency;
// ASIOCreateBuffers ()
long inputBuffers; // becomes number of actual created input buffers
long outputBuffers; // becomes number of actual created output buffers
ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
// ASIOGetChannelInfo()
ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// The above two arrays share the same indexing, as the data in them are linked together
// Information from ASIOGetSamplePosition()
// data is converted to double floats for easier use, however 64 bit integer can be used, too
double nanoSeconds;
double samples;
double tcSamples; // time code samples
// bufferSwitchTimeInfo()
ASIOTime tInfo; // time info state
unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
// Signal the end of processing in this example
bool stopped;
} DriverInfo;
DriverInfo asioDriverInfo = {0};
ASIOCallbacks asioCallbacks;
//----------------------------------------------------------------------------------
// some external references
extern AsioDrivers* asioDrivers;
bool loadAsioDriver(char *name);
// internal prototypes (required for the Metrowerks CodeWarrior compiler)
int main(int argc, char* argv[]);
long init_asio_static_data (DriverInfo *asioDriverInfo);
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo);
unsigned long get_sys_reference_time();
// callback prototypes
void bufferSwitch(long index, ASIOBool processNow);
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
void sampleRateChanged(ASIOSampleRate sRate);
long asioMessages(long selector, long value, void* message, double* opt);
//----------------------------------------------------------------------------------
long init_asio_static_data (DriverInfo *asioDriverInfo)
{ // collect the informational data of the driver
// get the number of available channels
if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
{
printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);
// get the usable buffer sizes
if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
{
printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
asioDriverInfo->minSize, asioDriverInfo->maxSize,
asioDriverInfo->preferredSize, asioDriverInfo->granularity);
// get the currently selected sample rate
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
{
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
{
// Driver does not store it's internal sample rate, so set it to a know one.
// Usually you should check beforehand, that the selected sample rate is valid
// with ASIOCanSampleRate().
if(ASIOSetSampleRate(44100.0) == ASE_OK)
{
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
else
return -6;
}
else
return -5;
}
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
if(ASIOOutputReady() == ASE_OK)
asioDriverInfo->postOutput = true;
else
asioDriverInfo->postOutput = false;
printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");
return 0;
}
return -3;
}
return -2;
}
return -1;
}
//----------------------------------------------------------------------------------
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
#define ASIO64toDouble(a) (a)
#else
const double twoRaisedTo32 = 4294967296.;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
{ // the actual processing callback.
// Beware that this is normally in a seperate thread, hence be sure that you take care
// about thread synchronization. This is omitted here for simplicity.
static processedSamples = 0;
// store the timeInfo for later use
asioDriverInfo.tInfo = *timeInfo;
// get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if (timeInfo->timeInfo.flags & kSystemTimeValid)
asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime);
else
asioDriverInfo.nanoSeconds = 0;
if (timeInfo->timeInfo.flags & kSamplePositionValid)
asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
else
asioDriverInfo.samples = 0;
if (timeInfo->timeCode.flags & kTcValid)
asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
else
asioDriverInfo.tcSamples = 0;
// get the system reference time
asioDriverInfo.sysRefTime = get_sys_reference_time();
#if WINDOWS && _DEBUG
// a few debug messages for the Windows device driver developer
// tells you the time when driver got its interrupt and the delay until the app receives
// the event notification.
static double last_samples = 0;
char tmp[128];
sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
OutputDebugString (tmp);
last_samples = asioDriverInfo.samples;
#endif
// buffer size in samples
long buffSize = asioDriverInfo.preferredSize;
// perform the processing
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
if (asioDriverInfo.bufferInfos[i].isInput == false)
{
// OK do processing for the outputs only
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOSTInt16LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24LSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
break;
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTInt16MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24MSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
break;
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
}
}
}
// finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
if (asioDriverInfo.postOutput)
ASIOOutputReady();
if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured
asioDriverInfo.stopped = true;
else
processedSamples += buffSize;
return 0L;
}
//----------------------------------------------------------------------------------
void bufferSwitch(long index, ASIOBool processNow)
{ // the actual processing callback.
// Beware that this is normally in a seperate thread, hence be sure that you take care
// about thread synchronization. This is omitted here for simplicity.
// as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs to be created
// though it will only set the timeInfo.samplePosition and timeInfo.systemTime fields and the according flags
ASIOTime timeInfo;
memset (&timeInfo, 0, sizeof (timeInfo));
// get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if(ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
bufferSwitchTimeInfo (&timeInfo, index, processNow);
}
//----------------------------------------------------------------------------------
void sampleRateChanged(ASIOSampleRate sRate)
{
// do whatever you need to do if the sample rate changed
// usually this only happens during external sync.
// Audio processing is not stopped by the driver, actual sample rate
// might not have even changed, maybe only the sample rate status of an
// AES/EBU or S/PDIF digital input at the audio device.
// You might have to update time/sample related conversion routines, etc.
}
//----------------------------------------------------------------------------------
long asioMessages(long selector, long value, void* message, double* opt)
{
// currently the parameters "value", "message" and "opt" are not used.
long ret = 0;
switch(selector)
{
case kAsioSelectorSupported:
if(value == kAsioResetRequest
|| value == kAsioEngineVersion
|| value == kAsioResyncRequest
|| value == kAsioLatenciesChanged
// the following three were added for ASIO 2.0, you don't necessarily have to support them
|| value == kAsioSupportsTimeInfo
|| value == kAsioSupportsTimeCode
|| value == kAsioSupportsInputMonitor)
ret = 1L;
break;
case kAsioResetRequest:
// defer the task and perform the reset of the driver during the next "safe" situation
// You cannot reset the driver right now, as this code is called from the driver.
// Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
// Afterwards you initialize the driver again.
asioDriverInfo.stopped; // In this sample the processing will just stop
ret = 1L;
break;
case kAsioResyncRequest:
// This informs the application, that the driver encountered some non fatal data loss.
// It is used for synchronization purposes of different media.
// Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
// Windows Multimedia system, which could loose data because the Mutex was hold too long
// by another thread.
// However a driver can issue it in other situations, too.
ret = 1L;
break;
case kAsioLatenciesChanged:
// This will inform the host application that the drivers were latencies changed.
// Beware, it this does not mean that the buffer sizes have changed!
// You might need to update internal delay data.
ret = 1L;
break;
case kAsioEngineVersion:
// return the supported ASIO version of the host application
// If a host applications does not implement this selector, ASIO 1.0 is assumed
// by the driver
ret = 2L;
break;
case kAsioSupportsTimeInfo:
// informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
// is supported.
// For compatibility with ASIO 1.0 drivers the host application should always support
// the "old" bufferSwitch method, too.
ret = 1;
break;
case kAsioSupportsTimeCode:
// informs the driver wether application is interested in time code info.
// If an application does not need to know about time code, the driver has less work
// to do.
ret = 0;
break;
}
return ret;
}
//----------------------------------------------------------------------------------
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo)
{ // create buffers for all inputs and outputs of the card with the
// preferredSize from ASIOGetBufferSize() as buffer size
long i;
ASIOError result;
// fill the bufferInfos from the start without a gap
ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
// prepare inputs (Though this is not necessaily required, no opened inputs will work, too
if (asioDriverInfo->inputChannels > kMaxInputChannels)
asioDriverInfo->inputBuffers = kMaxInputChannels;
else
asioDriverInfo->inputBuffers = asioDriverInfo->inputChannels;
for(i = 0; i < asioDriverInfo->inputBuffers; i++, info++)
{
info->isInput = ASIOTrue;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// prepare outputs
if (asioDriverInfo->outputChannels > kMaxOutputChannels)
asioDriverInfo->outputBuffers = kMaxOutputChannels;
else
asioDriverInfo->outputBuffers = asioDriverInfo->outputChannels;
for(i = 0; i < asioDriverInfo->outputBuffers; i++, info++)
{
info->isInput = ASIOFalse;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// create and activate buffers
result = ASIOCreateBuffers(asioDriverInfo->bufferInfos,
asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers,
asioDriverInfo->preferredSize, &asioCallbacks);
if (result == ASE_OK)
{
// now get all the buffer details, sample word length, name, word clock group and activation
for (i = 0; i < asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers; i++)
{
asioDriverInfo->channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
asioDriverInfo->channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
result = ASIOGetChannelInfo(&asioDriverInfo->channelInfos[i]);
if (result != ASE_OK)
break;
}
if (result == ASE_OK)
{
// get the input and output latencies
// Latencies often are only valid after ASIOCreateBuffers()
// (input latency is the age of the first sample in the currently returned audio block)
// (output latency is the time the first sample in the currently returned audio block requires to get to the output)
result = ASIOGetLatencies(&asioDriverInfo->inputLatency, &asioDriverInfo->outputLatency);
if (result == ASE_OK)
printf ("ASIOGetLatencies (input: %d, output: %d);\n", asioDriverInfo->inputLatency, asioDriverInfo->outputLatency);
}
}
return result;
}
int main(int argc, char* argv[])
{
// load the driver, this will setup all the necessary internal data structures
if (loadAsioDriver (ASIO_DRIVER_NAME))
{
// initialize the driver
if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK)
{
printf ("asioVersion: %d\n"
"driverVersion: %d\n"
"Name: %s\n"
"ErrorMessage: %s\n",
asioDriverInfo.driverInfo.asioVersion, asioDriverInfo.driverInfo.driverVersion,
asioDriverInfo.driverInfo.name, asioDriverInfo.driverInfo.errorMessage);
if (init_asio_static_data (&asioDriverInfo) == 0)
{
// ASIOControlPanel(); you might want to check wether the ASIOControlPanel() can open
// set up the asioCallback structure and create the ASIO data buffer
asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
asioCallbacks.asioMessage = &asioMessages;
asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
if (create_asio_buffers (&asioDriverInfo) == ASE_OK)
{
if (ASIOStart() == ASE_OK)
{
// Now all is up and running
fprintf (stdout, "\nASIO Driver started succefully.\n\n");
while (!asioDriverInfo.stopped)
{
#if WINDOWS
Sleep(100); // goto sleep for 100 milliseconds
#elif MAC
unsigned long dummy;
Delay (6, &dummy);
#endif
fprintf (stdout, "%d ms / %d ms / %d samples", asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)asioDriverInfo.samples);
// create a more readable time code format (the quick and dirty way)
double remainder = asioDriverInfo.tcSamples;
long hours = (long)(remainder / (asioDriverInfo.sampleRate * 3600));
remainder -= hours * asioDriverInfo.sampleRate * 3600;
long minutes = (long)(remainder / (asioDriverInfo.sampleRate * 60));
remainder -= minutes * asioDriverInfo.sampleRate * 60;
long seconds = (long)(remainder / asioDriverInfo.sampleRate);
remainder -= seconds * asioDriverInfo.sampleRate;
fprintf (stdout, " / TC: %2.2d:%2.2d:%2.2d:%5.5d", (long)hours, (long)minutes, (long)seconds, (long)remainder);
fprintf (stdout, " \r");
#if !MAC
fflush (stdout);
#endif
}
ASIOStop();
}
ASIODisposeBuffers();
}
}
ASIOExit();
}
asioDrivers->removeCurrentDriver();
}
return 0;
}
unsigned long get_sys_reference_time()
{ // get the system reference time
#if WINDOWS
return timeGetTime();
#elif MAC
static const double twoRaisedTo32 = 4294967296.;
UnsignedWide ys;
Microseconds(&ys);
double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
return (unsigned long)(r / 1000.);
#endif
}
+134
View File
@@ -0,0 +1,134 @@
# Microsoft Developer Studio Project File - Name="hostsample" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** NICHT BEARBEITEN **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=hostsample - Win32 Debug
!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
!MESSAGE
!MESSAGE NMAKE /f "hostsample.mak".
!MESSAGE
!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
!MESSAGE
!MESSAGE NMAKE /f "hostsample.mak" CFG="hostsample - Win32 Debug"
!MESSAGE
!MESSAGE Für die Konfiguration stehen zur Auswahl:
!MESSAGE
!MESSAGE "hostsample - Win32 Release" (basierend auf "Win32 (x86) Console Application")
!MESSAGE "hostsample - Win32 Debug" (basierend auf "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "hostsample - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "hostsample - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "hostsample - Win32 Release"
# Name "hostsample - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\common\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\pc\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=.\jahostsample.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\common\asio.h
# End Source File
# Begin Source File
SOURCE=..\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\pc\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\ginclude.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project
+29
View File
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
###############################################################################
Project: "hostsample"=.\hostsample.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
<html>
<body>
<pre>
<h1>Erstellungsprotokoll</h1>
<h3>
--------------------Konfiguration: hostsample - Win32 Debug--------------------
</h3>
<h3>Befehlszeilen</h3>
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E2.tmp" mit Inhalten
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"Debug/" /Fp"Debug/hostsample.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
"E:\home\Develop\SDKs\ASIO\asiosdk2\host\pc\asiolist.cpp"
]
Creating command line "cl.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E2.tmp"
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E3.tmp" mit Inhalten
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/hostsample.pdb" /debug /machine:I386 /out:"Debug/hostsample.exe" /pdbtype:sept
.\Debug\asio.obj
.\Debug\asiodrivers.obj
.\Debug\asiolist.obj
.\Debug\jahostsample.obj
]
Erstellen der Befehlzeile "link.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E3.tmp"
<h3>Ausgabefenster</h3>
Kompilierung läuft...
asiolist.cpp
Linker-Vorgang läuft...
<h3>Ergebnisse</h3>
hostsample.exe - 0 Fehler, 0 Warnung(en)
</pre>
</body>
</html>
+583
View File
@@ -0,0 +1,583 @@
// hostsample.cpp : a simple ASIO host example.
// - instantiates the driver
// - get the information from the driver
// - built up some audio channels
// - plays silence for 20 seconds
// - destruct the driver
// Note: This sample cannot work with the "ASIO DirectX Driver" as it does
// not have a valid Application Window handle, which is used as sysRef
// on the Windows platform.
#include <stdio.h>
#include <string.h>
#include "asiosys.h"
#include "asio.h"
#include "asiodrivers.h"
#include "iasiodrv.h"
// name of the ASIO device to be used
#if WINDOWS
// #define ASIO_DRIVER_NAME "ASIO Multimedia Driver"
#define ASIO_DRIVER_NAME "ASIO Sample"
#elif MAC
// #define ASIO_DRIVER_NAME "Apple Sound Manager"
#define ASIO_DRIVER_NAME "ASIO Sample"
#endif
#define TEST_RUN_TIME 60.0 // run for 20 seconds
enum {
// number of input and outputs supported by the host application
// you can change these to higher or lower values
kMaxInputChannels = 32,
kMaxOutputChannels = 32
};
// internal data storage
typedef struct DriverInfo
{
// ASIOInit()
ASIODriverInfo driverInfo;
// ASIOGetChannels()
long inputChannels;
long outputChannels;
// ASIOGetBufferSize()
long minSize;
long maxSize;
long preferredSize;
long granularity;
// ASIOGetSampleRate()
ASIOSampleRate sampleRate;
// ASIOOutputReady()
bool postOutput;
// ASIOGetLatencies ()
long inputLatency;
long outputLatency;
// ASIOCreateBuffers ()
long inputBuffers; // becomes number of actual created input buffers
long outputBuffers; // becomes number of actual created output buffers
ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
// ASIOGetChannelInfo()
ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// The above two arrays share the same indexing, as the data in them are linked together
// Information from ASIOGetSamplePosition()
// data is converted to double floats for easier use, however 64 bit integer can be used, too
double nanoSeconds;
double samples;
double tcSamples; // time code samples
// bufferSwitchTimeInfo()
ASIOTime tInfo; // time info state
unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
// Signal the end of processing in this example
bool stopped;
} DriverInfo;
DriverInfo asioDriverInfo = {0};
ASIOCallbacks asioCallbacks;
//----------------------------------------------------------------------------------
// some external references
extern AsioDrivers* asioDrivers;
bool loadAsioDriver(char *name);
// internal prototypes (required for the Metrowerks CodeWarrior compiler)
int main(int argc, char* argv[]);
long init_asio_static_data (DriverInfo *asioDriverInfo);
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo);
unsigned long get_sys_reference_time();
// callback prototypes
void bufferSwitch(long index, ASIOBool processNow);
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
void sampleRateChanged(ASIOSampleRate sRate);
long asioMessages(long selector, long value, void* message, double* opt);
//----------------------------------------------------------------------------------
long init_asio_static_data (DriverInfo *asioDriverInfo)
{ // collect the informational data of the driver
// get the number of available channels
if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
{
printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);
// get the usable buffer sizes
if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
{
printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
asioDriverInfo->minSize, asioDriverInfo->maxSize,
asioDriverInfo->preferredSize, asioDriverInfo->granularity);
// get the currently selected sample rate
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
{
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
{
// Driver does not store it's internal sample rate, so set it to a know one.
// Usually you should check beforehand, that the selected sample rate is valid
// with ASIOCanSampleRate().
if(ASIOSetSampleRate(44100.0) == ASE_OK)
{
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
else
return -6;
}
else
return -5;
}
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
if(ASIOOutputReady() == ASE_OK)
asioDriverInfo->postOutput = true;
else
asioDriverInfo->postOutput = false;
printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");
return 0;
}
return -3;
}
return -2;
}
return -1;
}
//----------------------------------------------------------------------------------
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
#define ASIO64toDouble(a) (a)
#else
const double twoRaisedTo32 = 4294967296.;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
{ // the actual processing callback.
// Beware that this is normally in a seperate thread, hence be sure that you take care
// about thread synchronization. This is omitted here for simplicity.
static processedSamples = 0;
// store the timeInfo for later use
asioDriverInfo.tInfo = *timeInfo;
// get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if (timeInfo->timeInfo.flags & kSystemTimeValid)
asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime);
else
asioDriverInfo.nanoSeconds = 0;
if (timeInfo->timeInfo.flags & kSamplePositionValid)
asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
else
asioDriverInfo.samples = 0;
if (timeInfo->timeCode.flags & kTcValid)
asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
else
asioDriverInfo.tcSamples = 0;
// get the system reference time
asioDriverInfo.sysRefTime = get_sys_reference_time();
#if WINDOWS && _DEBUG
// a few debug messages for the Windows device driver developer
// tells you the time when driver got its interrupt and the delay until the app receives
// the event notification.
static double last_samples = 0;
char tmp[128];
sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
OutputDebugString (tmp);
last_samples = asioDriverInfo.samples;
#endif
// buffer size in samples
long buffSize = asioDriverInfo.preferredSize;
// perform the processing
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
if (asioDriverInfo.bufferInfos[i].isInput == false)
{
// OK do processing for the outputs only
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOSTInt16LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24LSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
break;
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTInt16MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24MSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
break;
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
}
}
}
// finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
if (asioDriverInfo.postOutput)
ASIOOutputReady();
if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured
asioDriverInfo.stopped = true;
else
processedSamples += buffSize;
return 0L;
}
//----------------------------------------------------------------------------------
void bufferSwitch(long index, ASIOBool processNow)
{ // the actual processing callback.
// Beware that this is normally in a seperate thread, hence be sure that you take care
// about thread synchronization. This is omitted here for simplicity.
// as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs to be created
// though it will only set the timeInfo.samplePosition and timeInfo.systemTime fields and the according flags
ASIOTime timeInfo;
memset (&timeInfo, 0, sizeof (timeInfo));
// get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if(ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
bufferSwitchTimeInfo (&timeInfo, index, processNow);
}
//----------------------------------------------------------------------------------
void sampleRateChanged(ASIOSampleRate sRate)
{
// do whatever you need to do if the sample rate changed
// usually this only happens during external sync.
// Audio processing is not stopped by the driver, actual sample rate
// might not have even changed, maybe only the sample rate status of an
// AES/EBU or S/PDIF digital input at the audio device.
// You might have to update time/sample related conversion routines, etc.
}
//----------------------------------------------------------------------------------
long asioMessages(long selector, long value, void* message, double* opt)
{
// currently the parameters "value", "message" and "opt" are not used.
long ret = 0;
switch(selector)
{
case kAsioSelectorSupported:
if(value == kAsioResetRequest
|| value == kAsioEngineVersion
|| value == kAsioResyncRequest
|| value == kAsioLatenciesChanged
// the following three were added for ASIO 2.0, you don't necessarily have to support them
|| value == kAsioSupportsTimeInfo
|| value == kAsioSupportsTimeCode
|| value == kAsioSupportsInputMonitor)
ret = 1L;
break;
case kAsioResetRequest:
// defer the task and perform the reset of the driver during the next "safe" situation
// You cannot reset the driver right now, as this code is called from the driver.
// Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
// Afterwards you initialize the driver again.
asioDriverInfo.stopped; // In this sample the processing will just stop
ret = 1L;
break;
case kAsioResyncRequest:
// This informs the application, that the driver encountered some non fatal data loss.
// It is used for synchronization purposes of different media.
// Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
// Windows Multimedia system, which could loose data because the Mutex was hold too long
// by another thread.
// However a driver can issue it in other situations, too.
ret = 1L;
break;
case kAsioLatenciesChanged:
// This will inform the host application that the drivers were latencies changed.
// Beware, it this does not mean that the buffer sizes have changed!
// You might need to update internal delay data.
ret = 1L;
break;
case kAsioEngineVersion:
// return the supported ASIO version of the host application
// If a host applications does not implement this selector, ASIO 1.0 is assumed
// by the driver
ret = 2L;
break;
case kAsioSupportsTimeInfo:
// informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
// is supported.
// For compatibility with ASIO 1.0 drivers the host application should always support
// the "old" bufferSwitch method, too.
ret = 1;
break;
case kAsioSupportsTimeCode:
// informs the driver wether application is interested in time code info.
// If an application does not need to know about time code, the driver has less work
// to do.
ret = 0;
break;
}
return ret;
}
//----------------------------------------------------------------------------------
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo)
{ // create buffers for all inputs and outputs of the card with the
// preferredSize from ASIOGetBufferSize() as buffer size
long i;
ASIOError result;
// fill the bufferInfos from the start without a gap
ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
// prepare inputs (Though this is not necessaily required, no opened inputs will work, too
if (asioDriverInfo->inputChannels > kMaxInputChannels)
asioDriverInfo->inputBuffers = kMaxInputChannels;
else
asioDriverInfo->inputBuffers = asioDriverInfo->inputChannels;
for(i = 0; i < asioDriverInfo->inputBuffers; i++, info++)
{
info->isInput = ASIOTrue;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// prepare outputs
if (asioDriverInfo->outputChannels > kMaxOutputChannels)
asioDriverInfo->outputBuffers = kMaxOutputChannels;
else
asioDriverInfo->outputBuffers = asioDriverInfo->outputChannels;
for(i = 0; i < asioDriverInfo->outputBuffers; i++, info++)
{
info->isInput = ASIOFalse;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// create and activate buffers
result = ASIOCreateBuffers(asioDriverInfo->bufferInfos,
asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers,
asioDriverInfo->preferredSize, &asioCallbacks);
if (result == ASE_OK)
{
// now get all the buffer details, sample word length, name, word clock group and activation
for (i = 0; i < asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers; i++)
{
asioDriverInfo->channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
asioDriverInfo->channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
result = ASIOGetChannelInfo(&asioDriverInfo->channelInfos[i]);
if (result != ASE_OK)
break;
}
if (result == ASE_OK)
{
// get the input and output latencies
// Latencies often are only valid after ASIOCreateBuffers()
// (input latency is the age of the first sample in the currently returned audio block)
// (output latency is the time the first sample in the currently returned audio block requires to get to the output)
result = ASIOGetLatencies(&asioDriverInfo->inputLatency, &asioDriverInfo->outputLatency);
if (result == ASE_OK)
printf ("ASIOGetLatencies (input: %d, output: %d);\n", asioDriverInfo->inputLatency, asioDriverInfo->outputLatency);
}
}
return result;
}
#define MAX_DRV_NAME 256
int main(int argc, char* argv[])
{
AsioDrivers drivers;
ASIOChannelInfo *pChannelInfoInput, *pChannelInfoOutput;
char **ppDriverNames;
long numInstalledDrivers, numInputs, numOutputs;
numInstalledDrivers = drivers.asioGetNumDev();
ppDriverNames = new char*[numInstalledDrivers];
for (int i=0; i < numInstalledDrivers; i++)
ppDriverNames[i] = new char[MAX_DRV_NAME];
drivers.getDriverNames(ppDriverNames, numInstalledDrivers);
printf("* Available ASIO-Drivers:\n");
for (i=0; i < numInstalledDrivers; i++)
printf("Driver #%d: %s\n",i+1,ppDriverNames[i]);
printf("\n");
// load the driver, this will setup all the necessary internal data structures
if (loadAsioDriver (ppDriverNames[0]))
{
// initialize the driver
if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK)
{
printf ("asioVersion: %d\n"
"driverVersion: %d\n"
"Name: %s\n"
"ErrorMessage: %s\n",
asioDriverInfo.driverInfo.asioVersion, asioDriverInfo.driverInfo.driverVersion,
asioDriverInfo.driverInfo.name, asioDriverInfo.driverInfo.errorMessage);
ASIOGetChannels(&numInputs, &numOutputs);
pChannelInfoInput = new ASIOChannelInfo[numInputs];
pChannelInfoOutput = new ASIOChannelInfo[numOutputs];
for (i=0; i < numInputs; i++)
ASIOGetChannelInfoInput(&pChannelInfoInput[i], i);
for (i=0; i < numOutputs; i++)
ASIOGetChannelInfoOutput(&pChannelInfoOutput[i], i);
printf("* Input Channels:\n");
for (i=0; i < numInputs; i++)
{
printf("%s\n",pChannelInfoInput[i].name);
}
printf("* Out Channels:\n");
for (i=0; i < numOutputs; i++)
{
printf("%s\n",pChannelInfoOutput[i].name);
}
printf("\n");
if (init_asio_static_data (&asioDriverInfo) == 0)
{
// ASIOControlPanel(); you might want to check wether the ASIOControlPanel() can open
// set up the asioCallback structure and create the ASIO data buffer
asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
asioCallbacks.asioMessage = &asioMessages;
asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
if (create_asio_buffers (&asioDriverInfo) == ASE_OK)
{
if (ASIOStart() == ASE_OK)
{
// Now all is up and running
fprintf (stdout, "\nASIO Driver started succefully.\n\n");
while (!asioDriverInfo.stopped)
{
#if WINDOWS
Sleep(100); // goto sleep for 100 milliseconds
#elif MAC
unsigned long dummy;
Delay (6, &dummy);
#endif
fprintf (stdout, "%d ms / %d ms / %d samples", asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)asioDriverInfo.samples);
// create a more readable time code format (the quick and dirty way)
double remainder = asioDriverInfo.tcSamples;
long hours = (long)(remainder / (asioDriverInfo.sampleRate * 3600));
remainder -= hours * asioDriverInfo.sampleRate * 3600;
long minutes = (long)(remainder / (asioDriverInfo.sampleRate * 60));
remainder -= minutes * asioDriverInfo.sampleRate * 60;
long seconds = (long)(remainder / asioDriverInfo.sampleRate);
remainder -= seconds * asioDriverInfo.sampleRate;
fprintf (stdout, " / TC: %2.2d:%2.2d:%2.2d:%5.5d", (long)hours, (long)minutes, (long)seconds, (long)remainder);
fprintf (stdout, " \r");
#if !MAC
fflush (stdout);
#endif
// asioDriverInfo.
}
ASIOStop();
}
ASIODisposeBuffers();
}
}
ASIOExit();
}
asioDrivers->removeCurrentDriver();
for (int i=0; i < numInstalledDrivers; i++)
delete [] ppDriverNames[i];
delete ppDriverNames;
delete [] pChannelInfoInput;
delete [] pChannelInfoOutput;
}
return 0;
}
unsigned long get_sys_reference_time()
{ // get the system reference time
#if WINDOWS
return timeGetTime();
#elif MAC
static const double twoRaisedTo32 = 4294967296.;
UnsignedWide ys;
Microseconds(&ys);
double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
return (unsigned long)(r / 1000.);
#endif
}