当前位置: 首页 > news >正文

【Linux开发】基于ALSA库实现音量调节

基于ALSA库实现音量调节

  • ALSA库实现音量调节
    • 1、使用alsamixer工具查看音频接口
    • 2、完整代码
      • 2.1、snd_mixer_open
      • 2.2、snd_mixer_attach、
      • 2.3、snd_mixer_selem_register
      • 2.4、snd_mixer_load
      • 2.5、snd_mixer_first_elem/snd_mixer_elem_next
      • 2.6、snd_mixer_selem_get_playback_volume_range/snd_mixer_selem_get_capture_volume_range
      • 2.7、snd_mixer_selem_set_playback_volume_all
    • 3、完整程序
    • 4、注意细节
      • 4.1、初始化顺序
      • 4.2、声卡设备的选择
      • 4.3、元素查找
      • 4.4、单双通道音量设置

ALSA库实现音量调节

1、使用alsamixer工具查看音频接口

首先可以通过alsamixer工具图形化查看声卡的接口名,也可以使用该工具通过图形尝试调节音频大小,能帮助你后面更好的实现从应用层去调节,直接输入alsamixer即可自动弹出图形界面,如下图,Speaker是我播放的元素名称,上面的55是音量大小,通过键盘的上下键即可调节大小,这两个参数在后面应用层时都会用到:

在这里插入图片描述

2、完整代码

2.1、snd_mixer_open

  • 打开并实例化一个空的混音器

2.2、snd_mixer_attach、

  • 连接到选择的声卡控制设备

2.3、snd_mixer_selem_register

  • 注册混音器
int snd_mixer_selem_register(snd_mixer_t *mixer,struct snd_mixer_selem_regopt *options,snd_mixer_class_t **classp);

2.4、snd_mixer_load

  • 加载混音器

2.5、snd_mixer_first_elem/snd_mixer_elem_next

  • 找到混音器的第一个元素/查找下一个元素

2.6、snd_mixer_selem_get_playback_volume_range/snd_mixer_selem_get_capture_volume_range

  • 获取指定元素的音量范围
int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,long *min,long *max);
int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,long *min,long *max);

2.7、snd_mixer_selem_set_playback_volume_all

  • 一次性设置指定元素所有声道的音量

3、完整程序

下面的函数实现音量的获取和调节,通过ALSA库的API接口,注册一个混音器设备对象,使用该对象连接到想要控制的声卡,然后开始查找该声卡中的元素,找到想要控制的元素,然后对元素进行get和set,本函数实现对Speaker元素的调节控制扬声器声音大小,通过应用程序调节完音量后,可以使用alsamixer工具查看音量是否成功调节。

/* volume control init */
void volume_control_init(void)
{snd_mixer_t *mixer;snd_mixer_elem_t *elem;debug_msg(snd_mixer_open(&mixer,0),"opening mixer"); 						// 打开混音器设备debug_msg(snd_mixer_attach(mixer, "hw:1"),"attaching mixer");			// 连接到默认的声卡debug_msg(snd_mixer_selem_register(mixer, NULL, NULL),"registering mixer");	// 载入声卡配置debug_msg(snd_mixer_load(mixer),"load mixer");// 循环找到自己想要的elementelem = snd_mixer_first_elem(mixer);while(elem){// find element name(此处要找的就是上面看的speaker元素)if(strcmp("Speaker",snd_mixer_selem_get_name(elem)) == 0){printf("elem name : %s\n",snd_mixer_selem_get_name(elem));break;}elem = snd_mixer_elem_next(elem);}if(!elem){printf("snd_mixer_find_selem Error\n");snd_mixer_close(mixer);mixer = NULL;return;}long min, max;snd_mixer_selem_get_playback_volume_range(elem, &min, &max);printf("volume range: %ld -- %ld\n", min, max);long lVal, rVal;snd_mixer_handle_events(mixer); // 确保混音器状态和应用程序状态的同步snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &lVal);snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &rVal);printf("currnet volume: leftVal = %ld, rightVal = %ld\n", lVal, rVal);snd_mixer_selem_set_playback_volume_all(elem, 25);// 释放资源snd_mixer_close(mixer);
}

4、注意细节

4.1、初始化顺序

在初始化混音器设备时,需要先初始化好PCM声卡设备,不然PCM初始化时会重置导致音频设置失效

4.2、声卡设备的选择

程序中通过调用snd_mixer_attach选择声卡设备,选择时需要注意跟PCM选择声卡设备时不同,PCM初始化时选择的是声卡几设备几,比如声卡1,设备0,那么PCM初始化打开设备时要传入snd_pcm_open(&pb_handle, "plughw:1,0",SND_PCM_STREAM_PLAYBACK, 0),而mixer初始化时只需要选择声卡而不用详细到设备,依然是声卡1,设备0,那么mixer连接到声卡时只需要传入snd_mixer_attach(mixer, "hw:1")

4.3、元素查找

在mixer中,有很多的element(元素),也就是最开始通过图形化看到的各种元素,在ALSA中好像没有函数能够直接查找到某个元素,只能通过snd_mixer_first_elem找到第一个元素,然后通过snd_mixer_elem_next开始查找下一个元素一直查下去,直到通过snd_mixer_selem_get_name发现当前的元素是你想要调节的元素为止(你可以选择将这种方式封装起来成为一个能指定查找的函数)。

4.4、单双通道音量设置

你可以通过snd_mixer_selem_is_playback_mono查询该声卡是否是单通道(mono:单,stereo:双),然后通过snd_mixer_selem_set_capture_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume)的第2个参数来指定左右通道的音量,但是我没什么时间深究,所以直接选择snd_mixer_selem_set_capture_volume_all来设置总音量。

同时需要注意一下音量的调节,虽然在alsamixer工具的图形化中可以看到音量能从0调节到100,但是程序中使用snd_mixer_selem_get_playback_volume获取音量时会发现范围在0-30,并且如果你使用amixer get 'DAC HPOUT Left'get一下元素的值查看时就会发现limits的值也为0-30,因此在设置音量时也要注意设置的值不要超过这个范围,不能以图形化中的范围去设置。

root@firefly:~/twoway# amixer get 'DAC HPOUT Left'
Simple mixer control 'DAC HPOUT Left',0Capabilities: volume volume-joinedPlayback channels: MonoCapture channels: MonoLimits: 0 - 30Mono: 30 [100%] [6.00dB]

http://www.lryc.cn/news/392291.html

相关文章:

  • 代理IP在未来将面临哪些挑战?
  • FineBI在线学习资源-数据处理
  • 【代码随想录算法训练营第37期 第四十五天 | LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III】
  • Elasticsearch查询上下文和_source
  • golang实现网卡流量监控
  • 技术分享:直播平台如何开发并接入美颜SDK
  • 左耳听风_114_113_Go编程模式修饰器
  • Java实习手册(小白也看得懂)
  • Elasticsearch 分析器(Analyzer)的作用和配置
  • SpringBoot(一)创建一个简单的SpringBoot工程
  • 简述Vue中的数据双向绑定原理
  • C++STL函数对象的应用
  • AJAX-day1:
  • 昆虫学(书籍学习资料)
  • springboot + mybatis 多数据源切换
  • windows电脑网络重置后wifi列表消失怎么办?
  • Python + 在线 + 文生音,音转文(中文文本转为英文语音,语音转为中文文本)
  • 哏号分治,CF103D - Time to Raid Cowavans
  • 基于深度学习的图像背景剔除
  • Python使用(...)连接字符串
  • 鸿蒙:1.入门
  • 【matlab】智能优化算法——求解目标函数
  • 不改代码,实现web.config或app.config的连接字符串加密解密
  • Python创建MySQL数据库
  • 【C++】unordered系列容器的封装
  • matlab 超越椭圆函数图像绘制
  • 本地文件同步上传到Gitee远程仓库
  • RESTful Web 服务详解
  • 【ARMv8/v9 GIC 系列 5.3 -- 系统寄存器对中断的处理】
  • MUNIK解读ISO26262--系统架构