Android 开发一个耳返程序(录音,实时播放)

news2024/11/19 6:43:57

本文目录 点击直达

  • Android 开发一个耳返程序
    • 程序编写
      • 1. 配置 `AndroidManifast.xml`
      • 2.编写耳返管理器
      • 3. 录音权限申请
      • 4. 使用
      • 注意
  • 最后我还有一句话要说
      • 怕相思,已相思,轮到相思没处辞,眉间露一丝

Android 开发一个耳返程序

耳返程序是声音录入设备实时播放的一种程序,理论上实现方案是通过手机录音功能录制音频的同时播放音频,这样就可以简单达到耳返的目的。

分析完毕之后通过了解Android官方API和文档,决定采用AudioRecord/AudioTrack的方式实现简单的PCM编码录制和播放来实现耳返,接下来我们直接进入正题

程序编写

1. 配置 AndroidManifast.xml

录音需要使用录音权限,将以下代码写入AndroidManifast.xml文件中

    <uses-permission android:name="android.permission.RECORD_AUDIO" />

效果如下
配置权限

2.编写耳返管理器

这里我们创建一个类IEMSManager.kt,用来处理音频录制和播放

object IEMSManager {
    //录音来源使用通话语音,这样可以防止啸叫的同时拥有系统降噪
    private const val AUDIO_SOURCE = MediaRecorder.AudioSource.VOICE_COMMUNICATION
    // 采样频率:44100Hz是唯一目前所有Android设备都保证支持的采样频率
    private const val SAMPLE_RATE = 44100
    // 音频通道使用双声道输入
    private const val CHANNEL_IN = AudioFormat.CHANNEL_IN_STEREO
    // 音频通道使用双声道输出
    private const val CHANNEL_OUT = AudioFormat.CHANNEL_OUT_STEREO
    // PCM 16bits每个样本,所有设备保证支持
    private const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT

    // 录音时音频数据写入的buffer的大小
    private var recordBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_IN, AUDIO_FORMAT)
    // 播放时音频数据读取的buffer的大小
    private val trackBufferSize =
        AudioTrack.getMinBufferSize(SAMPLE_RATE, CHANNEL_OUT, AUDIO_FORMAT);

    //构建描述音频属性的对象
    private val attributes by lazy {
        AudioAttributes.Builder()
            //设置音频流的用途属性
            .setUsage(AudioAttributes.USAGE_ASSISTANT)
            //设置音频内容属性
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build()
    }

    //构建描述音频格式的对象
    private val format = AudioFormat.Builder()
        //设置采样频率
        .setSampleRate(SAMPLE_RATE)
        //设置音频格式的编码方式
        .setEncoding(AUDIO_FORMAT)
        //设置通道掩码
        .setChannelMask(CHANNEL_OUT)
        .build()

    //控制耳返的状态
    private var isRunning = false
    //音频录制器,可以录制音频裸数据PCM
    private var audioRecorder: AudioRecord? = null
    //音频播放器,支持PCM裸数据渲染
    private var audioTrack: AudioTrack? = null

    @RequiresPermission(android.Manifest.permission.RECORD_AUDIO)
    fun start() {
        if (isRunning) return
        isRunning = true
        //初始化音频录制器
        audioRecorder = AudioRecord(
            AUDIO_SOURCE,
            SAMPLE_RATE,
            CHANNEL_IN,
            AUDIO_FORMAT,
            recordBufferSize
        )
        //初始化音频播放器
        audioTrack = AudioTrack(
            attributes,
            format,
            trackBufferSize,
            AudioTrack.MODE_STREAM,
            AudioManager.AUDIO_SESSION_ID_GENERATE
        )
        //开启线程
        thread {
            //创建字节数组存储PCM的二进制数据
            val data = ByteArray(recordBufferSize)
            //开始录制
            audioRecorder?.startRecording()
            //开始播放
            audioTrack?.play()
            while (isRunning) {
                //录音数据是根据录制缓冲区大小试试读取的
                val byteSize = audioRecorder?.read(data, 0, recordBufferSize) ?: 0
                //检查到录制数据正常
                if (byteSize >= AudioRecord.SUCCESS) {
                    //AudioTrack实时渲染刚刚录制的部分
                    audioTrack?.write(data, 0, byteSize)
                }
            }
            //释放资源
            audioRecorder?.stop()
            audioRecorder?.release()
            audioTrack?.stop()
            audioTrack?.release()
            audioRecorder = null
            audioTrack = null
        }
    }

    fun stop() {
        isRunning = false
    }
}

3. 录音权限申请

在使用耳返功能前,需要检查权限,并且授予RECORD_AUDIO权限,否则会闪退

            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.RECORD_AUDIO
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0x1)
                return@setOnClickListener
            }

4. 使用

代码已经编写完成,只需要调用IEMSManager.kt使用即可听到自己发出的声音

IEMSManager.start()
IEMSManager.stop()

注意

因为使用通话的双通道麦克风实现了降噪,所以使用时可能声音较小,如果没有声音,请将声音调到最大,然后凑近麦克风吼两句"感谢博主,我会一键三连的"

最后我还有一句话要说

怕相思,已相思,轮到相思没处辞,眉间露一丝

明·俞彦《长相思·折花枝》

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

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

相关文章

开源分子对接程序rDock的安装及使用流程

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 前言 本文介绍开源分子对接程序rDock在Linux Ubuntu 22.04系统上的conda安装、编译安装过程及程序使用流程。 一、rDock是什么&#xff1f; rDock来源 rDock是一个快速、多功能的开源对接程序&#xff0c;可用…

鼠标右键助手专业版 MouseBoost PRO for Mac v3.3.6中文破解

MouseBoost Pro mac版是一款简单实用的鼠标右键助手专业版&#xff0c;MouseBoost Pro for Mac只要轻点你的鼠标右键&#xff0c;就可以激活你想要的各种功能&#xff0c;让你的工作效率大幅度提高&#xff0c;非常好用。 软件下载&#xff1a;MouseBoost PRO for Mac v3.3.6中…

Matlab/simulink光伏发电的扰动观察法MPPT仿真(持续更新)

1.光伏发电的电导增量法MPPT仿真 2.光伏发电的恒定电压法MPPT仿真 3.光伏发电的扰动观察法MPPT仿真 4.光伏发电的占空比法MPPT仿真 5.基于神经网络的MPPT光伏发电仿真 6. 基于模糊控制的MPPT光伏发电仿真 7. 基于粒子群算法&#xff08;PSO&#xff09;的500w光伏系统MPPT控…

WordPres Bricks Builder 前台RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

spark 少量key倾斜的join优化

背景 在使用spark join时&#xff0c;我们经常遇到少量key拥有大量的数据而导致的数据倾斜的问题&#xff0c;这导致了task任务数据处理非常不均匀而影响最终时效 少量key数据倾斜的join优化 这里有一个前提&#xff0c;join的另一边的表没有数据倾斜问题&#xff0c;也就是…

问题慢慢解决-通过android emulator调试android kernel-内核条件断点遇到的问题和临时解决方案

起因 在摸索到这个方案之后&#xff0c;mac m1调试aarch64 android kernel最终方案&#xff0c;就准备调试内核了&#xff0c;预备下断点的地方是 b binder_poll b ep_ptable_queue_proc b remove_wait_queue但是由于是android系统&#xff0c;上面三个函数会被频繁的触发&am…

Window部署SkyWalking

SkyWalking mysql的驱动依赖 选择下载版本 v9.4 现在后解压缩目录结构 一、修改config目录文件 application.yml 修改1&#xff1a; selector: ${SW_STORAGE:h2} 修改后&#xff1a; selector: ${SW_STORAGE:mysql} 修改2&#xff1a;使用mysql数据库 mysql: properti…

windows 11+docker desktop+grafana+influxDB

下载安装docker desktop 出现WSL相关的错误。WSL是一个linux内核的子系统&#xff0c;docker是基于linux内核的&#xff0c;所以运行docker需要WSL。 以管理员权限打开powershell&#xff0c;查看WSL状态 wsl --status 我遇到的错误是因为我关闭了windows的某些更新 执行上…

comfyui节点编写示例文件(下)

** 1、先看示例文件的结构 ** ** 2、设置输入参数 ** ** 3、节点指定任务、输出啥 ** ** 4、这个节点干了啥&#xff0c;定义函数、输出结果 ** ** 5、多个节点&#xff0c;就多个类 ** ** 6、设置多个入口 ** ** 7、放置 ** 直接把py文件放到 .\Co…

Python+Selenium-使用Pillow库进行元素截图

1. Pillow库 Pillow库是Python图像处理的基库&#xff0c;是一个免费开源的第三方库。 通过Python PyPi第三方库官网&#xff08;https://pypi.org/project/Pillow/#files&#xff09;下载与平台系统相对应的版本&#xff1a; 下载完成后&#xff0c;进入下载文件的所在位置&…

Redis(十六)缓存预热+缓存雪崩+缓存击穿+缓存穿透

文章目录 面试题缓存预热缓存雪崩解决方案 缓存穿透解决方案 缓存击穿解决方案案例&#xff1a;高并发聚划算业务 总结表格 面试题 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况?缓存预热你是怎么做的?如何避免或者减少缓存雪崩?穿透和击穿有什么区别?他两是…

力扣hot100题解(python版7-9题)

7、接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,…

mp4格式是什么?视频如何转换成MP4格式【详解】

当我们谈论数字视频时&#xff0c;MP4无疑是最常见、最受欢迎的格式之一。MP4&#xff0c;全称为MPEG-4 Part 14&#xff0c;是一种多媒体容器格式&#xff0c;主要用于存储音频、视频、字幕和图像等多媒体数据。由于其出色的兼容性、广泛的应用范围以及优秀的压缩效率&#xf…

Conmi的正确答案——将JAVA中maven的.m2文件夹放到D盘

系统&#xff1a;WIN11 1、将.m2文件夹移动到D盘 移动后&#xff1a; 2、创建目录链接 mklink /j "C:\Users\Administrator\.m2" "D:\.m2"至此&#xff0c;maven默认的jar包会加载到D盘的.m2文件夹

【动态规划】【前缀和】【推荐】2463. 最小移动总距离

作者推荐 【广度优先搜索】【网格】【割点】【 推荐】1263. 推箱子 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 2463. 最小移动总距离 X 轴上有一些机器人和工厂。给你一个整数数组 robot &#xff0c…

计算机组成原理(12)----多处理系统

目录 1.SISD&#xff08;单指令流单数据流&#xff09; &#xff08;1&#xff09;特性 &#xff08;2&#xff09;硬件组成 2.SIMD&#xff08;单指令流多数据流&#xff09; &#xff08;1&#xff09;特性 &#xff08;2&#xff09;硬件组成 3.MISD&#xff08;多指…

【Java EE初阶二十四】servlet的深入理解

1. Servlet API 的学习 下面主要学习这三个类&#xff0c;就已经可以完成 Servlet 的大部分开发了&#xff1b; 1. Httpservlet 2. HttpServletRequest 3. HttpServletResponse 2. Httpservlet的学习 2.1 Httpservlet在tomcat的工作原理 写一个 Servlet 代码&#xff0c;往往都…

C++最佳实践之编译篇

C最佳实践之工程编译 在大型c/c工程开发中&#xff0c;往往会涉及多级CMakeLists.txt的调用&#xff0c;并且调用方式错综复杂&#xff0c;主要有以下两种方式&#xff1a; 1. 子目录中的CMakeList.txt独立生成目标&#xff0c;不作为主目标生成过程的依赖关系&#xff08;比…

Windows+Yolo3-darknet训练自己数据集并测试

WindowsYolo3-darknet训练自己的数据集并测试 一、首要条件 Windows 7下配置好VS2015OPENCV3.4.2YOLO3CUDA10.0CUDNN7.5生成darknet.exe。具体配置可参考我的博客&#xff1a;https://blog.csdn.net/wszswllnzn_/article/details/100760477 二.制作数据集 1、方法1 使用软件la…

uView组件使用

u-collapse 折叠面板 https://www.uviewui.com/components/collapse.html?ivk_sa1024320u 如果是异步加载的数据&#xff0c;最开始的 u-collapse-item是默认高度&#xff0c;&#xff0c;第一次点开的时候&#xff0c;异步数据不能撑开高度 但是如果 u-collapse-item中有内…