android触屏音文件地址,Android音视频-音频采集

Android的音视频开发是我暂定的一个职业发展的一个方向,通过自学记录一些记了又忘记的知识。

音频基础知识

采样率(samplerate)

95a3614ba7524aeb0f330503d87ed692.png

蓝色代表模拟音频信号,红色的点代表采样得到的量化数值。

采用就是把模拟信号数字化的过程,不仅仅是音频需要采样,所有的模拟信号都需要通过采样转换为可以用0101来表示的数字信号。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。

人耳可以听到的声波频率范围?

20-20000Hz。为了保证声音不失真,采样频率应在40kHz以上。

AudioRecord构造参数中的sampleRateInHz。

量化精度(位宽)

上图中,每一个红色的采样点,都需要用一个数值来表示大小,这个数值的数据类型大小可以是:4bit、8bit、16bit、32bit等等,位数越多,表示得就越精细,声音质量自然就越好,当然,数据量也会成倍增大。

AudioRecord构造参数中的audioFormat。

声道数(channels)

由于音频的采集和播放是可以叠加的,因此,可以同时从多个音频源采集声音,并分别输出到不同的扬声器,故声道数一般表示声音录制时的音源数量或回放时相应的扬声器数量。

AudioRecord 构造参数中的channelConfig。

音频帧(frame)

视频我们知道每一帧是一张图片,音频数据是流式的,没有明确的一帧帧的概念,但是在音频处理的时候,一般取2.5ms-60ms为单位数据量的一帧音频。

假设某通道音频信号采样率为8kHz,位宽位16bit,20ms一帧,双通道,那么一帧音频的大小为:

8000*16bit*0.02*2=5120bit=640byte

音频编码

是将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量。模拟的音频信号转换为数字信号需要经过采样和量化,量化的过程被称之为编码,根据不同的量化策略,产生了许多不同的编码方式,常见的编码方式有:PCM 和 ADPCM

为什么要音频编码

存储一秒钟采样率为44.1KHz,位深为16bit,双声道的PCM编码的音频信号,需要

44100*16bit*2 / 8/1024 = 172.2KB的空间,那么1分钟则约为10.09M。

这对大部分用户是不可接受的。

只有2种方法,降低采样指标或者压缩。

音频压缩

降低采样是不可取的,因此就有了各种各样的压缩方式。

有两类主要的音频文件格式:

有损文件格式: 是基于声学心理学的模型,除去人类很难或根本听不到的声音。

无损格式,例如PCM,WAV,ALS,ALAC,TAK,FLAC,APE,WavPack(WV)

有损格式,例如MP3,AAC,WMA,Ogg。

根据采样率和采样大小可以得知,相对自然界的信号,音频编码最多只能做到无限接近,至少目前的技术只能这样了,相对自然界的信号,任何数字音频编码方案都是有损的,因为无法完全还原。在计算机应用中,能够达到最高保真水平的就是PCM编码,被广泛用于素材保存及音乐欣赏,CD、DVD以及我们常见的WAV文件中均有应用。因此,PCM约定俗成了无损编码,因为PCM代表了数字音频中最佳的保真水准,并不意味着PCM就能够确保信号绝对保真,PCM也只能做到最大程度的无限接近。

我们而习惯性的把MP3列入有损音频编码范畴,是相对PCM编码的。

Android如何采集音频

Android SDK对于音频采集提供两套API:MediaRecorder和AudioRecorder,前者是偏上层的一个API,可以直接把手机麦克风录入的音频数据进行编码压缩为AMR,MP3等并保存文件。后者接近底层,可以灵活控制,得到原始的一帧帧PCM音频数据。

当要简单的把数据采集为音频文件,就使用MediaRecorder,如果要对音频做进一步的算法处理就使用AudioRecorder。

什么是PCM音频数据?

PCM(Pulse Code Modulation)也被称为脉冲编码调制。PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。(详细参考)

AudioRecord

简介

AudioRecord输出是PCM语音数据,如果保存成音频文件,是不能够被播放器播放的,所以必须先写代码实现数据编码以及压缩。

AudioRecord适用于对采集的音频数据进行二次处理的,我们首先看到代码AudioRecord类的构造函数。

/**

* Class constructor.

* Though some invalid parameters will result in an {@link IllegalArgumentException} exception,

* other errors do not. Thus you should call {@link #getState()} immediately after construction

* to confirm that the object is usable.

* @param audioSource the recording source.

* See {@link MediaRecorder.AudioSource} for the recording source definitions.

* @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only

* rate that is guaranteed to work on all devices, but other rates such as 22050,

* 16000, and 11025 may work on some devices.

* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value

* which is usually the sample rate of the source.

* {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.

* @param channelConfig describes the configuration of the audio channels.

* See {@link AudioFormat#CHANNEL_IN_MONO} and

* {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is guaranteed

* to work on all devices.

* @param audioFormat the format in which the audio data is to be returned.

* See {@link AudioFormat#ENCODING_PCM_8BIT}, {@link AudioFormat#ENCODING_PCM_16BIT},

* and {@link AudioFormat#ENCODING_PCM_FLOAT}.

* @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written

* to during the recording. New audio data can be read from this buffer in smaller chunks

* than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum

* required buffer size for the successful creation of an AudioRecord instance. Using values

* smaller than getMinBufferSize() will result in an initialization failure.

* @throws java.lang.IllegalArgumentException

*/

public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,

int bufferSizeInBytes)

看这个构造函数的参数的解释可以明白个七七八八。具体的介绍如下:

audioSource

音频采集的输入源,可选的值以常量的形式定义在 MediaRecorder.AudioSource 类中,常用的值包括:DEFAULT(默认),VOICE_RECOGNITION(用于语音识别,等同于DEFAULT),MIC(由手机麦克风输入),VOICE_COMMUNICATION(用于VoIP应用)等等。

sampleRateInHz

采样率,注意,目前44100Hz是唯一可以保证兼容所有Android手机的采样率。

channelConfig

通道数的配置,可选的值以常量的形式定义在 AudioFormat 类中,常用的是 CHANNEL_IN_MONO(单通道),CHANNEL_IN_STEREO(双通道)

audioFormat

这个参数是用来配置“数据位宽”的,可选的值也是以常量的形式定义在 AudioFormat 类中,常用的是 ENCODING_PCM_16BIT(16bit),ENCODING_PCM_8BIT(8bit),注意,前者是可以保证兼容所有Android手机的。

bufferSizeInBytes

配置的是 AudioRecord 内部的音频缓冲区的大小,该缓冲区的值不能低于一帧“音频帧”(Frame)的大小,而前一篇文章介绍过,一帧音频帧的大小计算如下:

int size = 采样率 x 位宽 x 采样时间 x 通道数

在Android开发中,AudioRecord 类提供了一个帮助你确定这个 bufferSizeInBytes 的函数,原型如下:

int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);

不同的厂商的底层实现是不一样的,但无外乎就是根据上面的计算公式得到一帧的大小,音频缓冲区的大小则必须是一帧大小的2~N倍。

使用AudioRecord

操作AudioRecord步骤如下:

配置参数,初始化AudioRecord构造函数

开始采集

开启一个子线程,不断从AudioRecord的缓冲区将音频数据读出来。注意,这个过程一定要及时,否则就会出现“overrun”的错误,该错误在音频开发中比较常见,意味着应用层没有及时地取走音频数据,导致内部的音频缓冲区溢出。

停止采集,释放资源。

示例代码:

注意添加RECORD_AUDIO权限。

点击查看

MediaRecorder

MediaRecorder可以直接把手机麦克风录入的音频数据进行编码压缩为AMR,MP3等并保存文件。

使用MediaRecorder

简单操作使用MediaRecorder类步骤如下:

实例化MediaRecorder对象

使用函数SetAudioSource设置硬件设备为采集音频输入数据

使用函数SetOutputFormat设置输出音频格式。使用类OutputFormat列出支持的输出格式

调用方法SetAudioEncoder方法设置音频编码格式

调用SetOutputFile方法保存输出文件数据的绝对完整路径

调用Prepare方法初始化录制

调用Start方法开始录制

示例代码:

注意添加权限:

WRITE_EXTERNAL_STORAGE;

RECORD_AUDIO;

点击查看

总结

MediaRecorder和AudioRecord都可以录制音频,区别是MediaRecorder录制的音频文件是经过压缩后的,需要设置编码器。并且录制的音频文件可以用系统自带的Music播放器播放。

而AudioRecord录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。

在用MediaRecorder进行录制音视频时,最终还是会创建AudioRecord用来与AudioFlinger进行交互。

C++层MediaRecorder创建AudioRecord类的代码位于AudioSource类构造函数中.

MediaRecorder录制的数据是 amr MP3 格式;AudioRecorder录制出来的是比较原始的PCM音频格式;PCM经过编码压缩可以为 amr MP3 AAC。

优缺点:

AudioRecord

主要是实现边录边播以及对音频的实时处理,这个特性让他更适合在语音方面有优势;

优点:语音的实时处理,可以用代码实现各种音频的封装

缺点:输出是PCM格式文件,如果保存成音频文件,是不能够被播放器播放的,所以必须先写代码实现数据编码以及压缩

MediaRecorder

已经集成了录音、编码、压缩等,支持少量的录音音频格式,大概有,aac,amr,3gp等

优点:集成,直接调用相关接口即可,代码量小

缺点:无法实时处理音频;输出的音频格式不是很多,例如没有输出mp3格式文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/375902.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

平衡二叉树,AVL树之图解篇

学习过了二叉查找树,想必大家有遇到一个问题。例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况。有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本。而只有建立的树如图2,才能…

盒子模型的总结

转载于:https://www.cnblogs.com/zy2012/p/3725677.html

maven generating project in batch mode hang

现象: 执行 archetype:generate 的时候,会产生[INFO] Generating project in Batch mode原因是:网速问题, 解决方法: 设置maven不要从远程服务器上获取catalog,增加参数-DarchetypeCataloginternal 如何在i…

微博 Android 启动广告,使用Xposed去除微博国际版的启动广告

本文同步更新于旺仔的个人博客,访问可能有点慢,多刷新几次。前面有篇文章已经介绍了如何创建Xposed模块的文章了,这篇就让我们来实现一个简单的去除启动广告的功能吧。起因为什么要是要去掉微博国际版的开屏广告呢,因为广告烦人啊…

linux命令:vim文件操作命令、新建用户,查看用户列表,chown命令

命令 简单说明 :w 保存编辑后的文件内容,但不退出vim编辑器。这个命令的作用是把内存缓冲区中的数据写到启动vim时指定的文件中。 :w! 强制写文件,即强制覆盖原有文件。如果原有文件的访问权限不允许写入文件,例如,原有的文件…

cocos2d-x android 环境搭配,cocos2d-x Android环境配置问题和解决方法

1.前提:下载安装Cygwin,并已经在cygwin\home\admin(计算机用户名)下的.bash_profile中完成如下配置:NDK_ROOT /cygdrive/d/cocos2dxdev/andrid-ndk-r8e//NDK安装位置export NDK_ROOT问题:运行cygwin.exe.录入如下的第一行数据后,没…

栈的应用--括号匹配的检验

算法中设置一个栈,每次读入一个括号,若是右括号,则或者与置于栈顶的括号匹配,或者是不合法的情况,若是左括号,则入栈。若算法结束,栈是空的,则括号合法。 括号匹配函数 Status bra…

node.js 初体验

node.js 初体验 2011-10-31 22:56 by 聂微东, 174545 阅读, 118 评论, 收藏, 编辑 PS: ~ 此篇文章的进阶内容在为《Nodejs初阶之express》 ~ 2014/09/24 更新《Express 4.X 启航指南》 欢迎阅读和评论:) 最近写的文章收到许多朋友的反馈,感谢大家的支持和建议&#…

Linux内核3.0移植并基于Initramfs根文件系统启动

Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先,磨刀不误砍柴工。在动手进行linux内核移植之前,我们有必要对linux内核进行一定的了解。…

操作系统上机作业--实现shell(2)(多进程)

sh2.c: 实现shell程序,要求在第1版的基础上,添加如下功能 • 实现文件重定向 • $ echo hello >log • $ cat log • Hello 实现思路: 和sh1.c相比,主要是修改了cmd函数的实现过程。通过循环找出重定向符号"&g…

操作系统上机作业--根据莱布尼兹级数计算PI(1)(多线程)

pi1.c: 使用2个线程根据莱布尼兹级数计算PI • 莱布尼兹级数公式: 1 - 1/3 1/5 - 1/7 1/9 - ... PI/4 • 主线程创建1个辅助线程 • 主线程计算级数的前半部分 • 辅助线程计算级数的后半部分 • 主线程等待辅助线程运行結束后,将前半部分和后半部分相加实现思路&#xff1…

操作系统上机作业--根据莱布尼兹级数计算PI(2)(多线程)

pi2.c: 使用N个线程根据莱布尼兹级数计算PI • 与上一题类似,但本题更加通用化,能适应N个核心,需要使用线程参数来实现 • 主线程创建N个辅助线程 • 每个辅助线程计算一部分任务,并将结果返回 • 主线程等待N个辅助线程…

数组以及冒泡排序

数组 1、概念:可以帮我一次声明多个同类型的变量,这些变量再内存中是连续存储的。 2、声明语法:数据类型[] 数组名 new 数据类型[数组长度] 数组长度:一次要声明的同类型的变量个数。是在定义这个数组的时候就确定了&#xf…

操作系统上机作业--多线程排序

sort.c: 多线程排序 • 主线程创建一个辅助线程 • 主线程使用选择排序算法对数组的前半部分排序 • 辅助线程使用选择排序算法对数组的后半部分排序 • 主线程等待辅助线程运行結束后,使用归并排序算法归并数组的前半部分和后半部分 实现思路: ARRAY_CO…

jdk5下载链接

查看jdk版本 java -versionJDK下载 最新版本http://www.oracle.com/technetwork/java/javase/downloads/index.htmlJDK下载 版本1.5.22http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase5-419410.html#jdk-1.5.0_22-oth-JPR JDK…

html的细节优化,网站页面优化细节详解

原标题:网站页面优化细节详解SEO页面优化是继SEO结构优化之后,另一个重要优化地方;页面标题在每个页面中的关键位置,出现目标关键词,这是我们做页面优化的基础思路,关键词位置,都有哪些呢?第一个是关键位置…

操作系统上机作业--使用条件变量解决生产者、计算者、消费者问题(多线程)

pc1.c: 使用条件变量解决生产者、计算者、消费者问题 /* • 系统中有3个线程:生产者、计算者、消费者 • 系统中有2个容量为4的缓冲区:buffer1、buffer2 • 生产者生产a、b、c、‘d、e、f、g、h八个字符,放入到buffer1 • 计算者从b…

程序各个段text,data,bss,stack,heap

网上找了一堆资料学习一下,了解这些, 有助于规化程序结构,优化代码; 使用gcc编译出来的程序,用size可以查看程序结构和大小, 如 1: #size hello 2: Text data bss dec hex filename 3: 778 200 4 982 3D6 hello 所以一个可执行的程序文件,结构分三部分: .text 代码段,用来存…

操作系统上机作业-- 使用信号量解决生产者、计算者、消费者问题(多线程)

pc2.c: 使用信号量解决生产者、计算者、消费者问题 • 功能和前面的实验相同,使用信号量解决 实现思路: 生产者、计算者、消费者三者之间的关系和上一个编程任务一样,不一样的是,将互斥量、条件变量封装起来作为信号量,处理方…

Singleton 单件

模式分类 从目的来看: -创建型(Creational)模式:负责对象创建 -结构型(Structural)模式:处理类与对象间的组合 -行为型(Behavioral)模式:类与对象交互中的职责…