Android无驱usb音频实现

本文介绍如何实现在Android系统上通过USB麦克风进行声音采集,兼容多款设备。采用libusb库直接访问USB驱动,解析音频数据,通过JNI库供APK调用。详细讲解了初始化、配置和数据获取的步骤,以及注意事项,如endpoint参数设置和数据回调。文章还提及了UAC协议解析和设备兼容性的提升可能性。
摘要由CSDN通过智能技术生成

实现android系统通过usb麦克风采集声音功能,能够兼容多款anroid设备。

设想方案有两个:
1.采用通过libusb库,直接访问usb驱动,分析usb协议中的音频数据。
2.通过tinyalsa访问音频设备的pcm节点,通过节点直接获取音频数据。

因第二种方式音频节点id并不可控,并不能适配多款android设备,遂采用第一种方式。

通过代码调用libusb库,通过usb驱动获取数据,然后封装成jni库,供apk调用。

背景知识

每一个usb设备都有自己固定的VID和PID地址,根据这个地址可以寻找到指定的usb设备。

usb有config,然后下面有多个interface,interface下面有多个endpoint。根据interface的class和subclass值可以区分interface类型,比如video的class值是14,audio的class值是1等,根据这个可以识别复合设备的interface。然后每个interface下面有多个endpoint,endpoint存在address,这个是数据传输的通道。每个endpoint存在不同的数据格式,比如我手上的这个usb麦克风,每个endpoint对应一种格式,比如双通道/16位/48K。但也有一个endpoint对应多种格式的。

usb的传输类型有四种,分别是控制传输(Control Transfer)、中断传输(Interrupt Transfer)、批量传输(Bulk Transfer)、同步传输(Isochronous Transfer)。音频设备只用到控制传输和同步传输。

代码

1.初始化

先进行init,然后根据vid、pid查找usb设备,进行open,然后因为要使用无驱设计,需要将音频alsa和usb驱动进行解绑。最后扫描所有config,根据所需要的class找到所需的interface,进行选择设置。

int UsbAudio::open(int vid, int pid, int fd, const char *usbfs)
{
    int r;                         //for return values  
    ssize_t cnt;                   //holding number of devices in list  

    printf("start open %d\n", errno);
    if (mUsbFs)
        free(mUsbFs);

    mUsbFs = strdup(usbfs);
    printf("before 11111 errno:%d\n", errno);
    r = libusb_init2(&ctx, usbfs);         //initialize a library session  
    if(r < 0) {  
        printf("Init Error \n"); //there was an error  
        return -1;  
    }  

    usb_dev = libusb_find_device(ctx, vid, pid, NULL, fd);

    if (usb_dev) {
        libusb_set_device_fd(usb_dev, fd);  // assign fd to libusb_device for non-rooted Android devices
        libusb_ref_device(usb_dev);
    }

    printf("before 444444 errno:%d\n", errno);
    r = libusb_open(usb_dev, &dev_handle);
    if(r != LIBUSB_SUCCESS)
    {
        printf("open device err %d\n", errno);
        return -1;
    }

    //libusb_reset_device(dev_handle);
    printf("before scan_audio_interface errno:%d\n", errno);
    if (scan_audio_interface(usb_dev) < 0)
    {
        printf("scan_audio_interface err: errno:%d\n", errno);
        cancel();
        return -1;
    }
    printf("before interface_claim_if errno:%d\n", errno);

    interface_claim_if(dev_handle, interfaceNumber);
}

int UsbAudio::interface_claim_if(libusb_device_handle *dev, int interface_number)
{
    int r = 0;

    r = libusb_kernel_driver_active(dev, interface_number);
    printf("libusb_kernel_driver_active2 %d\n", r);  
    if(r == 1) 
    { //find out if kernel driver is attached  
        printf("Kernel Driver Active\n");  
        if(libusb_detach_kernel_driver(dev, interface_number) == 0) //detach it  
            printf("Kernel Driver Detached!\n&#
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值