ASIO
+ -

ASIO 获取音频参数init_asio_static_data函数

2022-02-07 118 0

要打开音频设备,总得先获取参数吧。
比如UAC设备,在打开MIC时,系统会通过特定类请求设置采样率,这样固件会源源不断地通过此采样率获取音频数据,然后通过USB要同步传输将数据发送给主机。
在ASIO中,获取ASIO设备的参数有几个函数,详情可见:ASIO 函数功能介绍

ASIO的测试用例是通过init_asio_static_data()函数来初始化ASIO设备,然后打开设备进行MIC数据采样的,其主要流程如下:

  • 通过ASIOGetChannels获取通道数
  • 通过ASIOGetBufferSize获取数据缓冲区大小
  • 通过ASIOGetSampleRate获取ASIO设备支持的采样率
  • 如果采样率过大或过小,则通过ASIOSetSampleRate设置工作时的采样率为44100。
  • 通过ASIOOutputReady判断输出通道是否准备好

当然,获取的这些数据是需要保存在内存中,以供在实际获取音频数据时的使用,所以这些参数包存在DriverInfo结构体中。


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

代码流程如下:

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

运行结果如下:

asioVersion:   0
driverVersion: 1
Name:          Sample ASIO
ErrorMessage:  No ASIO Driver Error
ASIOGetChannels (inputs: 16, outputs: 16);
ASIOGetBufferSize (min: 256, max: 256, preferred: 256, granularity: 0);
ASIOGetSampleRate (sampleRate: 44100.000000);
ASIOOutputReady(); - Not supported

init_asio_static_data

获取通道数量ASIOGetChannels

ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
{
    if(!theAsioDriver)
    {
        *numInputChannels = *numOutputChannels = 0;
        return ASE_NotPresent;
    }
    return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
}

由COM实始化:

ASIOError AsioSample::getChannels (long *numInputChannels, long *numOutputChannels)
{
    *numInputChannels = kNumInputs;
    *numOutputChannels = kNumOutputs;
    return ASE_OK;
}
enum
{
    kBlockFrames = 256,
    kNumInputs = 16,
    kNumOutputs = 16
};

获取缓冲区参数ASIOGetBufferSize

ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
{
    if(!theAsioDriver)
    {
        *minSize = *maxSize = *preferredSize = *granularity = 0;
        return ASE_NotPresent;
    }
    return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
}

由COM初始化

ASIOError AsioSample::getBufferSize (long *minSize, long *maxSize,
    long *preferredSize, long *granularity)
{
    *minSize = *maxSize = *preferredSize = blockFrames;        // allow this size only
    *granularity = 0;
    return ASE_OK;
}

颗粒度granularity=0,而blockFrames=256,由构造函数实现

AsioSample::AsioSample (LPUNKNOWN pUnk, HRESULT *phr)
    : CUnknown("ASIOSAMPLE", pUnk, phr)
{

    blockFrames = kBlockFrames;
    inputLatency = blockFrames;        // typically
    outputLatency = blockFrames * 2;
}
enum
{
    kBlockFrames = 256,
    kNumInputs = 16,
    kNumOutputs = 16
};

获取采样率ASIOGetSampleRate

ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
{
    if(!theAsioDriver)
        return ASE_NotPresent;
    return theAsioDriver->getSampleRate(currentRate);
}

而COM初始化为

ASIOError AsioSample::getSampleRate (ASIOSampleRate *sampleRate)
{
    *sampleRate = this->sampleRate;
    return ASE_OK;
}

构造函数将将采样率设为:

AsioSample::AsioSample (LPUNKNOWN pUnk, HRESULT *phr)
    : CUnknown("ASIOSAMPLE", pUnk, phr)
{
    ...
    sampleRate = 44100.
}

模拟仿真判断,使用ASIOOutputReady判断

ASIOError ASIOOutputReady(void)
{
    if(!theAsioDriver)
        return ASE_NotPresent;
    return theAsioDriver->outputReady();
}
ASIOError AsioSample::outputReady ()
{
    return ASE_NotPresent;
}
enum {
    ASE_OK = 0,             // This value will be returned whenever the call succeeded
    ASE_SUCCESS = 0x3f4847a0,    // unique success return value for ASIOFuture calls
    ASE_NotPresent = -1000, // hardware input or output is not present or available
    ASE_HWMalfunction,      // hardware is malfunctioning (can be returned by any ASIO function)
    ASE_InvalidParameter,   // input parameter invalid
    ASE_InvalidMode,        // hardware is in a bad mode or used in a bad mode
    ASE_SPNotAdvancing,     // hardware is not running when sample position is inquired
    ASE_NoClock,            // sample clock or rate cannot be determined or is not present
    ASE_NoMemory            // not enough memory for completing the request
};

这里表示的是软件模拟的,即硬件输出输入不存在,故处于测试态。所以执行

    asioDriverInfo->postOutput = false;

并输出:

ASIOOutputReady(); - Not supported

0 篇笔记 写笔记

UNICODE_STRING的初始化
从UNICODE_STRING结构体的三个成员可以看到,其包含的是字符串的指针,字符串的实际长度和字符串指针的内存空间长。学过C语言的我们都知道,要对一个指针的内存进行赋值,就必须确定这个指针指向的内存空间可用,否则会导致内存使用异常。在应用层中会导致应用程序异常,而在驱动中会导致蓝屏。我们们这里使......
WDDM KMDOD驱动介绍及驱动初始化
KMOD驱动是微软提供的一个Display Only驱动。WDDM KMOD驱动初始化Windows驱动的入口函数是DriverEntry,所以显示Mini小端口驱动程序也不例外。和其它Mini小端口驱动的入口函数实现一致,在其DriverEntry只做一件事,就是分配系统指定的一个结构体,然后......
ASIO 简介
ASIO是Audio Stream I/O的简称。ASIO主要用于对希望在个人电脑音频设备相对于系统的音频设备实现高效音频处理、高数据吞吐量,音频硬件端的同步、低延迟和可扩展性等方面的性能改善。ASIO比较灵活,音频接口不需要绑定到任何固定数量的输入和输出通道(当然,此数量受计算机系统本身的处理......
ASIO 状态机
主机应用程序加载设备的ASIO驱动程序,其时序状态机如下图:LOADED(加载驱动程序):应用程序加载ASIO驱动程序。Initialized(初始化):驱动程序接收应用程序控制查询,不过设备不必要在此时创建。Prepared(准备好):收发音频数据的缓冲区已经被分配,并且设备准备工作。Runn......
ASIO 函数功能介绍
主机应用查询设备驱动ASIO API为主机应用程序和驱动程序提供多个查询功能。驱动程序初始化后,应用程序将查询以下全部或部分功能:ASIOGetChannels()查询可用音频通道的数量ASIOGetBufferSize()获取支持的音频缓冲区大小ASIOCanSampleRate()询问驱动程......
ASIO 应用层函数分类大全
初始化/终止ASIOError ASIOInit(ASIODriverInfo *info);ASIOError ASIOExit(void);开始、停止ASIOError ASIOStart(void);ASIOError ASIOStop(void);查询方法和抽样率ASIOError ......
ASIO 应用层C++类声明
class AsioDriver {public:AsioDriver(); ~AsioDriver();ASIOBool init(void *);void getDriverName(char *name);long getDriverVersion();void getErrorM......
Windows下注册ASIO
在带有WOW6432 ASIO的Windows 64位系统上,32位和64位主机应用程序都可以使用ASIO。要求ASIO驱动程序的COM部分以32位和64位二进制形式提供32位主机应用程序将查询32位Windows注册表部分(Wow6432)。64位主机应用程序将查询普通Windows注册表。A......
ASIO 应用层工程组成
ASIO工程目录如下:asio:工程文件目录。asio.slncommon: asiosample.dll和hostsample.exe工程使用的公共文件 driver: asiosample文件目录host: hostsample文件目录ASIO应用层由asiosample工程和hostsa......
ASIO asiosample.dll注册及注册表信息变化
在Windows下注册ASIO一节中,是需要对COM进入注册的。故我们使用Regsvr32命令注册。如:K:usbzhasioasiosdk_2.3.3_2019-06-14driverasiosampleasiosampleDebug>REGSVR32 asiosample.......
ASIO 示例代码调试准备
ASIO提供的示例代码在进行调试前,需要做以下几个步骤:第一,就是按上节的要求将编译好的asiosample.dll通过命令行进行注册,这里使用的命令是REGSVR32 asiosample.dll当然,这个注册分为32位和DLL和64位的DLL,所以会有差别。本人在现有的机器使用的是32位编程......
ASIO hostsample工程分析
hostsample总共分为4个文件,分别为:asiolist.h/asiolist.cpp : 基类,主要功能是枚举系统中已经安装的ASIO的COMM类asiodriver.h/asiodriver.cpp 继承于asiolist,实现对指定ASIO驱动类的安装,卸载和当前信息获取asio.......
ASIO 驱动加载loadAsioDriver
loadAsioDriver用于加载指定的ASIO驱动程序,由main函数调用。int main(int argc, char* argv[]){ // load the driver, this will setup all the necessary internal data st......
ASIO 初始化函数ASIOInit
ASIOInit();初始化应用程序使用的驱动程序。可选择获取硬件或加载其他驱动程序组件ASIOError ASIOInit(ASIODriverInfo *info);其调用关系统如下:int main(int argc, char* argv[]){ // load the d......
ASIO 获取音频参数init_asio_static_data函数
要打开音频设备,总得先获取参数吧。比如UAC设备,在打开MIC时,系统会通过特定类请求设置采样率,这样固件会源源不断地通过此采样率获取音频数据,然后通过USB要同步传输将数据发送给主机。在ASIO中,获取ASIO设备的参数有几个函数,详情可见:ASIO 函数功能介绍 。ASIO的测试用例是通过in......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!