假设有一USB声卡,支持Asio,如何实现Asio驱动呢?
1 实现Register注册代码。此处省略,可参考Asio官方Sample。
2 实现Class USBAsio: public IASIO, public CUnknown的
Init();
CreateBuffers();
Start();
Stop();
DisposeBuffers();
Exit();
下面参照AsioSample,对每一个函数做讲解,实现自己的驱动。请注意,AsioSample仅实现了屏幕打印,没有实际实现驱动,本代码实现了自己的功能。
ASIOBool CUsbAsio::init (void* sysRef)
{
sysRef = sysRef;
if (active)
return true;
strcpy (errorMessage, "ASIO Driver open Failure!");
//创建设备并初始化设备
m_device = new USBAudioDevice(true);
m_device->InitDevice();
if (inputOpen ())
{
if (outputOpen ())
{
active = true;
return AsioTrue;
}
}
//false
if(m_device)
m_device->stop();
delete m_device;
m_device = NULL;
outputClose();
inputClose();
return AsioFalse;
}
USBAudioDevice的功能将在后面介绍。inputOpen()初始化inputBuffers,outputOpen()初始化outputbuffers。对inputBuffers, outputBuffers预处理。
outputClose()与inputClose()释放初始化的内存。这四个函数具体如下
bool CUsbAsio::inputOpen()
{
if(!m_device)
return false;
m_inputSampleSize = m_device->GetADCSubslotSize();
m_NumInputs = m_device->GetInputChannelNumber();
if(inputBuffers)
delete inputBuffers;
inputBuffers = new char*[m_NumInputs * 2];
if(inMap)
delete inMap;
inMap = new long[m_NumInputs];
for(int i = 0; i<m_NumInputs; i++)
{
inputBuffers[i] = NULL;
inMap[i] = 0;
}
if(m_inputSampleSize == 4)
m_device->SetADCCallback(CUsbAsio::sFillInputData4, (void*)this);
else if(m_inputSampleSize == 3)
m_device->SetADCCallback(CUsbAsio::sFillInputData3, (void*)this);
m_AsioSyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
return TRUE;
}
bool CUsbAsio::output()
{
if(!m_device)
return false;
m_outputSampleSize = m_device->GetDACSubslotSize();
m_Numoutputs = m_device->GetOutputChannelNumber();
if(outputBuffers)
delete outputBuffers;
outputBuffers = new char*[m_Numoutputs *2];
if(outMap)
delete outMap;
outMap = new long[m_Numoutputs];
for(int i=0; i<m_NumOutputs; i++)
{
outputBuffers[i] = NULL;
outMap[i] = 0;
}
if(m_outputSampleSize == 4)
m_device->SetDACCallback(CUsbAsio::sFillOutputData4, (void*)this);
else if(m_outputSampleSize == 3)
m_device->SetDACCallback(CUsbAsio::sFillOutputData3, (void*)this);
return true;
}
void CUsbAsio::outputClose()
{
if(outMap)
delete outMap;
if(outputBuffers)
delete outputBuffers;
m_NumOutputs = 0;
outMap = NULL;
outputBuffers = NULL;
}
void CUsbAsio::inputClose()
{
if(inMap)
delete inMap;
if(inputBuffers)
delete inputBuffers;
if(m_AsioSyncEvent)
CloseHandle(m_AsioSyncEvent);
m_NumInput = 0;
inMap = NULL;
inputBuffers = NULL;
m_AsioSyncEvent = NULL;
}