Android 深入系统完全讲解(24)

news2024/9/24 8:24:18

https://blog.csdn.net/weixin_41101173/article/details/80374455
理解了绘制内容,解决了这部分,下来我们来说说关于音视频的其他部分。
所有的文件,都有一个叫做格式的东西存在,MP3,WAV,而处理这个格式的东西,就是解
码器。音频解码器,和视频解码器。
在这里插入图片描述
音频解码出来,只需要播放就可以。
视频解码出来,就是一帧帧画面,这时候就需要绘制配合。

AudioRecord 录音
AudioRecord 的主要作用是让 Java 应用方便的管理音频资源,以便通过此类录制平台的声
音,输出声音。
开始录音的时候,需要一个 buffer 进行缓存音频数据,声音会从硬件中独处,数据大小不超
过 buffer 的大小。
采集的过程比较简单,主要分为几部分:

1 麦克风作为音源
2 采样率,这个代表采集的数据大小,采样率越高,质量越好,存储越大。
3 单声道还是双声道
4 PCM 原式格式,可以转化为 WAV,这是最简单的转化
5 缓存区,可以使用 AudioRecord.getMinBufferSize 获取最小的缓冲区
我们看下代码:
//音频输入-麦克风
private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
//采用频率
//44100 是目前的标准,但是某些设备仍然支持 22050,16000,11025
//采样频率一般共分为 22.05KHz、44.1KHz、48KHz 三个等级
private final static int AUDIO_SAMPLE_RATE = 16000;
//声道 单声道
private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
//编码
private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
// 获得缓冲区字节大小
bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING);
audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes);
this.fileName = fileName;
然后进行启动:
audioRecord.startRecording();
监听数据:
readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
将数据存储起来,当前的格式默认是 PCM,也就是麦克输入的原始格式,但是存储的时候
如果存出这个格式,播放器是不识别的,所以需要转化。
默认的转化格式是 WAV,最简单的一种。
/**

  • 将一个 pcm 文件转化为 wav 文件
  • @param pcmPath pcm 文件路径
  • @param destinationPath 目标文件路径(wav) * @param deletePcmFile 是否删除源文件
  • @return
    /
    public static boolean makePCMFileToWAVFile(String pcmPath, String destinationPath, boolean deletePcmFile) {byte buffer[] = null;
    int TOTAL_SIZE = 0;
    File file = new File(pcmPath);
    if (!file.exists()) {
    return false;
    }
    TOTAL_SIZE = (int) file.length();
    // 填入参数,比特率等等。这里用的是 16 位单声道 8000 hz
    WaveHeader header = new WaveHeader();
    // 长度字段 = 内容的大小(TOTAL_SIZE) +
    // 头部字段的大小(不包括前面 4 字节的标识符 RIFF 以及 fileLength 本身的 4 字节)
    header.fileLength = TOTAL_SIZE + (44 - 8);
    header.FmtHdrLeth = 16;
    header.BitsPerSample = 16;
    header.Channels = 2;
    header.FormatTag = 0x0001;
    header.SamplesPerSec = 8000;
    header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
    header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
    header.DataHdrLeth = TOTAL_SIZE;
    byte[] h = null;
    try {
    h = header.getHeader();
    } catch (IOException e1) {
    Log.e(“PcmToWav”, e1.getMessage());
    return false;
    }
    if (h.length != 44) // WAV 标准,头部应该是 44 字节,如果不是 44 个字节则不进行转换
    文件
    return false;
    // 先删除目标文件
    File destfile = new File(destinationPath);
    if (destfile.exists())
    destfile.delete();
    // 合成的 pcm 文件的数据,写到目标文件
    try {
    buffer = new byte[1024 * 4]; // Length of All Files, Total Size
    InputStream inStream = null;
    OutputStream ouStream = null;
    ouStream = new BufferedOutputStream(new FileOutputStream(
    destinationPath));
    ouStream.write(h, 0, h.length);
    inStream = new BufferedInputStream(new FileInputStream(file));
    int size = inStream.read(buffer);
    while (size != -1) {
    ouStream.write(buffer);
    size = inStream.read(buffer);
    }
    inStream.close();
    ouStream.close();
    } catch (FileNotFoundException e) {
    Log.e(“PcmToWav”, e.getMessage());
    return false;
    } catch (IOException ioe) {
    Log.e(“PcmToWav”, ioe.getMessage());
    return false;
    }
    if (deletePcmFile) {
    file.delete();
    }
    return true;
    }
    使用 AudioRecord 操作的是原始的数据,下面我们看下使用 MediaRecorder 进行操作。
    mMediaRecorder = new MediaRecorder();
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
    /
  • ② 设 置 输 出 文 件 的 格 式 : THREE_GPP/MPEG-4/RAW_AMR/Default
    THREE_GPP(3gp 格式
  • ,H263 视频/ARM 音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要
    求为 AMR_NB) /
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    /
    ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采
    /
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    fileName = DateFormat.format(“yyyyMMdd_HHmmss”, Calendar.getInstance(Locale.CHINA)) + “.m4a”;
    if (!FileUtils.isFolderExist(FileUtils.getFolderName(audioSaveDir))) {FileUtils.makeFolders(audioSaveDir);
    }
    filePath = audioSaveDir + fileName;
    /
    ③准备 /
    mMediaRecorder.setOutputFile(filePath);
    mMediaRecorder.prepare();
    /
    ④开始 */
    mMediaRecorder.start();
    MediaRecorder 录音的格式比较固定,同时不能够暂停,相对来说操作简单,但是功能也
    比较简单。
    完成了录音,我们来说下如何播放。

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

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

相关文章

zookeeper集群安装

zookeeper集群安装 1. 安装环境介绍 下载地址: http://archive.apache.org/dist/zookeeper/ 安装版本: 3.7.0 安装包: apache-zookeeper-3.7.0-bin.tar.gz 安装目录: /opt 机器IP: 10.28.19.107 10.28.19.108 10…

字符矩阵内单词搜索

单词搜索 问题链接:word search!!! 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通…

【阅读笔记】c++ Primer Plus——第九章

内存模型和命名空间 单独编译 c程序分成三部分 第一部分:包含结构声明和使用这些结构的函数原型(头文件)第二部分:包含与结构有关的函数代码(源代码文件)第三部分:包含调用与结构相关的函数代码(源代码文件)头文件包含了用户定义类型的定义…

FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(二)

第七章 实战项目提升,完善简历 19.OV7725摄像头实时采集送HDMI显示(二) 在正式介绍OV7725 CMOS Sensor视频采集前,首先需要去详细说明OV7725的寄存器配置接口,这里有OmniVision公司推出的官方手册 “OV7725_software_…

8个必须掌握的Blender拓扑技巧

组合 3D 模型的过程对后续过程影响很大 - 稍后编辑的难易程度、应用光照和着色器时的外观效果如何、动画时变形的难易程度等等。 一个好的模型对于 CG 管道的所有其他部分的良好运行至关重要。 另一方面,凌乱的拓扑结构会使流程的其余部分成为一场灾难。 你能做些…

IB地理科补习有用吗?

IB地理科的补习如何帮助学生改变学科的表现?这可以从几方面来做分析。 1. 训练 第一是训练。我们老师会按来补习的同学的个人需求、时间和个性,提供很多不同程度的训练,帮助他们建立一个正确的能力系统(skill set)去应…

二、预训练模型预测(Datawhale组队学习)

文章目录安装配置环境ImageNet预训练图像分类模型预测单张图像-英文载入预训练图像分类模型图像预处理执行图像分类预测预测结果分析ImageNet预训练图像分类模型预测单张图像-中文预训练图像分类模型图像预处理执行图像分类预测预测结果分析ImageNet预训练图像分类模型预测视频…

汽车CAN总线硬件电路原理

根据ISO 11898的定义,物理层被细分成3 个子层,它们分别是物理信令(位编码定时和同步)、物理媒体连接(驱动器和接收器特性)和媒体相关接口(总线连接器)。物理信令子层和数据链路层之间…

打包iOS App并上架到TestFlight测试

开发者账号 首先需要注册一个开发者账号,不然什么都免谈。在手机Apple Developer上注册给钱就行了,个人开发者一年688元。 打包App App开发好后,就可以通过XCode打包。打包前选好版本号,不要跟以前提交的一样,重复的…

亚马逊云科技携手普华永道,助力泉峰集团破解数据治理与使用难题

大数据时代的到来,掀起了企业数字化转型的热潮,对于制造行业的企业来说,除了顺应发展潮流快速开启数字转型之外,以创新思维不断拓展业务广度,对于自身发展也有着格外重要的意义。数字化水平能否与创新发展的脚步保持一…

Acwing---1237.螺旋折线

螺旋折线1.题目2.基本思想3.代码实现1.题目 如下图所示的螺旋折线经过平面上所有整点恰好一次。 对于整点 (X,Y)(X,Y)(X,Y),我们定义它到原点的距离 dis(X,Y)dis(X,Y)dis(X,Y) 是从原点到 (X,Y)(X,Y)(X,Y) 的螺旋折线段的长度。 例如 dis(0,1)3,dis(−2,−1)9di…

账户系统从0到1搭建

一、什么是账户/账户的作用?账户是记录账户所属人(账户主体)资产增减变化的载体,简单来说账户系统就是用来记账的,这也是账户系统最核心的功能,在这个基础之上也会根据业务需要衍生出来的其他附属功能。为了…

Kotlin 元编程之 KSP 实战:通过自定义注解配置Compose导航路由

在上一篇 Kotlin 元编程之 KSP 全面突破 中,通过几个设计模式相关的例子来生成代码,其逻辑都比较简单,没有涉及到Android相关的API 业务类,而本文的例子会涉及到使用 Android API 相关的代码。 在之前Jetpack Compose中的导航路由…

【MySQL进阶】MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!)

【MySQL进阶】MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!) 参考资料: 美团技术团队:Innodb中事务隔离级别和锁的关系 数据库的锁,到底锁的是什么? 阿里面试:说说…

来给博客除草了:Learned Indexes for a Google-scale Disk-based Database

1. 引言 这是一篇业界发表在NeurlIPS 2020的Wip论文《Google规模的基于磁盘的数据库的学习索引》。自从学习索引祖师爷Tim KraskaMIT在SIGMOD 2018发表了第一篇learned index的工作之后,有关学习索引的paper呈现 increasing trend。目前,较多的工作focu…

Java基础漏洞(四)

(1)递归调用的内存 我们定义一个类A,在类A中定义方法test来验证递归。在程序中,当条件符合的时候会不断的递归,只有遇到终止条件时才不再递归,然后便会执行递归语句之下的语句。 如以下程序:当…

高效节能 | 智慧灯杆综合管理解决方案

智慧灯杆的应用越来越广泛,园区、景区、道路照明,三站一场等户外场所大规模铺设路灯,通过智慧物联平台远程控制,可以实现高效节能和智能化运维管理。以解决传统运维管理中,不同路线路灯设备控制不统一,设备…

Yjs解析

本文引用自 摸鱼wiki 1. YATA算法解析 YATA算法是Yjs库的核心冲突解决算法,这里主要讲解下这个算法成立的三个规则: 规则1:禁止发生冲突的插入操作之间的origin连线(红线)发生交叉。 如上图所示,图中展示…

IDEA创建SpringBoot的Web项目,并使用外部Tomcat

IDEA创建SpringBoot的Web项目,并使用外部Tomcat 目录IDEA创建SpringBoot的Web项目,并使用外部Tomcat一、创建工程二、使用外部Tomcat一、创建工程 1.首先新建一个springboot的war工程,并且将外部的Tomcat整合进我们的idea中,我们…

GW1NSR-LV4CQN48GC6/I5 FPGA呼吸灯

环境 pwm.v $ cat pwm.v module Pwm( input clk, input [31:0] period, input [31:0] duty, output pwmout ); reg [31:0] counter; reg r_pwmout; always (posedge clk) begin if(counter < duty) begin r_pwmout 1; end…