Android 使用AudioRecord录音相关和音频文件的封装

2023-05-16

在Android中录音可以用MediaRecord录音,操作比较简单。但是不够专业,就是不能对音频进行处理。如果要进行音频的实时的处理或者音频的一些封装

就可以用AudioRecord来进行录音了。

这里给出一段代码。实现了AudioRecord的录音和WAV格式音频的封装。

用AudioTrack和AudioTrack类可以进行边录边播,可以参考:http://blog.sina.com.cn/s/blog_6309e1ed0100j1rw.html

我们这里的代码没有播放。但是有封装和详解,如下:

package com.ppmeet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;

/**
 * class name:TestAudioRecord<BR>
 * class description:用AudioRecord来进行录音<BR>
 * PS: <BR>
 * 
 * @version 1.00 2011/09/21
 * @author CODYY)peijiangping
 */
public class TestAudioRecord extends Activity {
	// 音频获取源
	private int audioSource = MediaRecorder.AudioSource.MIC;
	// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
	private static int sampleRateInHz = 44100;
	// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
	private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
	// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
	private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
	// 缓冲区字节大小
	private int bufferSizeInBytes = 0;
	private Button Start;
	private Button Stop;
	private AudioRecord audioRecord;
	private boolean isRecord = false;// 设置正在录制的状态
	//AudioName裸音频数据文件
	private static final String AudioName = "/sdcard/love.raw";
	//NewAudioName可播放的音频文件
	private static final String NewAudioName = "/sdcard/new.wav";

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().setFormat(PixelFormat.TRANSLUCENT);// 让界面横屏
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉界面标题
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		// 重新设置界面大小
		setContentView(R.layout.main);
		init();
	}

	private void init() {
		Start = (Button) this.findViewById(R.id.start);
		Stop = (Button) this.findViewById(R.id.stop);
		Start.setOnClickListener(new TestAudioListener());
		Stop.setOnClickListener(new TestAudioListener());
		creatAudioRecord();
	}

	private void creatAudioRecord() {
		// 获得缓冲区字节大小
		bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
				channelConfig, audioFormat);
		// 创建AudioRecord对象
		audioRecord = new AudioRecord(audioSource, sampleRateInHz,
				channelConfig, audioFormat, bufferSizeInBytes);
	}

	class TestAudioListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			if (v == Start) {
				startRecord();
			}
			if (v == Stop) {
				stopRecord();
			}

		}

	}

	private void startRecord() {
		audioRecord.startRecording();
		// 让录制状态为true
		isRecord = true;
		// 开启音频文件写入线程
		new Thread(new AudioRecordThread()).start();
	}

	private void stopRecord() {
		close();
	}

	private void close() {
		if (audioRecord != null) {
			System.out.println("stopRecord");
			isRecord = false;//停止文件写入
			audioRecord.stop();
			audioRecord.release();//释放资源
			audioRecord = null;
		}
	}

	class AudioRecordThread implements Runnable {
		@Override
		public void run() {
			writeDateTOFile();//往文件中写入裸数据
			copyWaveFile(AudioName, NewAudioName);//给裸数据加上头文件
		}
	}

	/**
	 * 这里将数据写入文件,但是并不能播放,因为AudioRecord获得的音频是原始的裸音频,
	 * 如果需要播放就必须加入一些格式或者编码的头信息。但是这样的好处就是你可以对音频的 裸数据进行处理,比如你要做一个爱说话的TOM
	 * 猫在这里就进行音频的处理,然后重新封装 所以说这样得到的音频比较容易做一些音频的处理。
	 */
	private void writeDateTOFile() {
		// new一个byte数组用来存一些字节数据,大小为缓冲区大小
		byte[] audiodata = new byte[bufferSizeInBytes];
		FileOutputStream fos = null;
		int readsize = 0;
		try {
			File file = new File(AudioName);
			if (file.exists()) {
				file.delete();
			}
			fos = new FileOutputStream(file);// 建立一个可存取字节的文件
		} catch (Exception e) {
			e.printStackTrace();
		}
		while (isRecord == true) {
			readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
			if (AudioRecord.ERROR_INVALID_OPERATION != readsize) {
				try {
					fos.write(audiodata);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		try {
			fos.close();// 关闭写入流
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 这里得到可播放的音频文件
	private void copyWaveFile(String inFilename, String outFilename) {
		FileInputStream in = null;
		FileOutputStream out = null;
		long totalAudioLen = 0;
		long totalDataLen = totalAudioLen + 36;
		long longSampleRate = sampleRateInHz;
		int channels = 2;
		long byteRate = 16 * sampleRateInHz * channels / 8;
		byte[] data = new byte[bufferSizeInBytes];
		try {
			in = new FileInputStream(inFilename);
			out = new FileOutputStream(outFilename);
			totalAudioLen = in.getChannel().size();
			totalDataLen = totalAudioLen + 36;
			WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
					longSampleRate, channels, byteRate);
			while (in.read(data) != -1) {
				out.write(data);
			}
			in.close();
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。
	 * 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个wav
	 * 音频的文件,可以发现前面的头文件可以说基本一样哦。每种格式的文件都有
	 * 自己特有的头文件。
	 */
	private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,
			long totalDataLen, long longSampleRate, int channels, long byteRate)
			throws IOException {
		byte[] header = new byte[44];
		header[0] = 'R'; // RIFF/WAVE header
		header[1] = 'I';
		header[2] = 'F';
		header[3] = 'F';
		header[4] = (byte) (totalDataLen & 0xff);
		header[5] = (byte) ((totalDataLen >> 8) & 0xff);
		header[6] = (byte) ((totalDataLen >> 16) & 0xff);
		header[7] = (byte) ((totalDataLen >> 24) & 0xff);
		header[8] = 'W';
		header[9] = 'A';
		header[10] = 'V';
		header[11] = 'E';
		header[12] = 'f'; // 'fmt ' chunk
		header[13] = 'm';
		header[14] = 't';
		header[15] = ' ';
		header[16] = 16; // 4 bytes: size of 'fmt ' chunk
		header[17] = 0;
		header[18] = 0;
		header[19] = 0;
		header[20] = 1; // format = 1
		header[21] = 0;
		header[22] = (byte) channels;
		header[23] = 0;
		header[24] = (byte) (longSampleRate & 0xff);
		header[25] = (byte) ((longSampleRate >> 8) & 0xff);
		header[26] = (byte) ((longSampleRate >> 16) & 0xff);
		header[27] = (byte) ((longSampleRate >> 24) & 0xff);
		header[28] = (byte) (byteRate & 0xff);
		header[29] = (byte) ((byteRate >> 8) & 0xff);
		header[30] = (byte) ((byteRate >> 16) & 0xff);
		header[31] = (byte) ((byteRate >> 24) & 0xff);
		header[32] = (byte) (2 * 16 / 8); // block align
		header[33] = 0;
		header[34] = 16; // bits per sample
		header[35] = 0;
		header[36] = 'd';
		header[37] = 'a';
		header[38] = 't';
		header[39] = 'a';
		header[40] = (byte) (totalAudioLen & 0xff);
		header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
		header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
		header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
		out.write(header, 0, 44);
	}

	@Override
	protected void onDestroy() {
		close();
		super.onDestroy();
	}
}



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 使用AudioRecord录音相关和音频文件的封装 的相关文章

  • esp8266 硬件平台

    esp8266 硬件平台 概述对模组的选择最小系统 概述 首先8266是个芯片 好像有掉进某个巨坑 xff0c 哈哈 认识一下芯片出产是乐鑫 模组出产是安信可 一般都使用模组 xff0c 因为射频电路设计的门槛比较高 xff0c 不懂时候近
  • esp32s2 tinyusb vendor device小总结

    usb 802 11 wifi网卡 xff0c 遇到点问题 对tinyusb的架构有一点小了解了 发送路径 xff1a 用户调用tud vendor write urb msg urb len 启动传输 tud vendor write g
  • Java面试回报率最高的5本书!别再傻傻的看入门到放弃系列了!

    二八定律工欲善其事 xff0c 必先利其器读一本好书 如果你是一名 程序猿 xff0c 那么你肯定免不了准备各种面试 毕竟无论校招还是社招都是要经过严格的面试流程 xff0c 才能入职 可能每个人准备面试的方法也不一样 xff0c 但是读一
  • 2020互联网大厂硕士生薪资出炉!来源OfferShow爆料整理!

    今天和大家聊一聊 2020 届秋招硕士生开发岗位的薪资情况 最近看网上有人爆料 2020 互联网大厂校招硕士生的薪资情况 xff0c 这份榜单中包含了 10 家公司 xff0c 其中有 4 家是我秋招中拿到 offer 且谈过薪资的 榜单中
  • nvidia nx平台HDMIDP输出红色噪声调试记录

    1 前言 使用定制板 Jetpack版本是4 4 1 L4T 32 4 4 使用以下命令 当同时通过nvoverlaysink输出视频到HDMI DP时 在整个DP屏幕上出现红色噪声错误 gst launch 1 0 videotestsr
  • 没有实习我是不是就拿不到大厂offer了吗?---校招答疑

    可能是快放寒假了 xff0c 也可能是再有 2 3 个月就要进入 2020 年春招 xff08 应届生春季校招和暑期实习生招聘 xff09 了 越来越多的同学开始问实习的事情了 我认识的 20 届的同学有已经日常实习两个月以上的 xff0c
  • 最新42道计算机网络面试题!-- 附答案

    写在前面 计算机网络 计算机操作系统这两个 兄弟 是所有开发岗位都需要 结拜 的 xff0c 不管你是 Java C 43 43 还是测试 对于后端开发的童鞋来说 xff0c 计算机网络的重要性不亚于语言基础 xff0c 毕竟平时开发经常会
  • 秋招没拿到心仪offer,春招还有机会吗?该如何准备?

    最近很多秋招不理想或者考研不理想的同学问我这样一个问题 xff1a 互联网公司春招还有没有机会 xff1f 其实我相信大部分同学问这个问题的时候 xff0c 心里都是有答案的 xff0c 只不过想找一个他认为可以让他安心的人说出这个答案 那
  • 使用Filezilla Server软件配置FTP的全过程

    博主秋招提前批已拿百度 字节跳动 拼多多 顺丰等公司的offer xff0c 可加微信 xff1a pcwl Java 一起交流秋招面试经验 xff0c 可获得博主的秋招简历和复习笔记 使用Filezilla Server软件配置FTP的全
  • JAVA的四类八种基本数据类型

    先说明两个词汇的基本概念 xff1a bit xff08 位 xff09 xff1a 位是计算机中存储数据的最小单位 xff0c 指二进制数中的一个位数 xff0c 其值为 0 或 1 byte xff08 字节 xff09 xff1a 字
  • 集线器、交换机与路由器有什么区别?

    转发自 xff1a https mp weixin qq com s YXWBw3aFTSEFvkg oN9eQA 我相信我们都玩过一款特别火的游戏 xff1a 帝国时代 小时候想要玩帝国时代 xff0c 需要到软件城购买盗版光盘安装 xf
  • 【leetcode】第5题:最长回文子串

    目 录 一 暴力解法 二 动态规划 三 中心扩展法 四 Manacher 算法 先说明几个概念 xff1a 1 子串 xff1a 小于等于原字符串长度 xff0c 由原字符串中任意个连续 字符组成的子序列 xff1b 2 回文 xff1a
  • 字符串的排列与组合【Java 递归实现】

    我们在笔试中经常会遇到需要对字符串进行排列或者组合的题目 本篇文章对字符串的排列和组合进行递归版本的实现 如果你有更简单易懂的方法 xff0c 一定要在评论区留下来 1 字符串的组合 子序列 题目 xff1a 输入一个字符串 xff0c 输
  • 【手撕代码】多个线程交替打印

    目 录 xff1a 方法一 xff1a 锁实现 推荐 方法二 xff1a 信号量 semaphore 实现 推荐 方法三 xff1a wait notify 实现 方法四 xff1a 使用 Lock Condition 实现 面试的过程中
  • 【搞定算法】找出数组中出现次数大于数组长度一半和 N/K 的数

    博主秋招提前批已拿百度 字节跳动 拼多多 顺丰等公司的offer xff0c 可加微信 xff1a pcwl Java 一起交流秋招面试经验 目 录 xff1a 1 找出数组中出现次数大于数组长度一半的数 2 找出数组中出现次数大于数组长度
  • NVIDIA Jetson Nano 电源适配器 (供电)

    1 Jetson Nano 供电 Jetson Nano 的 micro USB 接口支持 2A 的电流 xff0c DC 供电接口支持 4A 电流 MicroUSB 在安全范围内的最大承载电流为 2A 实际项目中 CPU 满载 43 GP
  • 【搞定算法】常见算法题分类总览

    博主秋招提前批已拿百度 字节跳动 拼多多 顺丰等公司的offer xff0c 可加微信 xff1a pcwl Java 一起交流秋招面试经验 xff0c 可获得博主的秋招简历和复习笔记 完善中 由于本人平时刷题比较零散 xff0c 有时候找
  • 堆、栈的储存内容

    Java的JVM的内存可分为3个区 xff1a 堆 heap 栈 stack 和方法区 method 堆区 1 存储的全部是对象 xff0c 每个对象都包含一个与之对应的class的信息 class的目的是得到操作指令 2 jvm只有一个堆
  • 某32位系统下, C++程序,请计算sizeof 的值.

    某32 位系统下 C 43 43 程序 xff0c 请计算 sizeof 的值 void Foo 1 char str 100 cout lt lt 34 Foo 1 34 lt lt sizeof str lt lt endl char
  • python-pcl安装及使用

    在开始前 xff0c 先说明一下 xff0c pcl的库安装不简单 xff0c 不仅需要pip安装 xff0c 还需要安装C 43 43 的pcl库 xff0c 所以整个流程会比较漫长 鉴于官方参考网站的python pcl太麻烦 xff0

随机推荐

  • ROSBAG解析bag包教程

    一 软件安装教程 1 安装rosbag xff1a https www cnblogs com arkenstone p 6676203 html 2 安装mjepgtools和ffmpeg sudo apt get install mje
  • 双电机同步PID调试方法(二)

    由于双电机的PID上升曲线难以完全重合 xff0c 造成左右电机速度不一致 本文为了解决该问题设计了一种方法 主要思想是将不同速度对应的PWM占空比曲线拟合出来 xff0c 减1000 xff08 总10000 xff09 占空比后作为预设
  • exe打包成安装包

    前面介绍了如何将python代码打包成可执行文件 xff0c 这里再介绍一下如何将exe打包成安装包 一 安装InstallShield2015 百度云网址 xff1a https pan baidu com s 1fFGDeczPduWa
  • Python 打包成 wheel

    1 编写 setup py 在项目的根目录下外面一个文件夹创建 96 setup py 96 96 name 96 xff1a 指的是你打包后发布的名称 xff08 如 96 numpy 96 和 96 torch 96 xff09 96
  • plugins插件使用例程

    最近在看一个pyqt写的工具软件 xff0c 项目中大量使用plugins xff0c 所以了解了一下plugins的功能机制 下面简单分享一个例程 xff0c 代码结构如下 main py platform py init py plug
  • pycharm中.gitignore无效

    1 打开pycharm的命令行 xff0c 输入以下指令 git rm r cached git add 2 再次在pycharm上 xff0c 点击commit 原因 xff1a 这是因为pycharm会自动运行git add 的功能 x
  • Jetson Orin&Nx&Nano平台 FPDlink Ⅲ相机采集---双目场景应用

    1 前言 基于上次在淘宝上采购的FPDlink 相机采集套件使用一段时间之后 不少人对此方案很感兴趣的 又激发了我继续写的激情 上次帖子链接如下 Jetson Orin平台多路 FPDlink 相机采集套装推荐 bingdund的博客 CS
  • SBUS协议:SBUS解析与合成

    在说协议之前 xff0c 我想强调一点 xff1a 信号要取反 xff0c 硬件取反 xff01 xff01 xff01 xff01 xff01 至于为什么强调 xff0c 我会在后面解释 xff0c 你们先记住 SBUS协议 xff1a
  • 上海灵信视觉A4控制板

    资料准备 xff1a 1 LED Player上位机控制 xff1a em span style font size 12px http www 168led com AjaxFile DownLoadFileNew aspx FilePa
  • stm32串口一直进USART1_IRQHandler

    今天在使用USART模块 xff0c 遇到了一些问题并解决了 xff0c 于是发贴共享 问题描述 xff1a 在使用USART做串口通讯时 xff0c 我只把接收中断打开 xff0c 并设置抢占优先级为最低一个级别 xff0c 而接收中断上
  • tensorflow载入报错Process finished with exit code -1073741819 (0xC0000005)

    这几天准备在现有的软件里加上caffe来测试一种新算法 发现windows下python3 6安装caffe是真的难 xff0c 只能装好python2 7的版本就放弃了 回来继续完善软件 xff0c 又发现软件里的tensorflow不能
  • python项目打包(自定义dll) anaconda3+pyinstaller

    目前手上有一个python 43 pyqt的项目需要打包 xff0c 所以查了一下打包的方法 下面介绍一下具体步骤 xff1a python打包有很多方法 xff0c py2exe xff0c pyinstaller等等 xff08 其实我
  • Docker(六)同一镜像有多个Tag情况下,执行 docker rmi 镜像ID 指令无法删除

    删除方法一 docker rmi f 镜像ID 删除方法二 docker rmi repository tag 参考 xff1a 1 https www imooc com article 35040
  • 《ROS机器人开发实践(胡春旭)》第十章MoveIt!机械臂控制 学习笔记

    r 在学习 ROS机器人开发实践 胡春旭 第10章的MoveIt xff01 时 xff0c 因为在自己创建的工作空间中没有下载作者的源代码 xff0c 所有有以下几个问题 xff1a 1 使用moveit setup assistant时
  • Android 根据网络分析运营商信息

    我们想获取手机的运营商信息 通常都会去调用系统的TelephonyManager类的取数据 但是很多时候可能取不到卡的信息 xff08 例如双卡手机和一些特殊卡 xff09 xff0c 这样就区别不了运营商了 但是有时候我们的需求要进行不通
  • 简单又好看的按钮,扁平化按钮。

    今天分享一下流行的扁平化按钮 完全不需要用到图片哦 效果图如下 xff1a 里面有2个按钮都是一样的模式 只要修改的色值就可以 下面跟我来更新你的UI吧 首先编写 button xml 代码如下 lt xml version 61 34 1
  • Android 获取运营商信息(完整版)-解决高通,MTK等双卡问题

    由于国内的运营商问题 xff0c 双卡手机获取IMSI号问题要根据厂商API 来实现 下面我们就来做一套完整的分析运营商获取IMSI号逻辑 1 xff0c 首先我们要判断手机的平台 1 1 xff0c 判断手机是否MTK平台 public
  • AstarPathfindingProject 中RVO碰撞体扩展

    原本库中只有矩形RVO碰撞体 xff0c 如果要添加自己的需要继承RVOObstacle抽象类 xff0c 重写里面的方法 例如下面的圆柱形碰撞 using UnityEngine if UNITY EDITOR using UnityEd
  • Android中抓取手机视频流数据。

    目前实时抓取手机视频数据有2种方法 xff0c 一种是通过camera的回调获取源数据 xff0c 这里获取的源数据是没有编码的数据 有的人发送yuv数据然后在那绘制图片 xff0c 也说视频聊天 xff0c 真是可笑 这种方式是可是实现视
  • Android 使用AudioRecord录音相关和音频文件的封装

    在Android中录音可以用MediaRecord录音 xff0c 操作比较简单 但是不够专业 xff0c 就是不能对音频进行处理 如果要进行音频的实时的处理或者音频的一些封装 就可以用AudioRecord来进行录音了 这里给出一段代码