qemu声卡模拟原理-声音播放(pa+ac97)
连载目录
1.qemu声卡模拟
2.qemu声卡模拟原理-声卡初始化(pa+ac97)
3.qemu声卡模拟原理-声音播放(pa+ac97)
PCM数据
PCM数据格式这里抛砖引玉贴一点别人写的: PCM数据格式介绍更多详细的解释请参考度娘
PCM全称Pulse-Code Modulation,翻译一下是脉冲调制编码。
其实大可以不用关心英文释义,之所以这么命名是因为一些历史原因。
在音视频中,PCM是一种用数字表示采样模拟信号的方法。
要将一段音频模拟信号转换为数字表示,包含如下三个步骤:
Sampling(采样)
Quantization(量化)
Coding(编码)
#### PCM数据常用量化指标
采样率(Sample rate):每秒钟采样多少次,以Hz为单位。
位深度(Bit-depth):表示用多少个二进制位来描述采样数据,一般为16bit。
字节序:表示音频PCM数据存储的字节序是大端存储(big-endian)还是小端存储(little-endian),为了数据处理效率的高效,通常为小端存储。
声道数(channel number):当前PCM文件中包含的声道数,是单声道(mono)、双声道(stereo)?此外还有5.1声道等。
采样数据是否有符号(Sign):要表达的就是字面上的意思,需要注意的是,使用有符号的采样数据不能用无符号的方式播放。
以FFmpeg中常见的PCM数据格式s16le为例:它描述的是有符号16位小端PCM数据。
s表示有符号,16表示位深,le表示小端存储。
PCM采样到编码的过程如下:
qemu播放声音这个部分其实就是围绕PCM数据的转换和播放完成的。
之前声卡初始化说道了SWVoiceOut、HWVoiceOut两个结构体,在讲解声音播放之前有必要先介绍一下这两个对象。
QEMUSoundCard:建模一个给定的模拟的声卡
SWVoiceOut:建模一个来自 QEMUSoundCard 的音频输出
HWVoiceOut:建模一个主机端的音频输出(后端)
虚拟声卡的启动
虚拟声卡由虚拟机内部通过设备驱动启动,主要流程如下:
ac97.c:nabm_write->ac97.c:nabm_writeb->ac97.c:voice_set_active->audio.c:AUD_set_active_out->audio.c:audio_reset_timer
最后audio_reset_timer将启动一个定时器,不停的处理虚拟机发送出来的声音
虚拟声卡数据处理流程
声卡处理声音数据从定时器调用这里开始,主要流程如下:
audio.c:audio_timer->audio.c:audio_run->audio.c:audio_run_out->audio.c:sw->callback.fnac97.c:po_callback->ac97.c:transfer_audio->ac97.c:write_audio->ac97.c:pci_dma_read->audio.c:AUD_write->audio.c:audio_pcm_sw_write->audio.c:st_rate_flow_mixrate_template.h:NAMEaudio.c:audio_pcm_hw_run_outaudio.c:hw->pcm_ops->put_buffer_outac97.c:qpa_get_buffer_outac97.c:qpa_put_buffer_out
以上就是一次完整的声音处理流程,最先是定时器发起处理一次声音,从虚拟机内部读取音频数据,然后交给后端处理。下面详细看一下整个过程。
从虚拟机内部读取音频数据
ac97.c:po_callback到ac97.c:write_audio开始读取虚拟机内部的数据,首先判断虚拟机是否有音频数据,picb为需要读取的数据量,picb由驱动写入,具体逻辑请自行参考ac97芯片手册。然后做数据转换和音量调整
在后面通过一个循环不停的读取并转换数据,直到虚拟机内部的音频数据全部读取出来。pci_dma_read实际上就是根据地址从guest的内存中读取数据,AUD_write完成数据的转换,下面将详细描述数据转换流程。
转换音频数据
音频数据转换首先从audio_pcm_sw_write函数开始,先通过虚拟设备注册的sw->conv做初步转换。
sw的conv函数在audio_template.h中注册的
最后sw->conv = mixeng_conv[1][1][0][1] = conv_natural_int16_t_to_stereo
conv_natural_int16_t_to_stereo在mixeng_template.h中定义实现
这里的音频转换主要是完成PCM格式的转换,比如有些声卡使用浮点格式,有些使用整形格式,最后转换到一个统一的格式处理。具体转换逻辑不做详细分析,请参考芯片手册。
我们来看下音量大小控制,这个逻辑比较通用也比较简单
这里直接将音量大小乘以PCM音频数据便完成了音量的转换。
最后st_rate_flow_mix函数完成PCM的码率转换,源码在rate_template.h中。具体的算法就不详细分析了,比较简单。
播放音频数据
音频数据转换完成后回到audio_run_out函数后面的audio_pcm_hw_run_out开始正真的播放音频数据。
最后通过pa的音频api pa_stream_write播放声音。
qemu声卡模拟原理-声音播放(pa+ac97)相关推荐
- qemu声卡模拟原理-声卡初始化(pa+ac97)
连载目录 1.qemu声卡模拟 2.qemu声卡模拟原理-声卡初始化(pa+ac97) 3.qemu声卡模拟原理-声音播放(pa+ac97) qemu的整个声卡虚拟化都是围绕着audio.c这个文件展 ...
- qemu声卡模拟原理-基本使用方法
连载目录 1.qemu声卡模拟原理-基本使用方法 2.qemu声卡模拟原理-声卡初始化(pa+ac97) 3.qemu声卡模拟原理-声音播放(pa+ac97) qemu版本:5.2.50 qemu声卡 ...
- QEMU 中音频模拟如何工作
事情有点棘手,但这里有一个粗略的描述: QEMUSoundCard:建模一个给定的模拟的声卡 SWVoiceOut:建模一个来自 QEMUSoundCard 的音频输出 SWVoiceIn:建模一个来 ...
- QEMU中音频模拟工作过程(十)
QEMUSoundCard:建模一个给定的模拟的声卡 SWVoiceOut:建模一个来自 QEMUSoundCard 的音频输出 SWVoiceIn:建模一个来自 QEMUSoundCard 的音频输 ...
- 在C#中利用DirectX实现声音播放
在c#中利用directx实现声音播放 我感觉声音的播放比较简单.我们从播放声音开始.为什么我这么觉得?我也不知道. 这里是展示最简单的directx播放声音的例子,我尽量省略了无关的代码.最后的代码 ...
- 「雕爷学编程」Arduino动手做(35)——模拟量声音传感器
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- vm15虚拟机没声音常见解决方法与设置了声卡也没声音
vm虚拟机没声音的常见解决方法 一.vm软件问题 右下角菜单的[虚拟机]>>[设置]或虚拟机选项卡中的[编辑虚拟机设置],在弹出的设置框中,选择[声卡],确保设置如下图,尤其是" ...
- Unity 声音播放控制
1.分为三大类:背景音.音效.对话音 2.将所有声音放到某文件目录下,本文以Resources为例 3.原理是三大类声音中的每个都有对应的AudioSources组件,当本类内切换声音时会自动停止上一 ...
- 声音播放装置及其补偿方法 电容模式, 无电容模式(capless mode)
专利名称:声音播放装置及其补偿方法 技术领域: 本发明涉及一种声音播放装置,尤其涉及一种可对串音现象进行补偿的声音播放 装置. 背景技术: 随着消费性电子产品的普及化,许多应用于消费性的电子产品的周边 ...
最新文章
- git apply、git am打补丁.diff 和 .patch
- 设计模式之单例设计模式(懒汉式)
- erlang精要(4)-列表及运算
- linux删除空行 基本操作
- 基于Adaboost实现鸢尾花数据集分类
- 带权并查集--hdu3047 ZJnu stadium
- Bootstrap 3: 使用注意box-sizing细节及解决方法
- 具有审计表的实体框架
- PHP curl 参数详解
- Oracle每日一题——(1) 启动/停止监听
- 2021-08-22 过滤器实现登录权限拦截
- Android arm64-v8a、armeabi-v7a、armeabi、x86详解
- 根据名称获取对应的拼音码首字母大写
- ringbuffer java例子_Java RingBuffer.publish方法代碼示例
- Java入门(六)MySql 数据库
- 澳洲语言成绩等级c,澳洲本科成绩等级介绍 怎么划分的
- 教你一招永久去除WPS广告
- 职场:狼文化or羊文化
- 怎么在应用中实现自助报表功能?
- 程序员如何在业余时间接单月入过万