linux音频子系统
来源:互联网 发布:有哪些很污的淘宝店铺 编辑:程序博客网 时间:2024/06/05 03:18
音频相关术语
PCM(Pulse Code Modulation)
脉冲编码调制,对连续变化的模拟信号进行抽样、量化和编码,在驱动中一般音频流设备都称为pcm设备I2S
I2S是对PCM格式的数据进行规范化,可以说是PCM的子集,I2S只有左右两通道数据TDM(Time Division Multiplexing)
时分复用,可以用单根线传送多通道数据midi(Musical Instrument Digital Interface)
MIDI是编曲界最广泛的音乐标准格式,可称为“计算机能理解的乐谱”。它用音符的数字控制信号来记录音乐。一首完整的MIDI音乐只有几十KB大,而能包含数十条音乐轨道。几乎所有的现代音乐都是用MIDI加上音色库来制作合成的。MIDI 传输的不是声音信号, 而是音符、控制参数等指令, 它指示MIDI 设备要做什么,怎么做, 如演奏哪个音符、多大音量等。timer(音序器)
音序器,又称声音序列发生器,可将所有MIDI通道中的演奏信息同时自动播放演奏
驱动架构图
OSS(Open Sound System),linux以前的驱动架构,现在已废弃不用
linux目前的音频框架为ALSA(Advanced Linux Sound Architecture),框架如下图所示,分三层,其中ASoc适用于目前的嵌入式设备,在ALSA-core基础上又分出一个小架构
其中alsa-core层的主要结构如下,一个声卡用snd_card来表示,在一个声卡上可能集成了好几个子设备,每个子设备负责不用的功能,分为pcm/control/midi/timer等
声卡结构体
一个声卡下是由多个设备的,总声卡用结构体snd_card来表示,各个子设备用结构体snd_device来抽象,当然对于具体的子设备,还会有相应的结构体来表示,这个会在子设备的文章中详细介绍
snd_card
(include/sound/core.h)
struct snd_card { int number; /* number of soundcard (index to snd_cards) */ char id[16]; /* id string of this card */ char driver[16]; /* driver name */ char shortname[32]; /* short name of this soundcard */ char longname[80]; /* name of this soundcard */ char mixername[80]; /* mixer name */ char components[128]; /* card components delimited with space */ struct module *module; /* top-level module */ void *private_data; /* private data for soundcard */ void (*private_free) (struct snd_card *card); /* callback for freeing of private data */ struct list_head devices; /* devices */---------snd_device加入此链表 unsigned int last_numid; /* last used numeric ID */ struct rw_semaphore controls_rwsem; /* controls list lock */ rwlock_t ctl_files_rwlock; /* ctl_files list lock */ int controls_count; /* count of all controls */ int user_ctl_count; /* count of all user controls */ struct list_head controls; /* all controls for this card */---控制设备snd_device加入此链表 struct list_head ctl_files; /* active control files */ struct mutex user_ctl_lock; /* protects user controls against concurrent access */ struct snd_info_entry *proc_root; /* root for soundcard specific files */ struct snd_info_entry *proc_id; /* the card id */ struct proc_dir_entry *proc_root_link; /* number link to real id */ struct list_head files_list; /* all files associated to this card */ struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */ spinlock_t files_lock; /* lock the files for this card */ int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */#ifdef CONFIG_PM unsigned int power_state; /* power state */ struct mutex power_lock; /* power lock */ wait_queue_head_t power_sleep;#endif#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) struct snd_mixer_oss *mixer_oss; int mixer_oss_change_count;#endif};
snd_device
(include/sound/core.h)
struct snd_device { struct list_head list; /* list of registered devices */---加入声卡的链表节点 struct snd_card *card; /* card which holds this device */-对应的声卡 snd_device_state_t state; /* state of the device */ snd_device_type_t type; /* device type */ void *device_data; /* device structure */------------对于具体子设备的私有数据 struct snd_device_ops *ops; /* operations */------------------对子设备注册的操作};
声卡注册
snd_card_register
(sound/core/init.c)
int snd_card_register(struct snd_card *card){ int err; if (snd_BUG_ON(!card)) return -EINVAL; if (!card->card_dev) { card->card_dev = device_create(sound_class, card->dev, MKDEV(0, 0), card, "card%i", card->number);---注册声卡 if (IS_ERR(card->card_dev)) card->card_dev = NULL; } if ((err = snd_device_register_all(card)) < 0)-----注册声卡下的所有子设备 return err; mutex_lock(&snd_card_mutex); if (snd_cards[card->number]) { /* already registered */ mutex_unlock(&snd_card_mutex); return 0; } if (*card->id) { /* make a unique id name from the given string */ char tmpid[sizeof(card->id)]; memcpy(tmpid, card->id, sizeof(card->id)); snd_card_set_id_no_lock(card, tmpid, tmpid); } else { /* create an id from either shortname or longname */ const char *src; src = *card->shortname ? card->shortname : card->longname; snd_card_set_id_no_lock(card, src, retrieve_id_from_card_name(src)); } snd_cards[card->number] = card; mutex_unlock(&snd_card_mutex); init_info_for_card(card);#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);#endif if (card->card_dev) { err = device_create_file(card->card_dev, &card_id_attrs); if (err < 0) return err; err = device_create_file(card->card_dev, &card_number_attrs); if (err < 0) return err; } return 0;}
snd_device_register_all
int snd_device_register_all(struct snd_card *card){ struct snd_device *dev; int err; if (snd_BUG_ON(!card)) return -ENXIO; list_for_each_entry(dev, &card->devices, list) {----遍历声卡的设备链表 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { if ((err = dev->ops->dev_register(dev)) < 0) return err;-----------------调用每个设备注册函数,进行注册 dev->state = SNDRV_DEV_REGISTERED; } } return 0;}
change log
- linux音频子系统
- linux音频子系统
- linux音频子系统
- linux音频子系统
- Linux ALSA音频框架分析二:linux音频子系统介绍
- linux 音频子系统学习及软件安装
- Linux内核工程导论——硬件:音频子系统
- Linux音频子系统-转自droidphone的CSDN博客
- Linux内核架构 Linux设备驱动 Linux电源管理 Linux音频子系统 Linux中断子系统 Linux时间管理系统 Linux输入子系统
- Android音频子系统,音频流(六)
- Android 音频子系统简要介绍
- linux驱动由浅入深系列:tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音频子系统之一
- Linux子系统
- Linux子系统
- Linux子系统系列-时钟子系统
- Linux 输入子系统 input 子系统
- android 音频子系统框架(一)
- android 音频子系统-AudioFlinger(二)
- 《设计模式》学习笔记1——七大面向对象设计原则
- Linux部署以及常规使用
- 关于curl 采集时候乱码的问题
- HDOJ2008 数值统计
- 来到CSDN
- linux音频子系统
- MyBatis源码(四)之mapper文件解析和动态Sql解析启动阶段
- Mac Android studio插件GsonFormat的使用
- kickstart安装centos6.5
- mySql 修改字段自增
- Hadoop
- shell学习二十一--使用if编写mysql启动脚本
- HDOJ2009 求数列的和
- 快速幂&&快速计算(a*b)mod m