嵌入式 pcm音频二

原创 2013年12月02日 14:51:33

4. 设备文件节点的建立(dev/snd/pcmCxxDxxp、pcmCxxDxxc)


4.1 struct snd_minor

每个snd_minor结构体保存了声卡下某个逻辑设备的上下文信息,他在逻辑设备建立阶段被填充,在逻辑设备被使用时就可以从该结构体中得到相应的信息。pcm设备也不例外,也需要使用该结构体。该结构体在include/sound/core.h中定义。

 

[c-sharp] view plaincopy
  1. struct snd_minor  
  2.     int type;             
  3.     int card;             
  4.     int device;           
  5.     const struct file_operations *f_ops;      
  6.     void *private_data;       
  7.     struct device *dev;       
  8. };  

在sound/sound.c中定义了一个snd_minor指针的全局数组:

 

[c-sharp] view plaincopy
  1. static struct snd_minor *snd_minors[256];  

前面说过,在声卡的注册阶段(snd_card_register),会调用pcm的回调函数snd_pcm_dev_register(),这个函数里会调用函数snd_register_device_for_dev():

 

[c-sharp] view plaincopy
  1. static int snd_pcm_dev_register(struct snd_device *device)  
  2.  
  3.     ......  
  4.   
  5.       
  6.     err snd_register_device_for_dev(devtype, pcm->card,  
  7.                          pcm->device,  
  8.                     &snd_pcm_f_ops[cidx],  
  9.                     pcm, str, dev);  
  10.     ......  
  11.  

我们再进入snd_register_device_for_dev():

 

[c-sharp] view plaincopy
  1. int snd_register_device_for_dev(int type, struct snd_card *card, int dev,  
  2.                 const struct file_operations *f_ops,  
  3.                 void *private_data,  
  4.                 const char *name, struct device *device)  
  5.  
  6.     int minor;  
  7.     struct snd_minor *preg;  
  8.   
  9.     if (snd_BUG_ON(!name))  
  10.         return -EINVAL;  
  11.     preg kmalloc(sizeof *preg, GFP_KERNEL);  
  12.     if (preg == NULL)  
  13.         return -ENOMEM;  
  14.     preg->type type;  
  15.     preg->card card card->number -1;  
  16.     preg->device dev;  
  17.     preg->f_ops f_ops;  
  18.     preg->private_data private_data;  
  19.     mutex_lock(&sound_mutex);  
  20. #ifdef CONFIG_SND_DYNAMIC_MINORS  
  21.     minor snd_find_free_minor();  
  22. #else  
  23.     minor snd_kernel_minor(type, card, dev);  
  24.     if (minor >= && snd_minors[minor])  
  25.         minor -EBUSY;  
  26. #endif  
  27.     if (minor 0)  
  28.         mutex_unlock(&sound_mutex);  
  29.         kfree(preg);  
  30.         return minor;  
  31.      
  32.     snd_minors[minor] preg;  
  33.     preg->dev device_create(sound_class, device, MKDEV(major, minor),  
  34.                   private_data, "%s"name);  
  35.     if (IS_ERR(preg->dev))  
  36.         snd_minors[minor] NULL;  
  37.         mutex_unlock(&sound_mutex);  
  38.         minor PTR_ERR(preg->dev);  
  39.         kfree(preg);  
  40.         return minor;  
  41.      
  42.   
  43.     mutex_unlock(&sound_mutex);  
  44.     return 0;  
  45.  
  • 首先,分配并初始化一个snd_minor结构中的各字段
    • type:SNDRV_DEVICE_TYPE_PCM_PLAYBACK/SNDRV_DEVICE_TYPE_PCM_CAPTURE
    • card: card的编号
    • device:pcm实例的编号,大多数情况为0
    • f_ops:snd_pcm_f_ops
    • private_data:指向该pcm的实例
  • 根据type,card和pcm的编号,确定数组的索引值minor,minor也作为pcm设备的此设备号
  • 把该snd_minor结构的地址放入全局数组snd_minors[minor]中
  • 最后,调用device_create创建设备节点

4.2 设备文件的建立

 


 

在4.1节的最后,设备文件已经建立,不过4.1节的重点在于snd_minors数组的赋值过程,在本节中,我们把重点放在设备文件中。

 

回到pcm的回调函数snd_pcm_dev_register()中:

 

[c-sharp] view plaincopy
  1. static int snd_pcm_dev_register(struct snd_device *device)  
  2.  
  3.     int cidx, err;  
  4.     char str[16];  
  5.     struct snd_pcm *pcm;  
  6.     struct device *dev;  
  7.   
  8.     pcm device->device_data;  
  9.          ......  
  10.     for (cidx 0; cidx 2; cidx++)  
  11.                   ......  
  12.         switch (cidx)  
  13.         case SNDRV_PCM_STREAM_PLAYBACK:  
  14.             sprintf(str, "pcmC%iD%ip"pcm->card->number, pcm->device);  
  15.             devtype SNDRV_DEVICE_TYPE_PCM_PLAYBACK;  
  16.             break 
  17.         case SNDRV_PCM_STREAM_CAPTURE:  
  18.             sprintf(str, "pcmC%iD%ic"pcm->card->number, pcm->device);  
  19.             devtype SNDRV_DEVICE_TYPE_PCM_CAPTURE;  
  20.             break 
  21.          
  22.           
  23.         dev pcm->dev;  
  24.         if (!dev)  
  25.             dev snd_card_get_device_link(pcm->card);  
  26.           
  27.         err snd_register_device_for_dev(devtype, pcm->card,  
  28.                           pcm->device,  
  29.                           &snd_pcm_f_ops[cidx],  
  30.                           pcm, str, dev);  
  31.                   ......  
  32.      
  33.          ......  
  34.  

 

以上代码我们可以看出,对于一个pcm设备,可以生成两个设备文件,一个用于playback,一个用于capture,代码中也确定了他们的命名规则:

  • playback  --  pcmCxDxp,通常系统中只有一各声卡和一个pcm,它就是pcmC0D0p
  • capture  --  pcmCxDxc,通常系统中只有一各声卡和一个pcm,它就是pcmC0D0c

snd_pcm_f_ops

 

snd_pcm_f_ops是一个标准的文件系统file_operations结构数组,它的定义在sound/core/pcm_native.c中:

 

[c-sharp] view plaincopy
  1. const struct file_operations snd_pcm_f_ops[2]  
  2.      
  3.         .owner        THIS_MODULE,  
  4.         .write        snd_pcm_write,  
  5.         .aio_write        snd_pcm_aio_write,  
  6.         .open         snd_pcm_playback_open,  
  7.         .release      snd_pcm_release,  
  8.         .llseek       no_llseek,  
  9.         .poll         snd_pcm_playback_poll,  
  10.         .unlocked_ioctl   snd_pcm_playback_ioctl,  
  11.         .compat_ioctl     snd_pcm_ioctl_compat,  
  12.         .mmap         snd_pcm_mmap,  
  13.         .fasync       snd_pcm_fasync,  
  14.         .get_unmapped_area    snd_pcm_get_unmapped_area,  
  15.     },  
  16.      
  17.         .owner        THIS_MODULE,  
  18.         .read         snd_pcm_read,  
  19.         .aio_read     snd_pcm_aio_read,  
  20.         .open         snd_pcm_capture_open,  
  21.         .release      snd_pcm_release,  
  22.         .llseek       no_llseek,  
  23.         .poll         snd_pcm_capture_poll,  
  24.         .unlocked_ioctl   snd_pcm_capture_ioctl,  
  25.         .compat_ioctl     snd_pcm_ioctl_compat,  
  26.         .mmap         snd_pcm_mmap,  
  27.         .fasync       snd_pcm_fasync,  
  28.         .get_unmapped_area    snd_pcm_get_unmapped_area,  
  29.      
  30. };  

snd_pcm_f_ops作为snd_register_device_for_dev的参数被传入,并被记录在snd_minors[minor]中的字段f_ops中。最后,在snd_register_device_for_dev中创建设备节点:

 

[c-sharp] view plaincopy
  1. snd_minors[minor] preg;  
  2. preg->dev device_create(sound_class, device, MKDEV(major, minor),  
  3.               private_data, "%s"name);  

 

相关文章推荐

嵌入式 wave文件(*.wav)格式、PCM数据格式收藏

1. 音频简介   经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等. 44100HZ 16bit stereo: 每秒钟有 441...
  • skdkjxy
  • skdkjxy
  • 2013年12月02日 14:56
  • 943

嵌入式linux中PCM音频编程实践

嵌入式设备中经常需要用的音频,音频设备最原始的数据格式就是PCM,也就是大家常见的WAV,在linux中,音频编程使用最多的就是alsa框架,下面就来看一下pcm音频的编程实例吧。     首先需要...
  • cjyusha
  • cjyusha
  • 2016年01月11日 11:09
  • 2411

嵌入式音频播放的实现

1.PCM(脉冲编码调制)技术及声波的数字化我们知道声音是一种连续变化的波形,是模拟信号,而我们的计算机或者说MCU存储及使用的都是二进制数字信号,所以我们需要对声音信号进行一些处理,这里便使用到了P...
  • YCM888
  • YCM888
  • 2017年07月15日 10:40
  • 52

嵌入式 hi3518c音频模块相关常识

AUDIO: AUDIO模块包括音频输入、音频输出、音频编码、音频解码四个子模块。音频输入和输出模块通过对Hi35xx芯片SIO接口的控制实现音频输入输出功能。音频编码和解码模块提供对G711、G7...
  • skdkjxy
  • skdkjxy
  • 2014年02月11日 10:04
  • 4209

嵌入式音频播放器

  • 2014年04月23日 21:54
  • 2.89MB
  • 下载

嵌入式音频

  • 2014年06月12日 18:38
  • 411KB
  • 下载

初学音视频(二)-PCM音频采样数据处理

PCM音频采样数据处理(该阶段是处于音频解码——— >播放阶段) 基本概念:         pcm编码格式的概念:pcm编码的概念  ,pcm是音频编码的一种,想wav就是用没有压缩过的pcm编码+...

Linux openwrt 树莓派 香蕉派 嵌入式 usb 声卡 PCM2704 2705 2706 CM108 PCM2704/2705/2706 linux专用声卡 专用usb声卡

Linux openwrt 树莓派 香蕉派 嵌入式 usb 声卡 PCM2704 2705 2706  CM108 PCM2704/2705/2706  最近在鼓捣linux,打算用USB声卡录制监...
  • vbvcde
  • vbvcde
  • 2017年02月20日 15:39
  • 736
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 pcm音频二
举报原因:
原因补充:

(最多只允许输入30个字)