alsa音频架构1

本文深入探讨了ALSA(Advanced Linux Sound Architecture)音频架构,从声卡设备类型、声卡结构体、声卡设备创建、注册过程到声卡控制设备的分析。重点介绍了snd_card、snd_device等关键结构体,以及创建和注册设备的过程。同时,文章提到了alsa-utils工具集,如alsamixer、arecord和aplay等,用于与ALSA驱动交互和音量控制。
摘要由CSDN通过智能技术生成

 第一部分 alsa子系统关键结构体对象等

1.声卡设备类型定义

#define	SNDRV_DEV_TOPLEVEL	((__force snd_device_type_t) 0)
#define	SNDRV_DEV_CONTROL	((__force snd_device_type_t) 1)	
#define	SNDRV_DEV_LOWLEVEL_PRE	((__force snd_device_type_t) 2)
#define	SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)
#define	SNDRV_DEV_PCM		((__force snd_device_type_t) 0x1001)
#define	SNDRV_DEV_RAWMIDI	((__force snd_device_type_t) 0x1002)
#define	SNDRV_DEV_TIMER		((__force snd_device_type_t) 0x1003)
#define	SNDRV_DEV_SEQUENCER	((__force snd_device_type_t) 0x1004)
#define	SNDRV_DEV_HWDEP		((__force snd_device_type_t) 0x1005)
#define	SNDRV_DEV_INFO		((__force snd_device_type_t) 0x1006)
#define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
#define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
#define	SNDRV_DEV_JACK      ((__force snd_device_type_t) 0x1009)
#define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)

一个声卡可以有多个声卡设备,alsa中用snd_card描述声卡对象,用snd_device描述声卡设备对象

2.声卡结构体

struct snd_card {
	int number;				//声卡索引号
	char id[16];			//id识别字串
	char driver[16];		//驱动名
	char shortname[32];		//短名
	char longname[80];		//长名
	char mixername[80];		/* mixer name */
	char components[128];	/* card components delimited with space */
	struct module *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;	//设备链表
	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;	//控制链表
	struct list_head ctl_files;	/* active control files */
	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;
	struct device *dev;		//设备文件
	struct device *card_dev;	//声卡设备文件
#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
};


2.1.全局变量snd_cards

在"/sound/core/init.c"

struct snd_card *snd_cards[SNDRV_CARDS];

SNDRV_CARDS为8也就是声卡最多8个

3.声卡设备结构体

struct snd_device {
	struct list_head list;		//链表
	struct snd_card *card;		//所属的声卡
	snd_device_state_t state;	//设备状态
	snd_device_type_t type;		//设备类型
	void *device_data;		/* device structure */
	struct snd_device_ops *ops;	//声卡设备操作函数集
};

3.1 设备状态的值

#define	SNDRV_DEV_BUILD		((__force snd_device_state_t) 0)//创建
#define	SNDRV_DEV_REGISTERED	((__force snd_device_state_t) 1)//注册
#define	SNDRV_DEV_DISCONNECTED	((__force snd_device_state_t) 2)//断开连接

3.2 设备类型
也就是上面 1.声卡设备类型定义 所指定的类型

4.声卡操作函数集

struct snd_device_ops {
	int (*dev_free)(struct snd_device *dev);		//释放
	int (*dev_register)(struct snd_device *dev);	//注册
	int (*dev_disconnect)(struct snd_device *dev);	//断开连接
};


第二部分 声卡

1.声卡创建

传递进来的idx为负值,则系统会分配一个idx作为全局snd_cards数组的索引项值,xid字串用来区分描述声卡id,module一般为THIS_MODULE...

int snd_card_create(int idx, const char *xid,struct module *module, int extra_size,struct snd_card **card_ret)
{
	struct snd_card *card;
	int err, idx2;
	if (snd_BUG_ON(!card_ret))
		return -EINVAL;
	*card_ret = NULL;
	if (extra_size < 0)
		extra_size = 0;
	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);	//分配声卡对象和额外空间的内存
	if (!card)
		return -ENOMEM;
	if (xid)	//若需要填充声卡id识别字串
		strlcpy(card->id, xid, sizeof(card->id));	//card->id=xid 声卡id识别字串
	err = 0;
	
	mutex_lock(&snd_card_mutex);	//idx为负值则交由系统选择一个值______________________<
	if (idx < 0) {	
		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
			/* idx == -1 == 0xffff means: take any free slot */
			if (~snd_cards_lock & idx & 1<<idx2) {
				if (module_slot_match(module, idx2)) {
					idx = idx2;
					break;
				}
			}
	}
	if (idx < 0) {
		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
			/* idx == -1 == 0xffff means: take any free slot */
			if (~snd_cards_lock & idx & 1<<idx2) {
				if (!slots[idx2] || !*slots[idx2]) {
					idx = idx2;
					break;
				}
			}
	}
	if (idx < 0)
		err = -ENODEV;
	else if (idx < snd_ecards_limit) {
		if (snd_cards_lock & (1 << idx))
			err = -EBUSY;	/* invalid */
	} else if (idx >= SNDRV_CARDS)
		err = -ENODEV;
	if (err < 0) {
		mutex_unlock(&snd_card_mutex);
		snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",idx, snd_ecards_limit - 1, err);
		goto __error;
	}
	snd_cards_lock |= 1 << idx;		/* lock it */
	if (idx >= snd_ecards_limit)
		snd_ecards_limit = idx + 1; /* increase the limit */
	mutex_unlock(&snd_card_mutex);		//______________________>
	
	card->number = idx;		//声卡对象索引号 全局数组snd_cards的数组下标
	card->module = module;	//声卡对象模块所有者THIS_MODULE
	INIT_LIST_HEAD(&card->devices);	//初始化声卡设备链表
	init_rwsem(&card->controls_rwsem);	//初始化读写信号量
	rwlock_init(&card->ctl_files_rwlock);	//初始化读写锁
	INIT_LIST_HEAD(&card->controls);	//初始化声卡控制链表
	INIT_LIST_HEAD(&card->ctl_files);	//初始化声卡控制文件链表
	spin_lock_init(&card->files_lock);	//初始化自旋锁
	INIT_LIST_HEAD(&card->files_list);	//初始化声卡文件链表
	init_waitqueue_head(&card->shutdown_sleep);	//初始化关机队列头
#ifdef CONFIG_PM
	mutex_init(&card->power_lock);	//初始化电源互斥锁
	init_waitqueue_head(&card->power_sleep);	//初始化睡眠等待队列头
#endif
	err = snd_ctl_create(card);	//创建用于控制的声卡设备对象
	if (err < 0) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值