Android-Audio-编解码
好的这是一个关于 Android 音频编解码的全面介绍涵盖基本概念、原理和例子。一、 基本概念音频编解码 (Audio Codec)◦ 编解码 是 编码 (Encode) 和 解码 (Decode) 的合称。◦ 编码将原始的、未压缩的音频数据如 PCM转换为压缩的、更小体积的数据格式如 MP3, AAC。目的是减小存储空间和传输带宽。◦ 解码将压缩的音频数据转换回或近似原始的、可以被扬声器播放的格式。目的是播放音频。关键数据格式◦ PCM (Pulse Code Modulation, 脉冲编码调制)▪ 定义是数字音频的“原始”或“无损”表示形式直接从模拟信号通过采样、量化得到。它没有经过压缩因此文件体积很大。 ▪ 特点它是所有数字音频处理如混音、特效的基础格式。音频在设备内部处理和硬件驱动之间传输时通常是 PCM 格式。◦ 压缩音频格式如 MP3, AAC, OGG, FLAC 等。它们是在 PCM 基础上通过特定算法压缩后的格式用于存储和网络传输。Android 中的核心类◦ MediaPlayer高级 API用于播放音频/视频。它内部处理了解码、同步等复杂任务开发者只需提供文件路径或 URI。主要用于播放压缩格式的音频文件或网络流。◦ MediaRecorder高级 API用于录制音频/视频。它内部处理了编码、文件封装等任务。◦ AudioTrack低级 API用于播放 PCM 音频流。开发者需要提供 PCM 数据缓冲区由 AudioTrack 写入音频硬件。它只处理播放不负责解码。◦ AudioRecord低级 API用于录制 PCM 音频流。它从音频硬件麦克风采集原始的 PCM 数据。它只负责采集不负责编码。◦ MediaCodec最核心的低级编解码 API。用于对原始数据如 PCMYUV进行编码或解码。它是连接压缩数据与原始数据的桥梁。二、 原理与流程在 Android 中完整的音频处理流程通常涉及以上类的组合。音频播放流程 (解码过程)对于一个压缩音频文件如 MP3的播放原理如下[压缩文件: e.g., MP3] --(输入)– [MediaCodec 解码器] --(输出)– [PCM 数据] --(写入)– [AudioTrack] --(播放)– [扬声器]• 步骤 1解封装与解码MediaPlayer 内部或开发者自己使用 MediaExtractor 和 MediaCodec 协作完成。◦ MediaExtractor 从 MP4/MP3 等容器中分离出音频轨道。 ◦ MediaCodec配置为解码模式接收压缩的音频帧如 AAC 帧将其解码为原始的 PCM 数据。• 步骤 2播放 PCM解码得到的 PCM 数据被送入 AudioTrack由 AudioTrack 管理音频缓冲区并将数据推送至底层音频硬件如 HAL进行数模转换和放大最终驱动扬声器发声。简单使用用 MediaPlayer 时步骤 1 和 2 被自动完成。高级/自定义使用开发者可以使用 MediaCodec AudioTrack 手动控制解码和播放过程以实现音频特效、可视化或极低延迟播放。音频录制流程 (编码过程)录制音频并保存为压缩文件如 AAC原理如下[麦克风] --(采集)– [AudioRecord] --(输出)– [PCM 数据] --(输入)– [MediaCodec 编码器] --(输出)– [压缩数据: e.g., AAC] --(写入)– [文件/网络]• 步骤 1采集 PCMAudioRecord 从麦克风硬件采集原始的 PCM 音频数据。• 步骤 2编码采集到的 PCM 数据被送入 MediaCodec配置为编码模式编码器将其压缩为指定的格式如 AAC。• 步骤 3封装与写入编码后的压缩数据如 AAC 帧被 MediaMuxer 封装到特定的容器格式如 MP4中并写入文件。简单使用用 MediaRecorder 时步骤 1、2、3 被自动完成。高级/自定义使用开发者可以使用 AudioRecord MediaCodec MediaMuxer 手动控制流程以实现音频预处理、自定义编码参数或流式传输。三、 例子这里给出使用低级 API (AudioTrack, MediaCodec) 进行解码播放的简化版代码框架以展示原理。场景解码一个 MP3 文件并用 AudioTrack 播放。// 注意此为示意代码省略了异常处理、资源释放、同步等细节。// 1. 创建并配置 MediaExtractor定位音频轨道MediaExtractor extractor new MediaExtractor();extractor.setDataSource(“/sdcard/music.mp3”);int audioTrackIndex selectAudioTrack(extractor); // 选择音频轨道的辅助函数extractor.selectTrack(audioTrackIndex);// 2. 从 Extractor 获取音频格式包含 MIME 类型如 “audio/mp4a-latm”MediaFormat format extractor.getTrackFormat(audioTrackIndex);String mime format.getString(MediaFormat.KEY_MIME);// 3. 创建解码器 (MediaCodec)MediaCodec decoder MediaCodec.createDecoderByType(mime);decoder.configure(format, null, null, 0); // 配置为解码模式decoder.start();// 4. 创建 AudioTrack 用于播放解码后的 PCM// 从 format 中获取音频参数int sampleRate format.getInteger(MediaFormat.KEY_SAMPLE_RATE);int channelCount format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);int channelConfig (channelCount 1) ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO;int audioFormat AudioFormat.ENCODING_PCM_16BIT; // 常见格式int bufferSize AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);AudioTrack audioTrack new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,channelConfig,audioFormat,bufferSize,AudioTrack.MODE_STREAM);audioTrack.play();// 5. 解码循环boolean sawInputEOS false;boolean sawOutputEOS false;ByteBuffer[] inputBuffers decoder.getInputBuffers(); // API 21 后使用 getInput/OutputBufferByteBuffer[] outputBuffers decoder.getOutputBuffers();while (!sawOutputEOS) {// 5.1 将压缩数据送入解码器输入缓冲区if (!sawInputEOS) {int inputBufferIndex decoder.dequeueInputBuffer(TIMEOUT_US);if (inputBufferIndex 0) {ByteBuffer inputBuffer inputBuffers[inputBufferIndex];int sampleSize extractor.readSampleData(inputBuffer, 0);if (sampleSize 0) { // 已读完sawInputEOS true;decoder.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);} else {long presentationTimeUs extractor.getSampleTime();decoder.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);extractor.advance(); // 移动到下一帧}}}// 5.2 从解码器输出缓冲区获取解码后的 PCM 数据 MediaCodec.BufferInfo bufferInfo new MediaCodec.BufferInfo(); int outputBufferIndex decoder.dequeueOutputBuffer(bufferInfo, TIMEOUT_US); if (outputBufferIndex 0) { if ((bufferInfo.flags MediaCodec.BUFFER_FLAG_END_OF_STREAM) ! 0) { sawOutputEOS true; } if (bufferInfo.size 0) { ByteBuffer outputBuffer outputBuffers[outputBufferIndex]; // 将 PCM 数据写入 AudioTrack byte[] pcmData new byte[bufferInfo.size]; outputBuffer.get(pcmData); outputBuffer.clear(); // 必须清空或重置位置 audioTrack.write(pcmData, 0, pcmData.length); } decoder.releaseOutputBuffer(outputBufferIndex, false); }}// 6. 清理资源audioTrack.stop();audioTrack.release();decoder.stop();decoder.release();extractor.release();总结• 高级API (MediaPlayer, MediaRecorder): 简单、快捷适合大多数播放/录制场景。• 低级API (AudioTrack, AudioRecord, MediaCodec): 灵活、强大允许开发者深入控制音频流水线的每一个环节适用于需要低延迟、实时处理、自定义编解码或特殊文件格式的场景。理解它们之间的数据流转PCM - 压缩数据是掌握 Android 音频处理的关键。

相关新闻

书匠策AI:文献综述的“智能拼图师”,解锁论文写作新姿势!

书匠策AI:文献综述的“智能拼图师”,解锁论文写作新姿势!

在学术的广阔天地里,论文写作是每一位学者展示研究成果、交流学术见解的重要方式。而文献综述,作为论文的“开篇序章”,不仅是对前人研究的致敬与总结,更是为后续研究搭建桥梁的关键环节。然而,面对浩如烟海的文献资料…

2026/7/5 9:30:44 阅读更多 →
力扣刷题——24. 两两交换链表中的节点

力扣刷题——24. 两两交换链表中的节点

24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1:输入:head [1,2,3,4…

2026/7/5 9:25:24 阅读更多 →
基于Java springboot高校科研信息管理系统(源码+文档+运行视频+讲解视频)

基于Java springboot高校科研信息管理系统(源码+文档+运行视频+讲解视频)

文章目录 系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈 后端框架springboot前端框架vue持久层框架MyBaitsPlus系统测试 四、代码参考 源码获取 目的 高校科研信息管理是提升科研效率与质量的关键环节。基于Java Spring Boot框架开发的高校科研信息管…

2026/7/3 15:50:15 阅读更多 →

最新新闻

RevokeMsgPatcher防撤回补丁:原理、风险与Windows微信/QQ/TIM实操指南

RevokeMsgPatcher防撤回补丁:原理、风险与Windows微信/QQ/TIM实操指南

1. 项目概述:为什么我们需要一个“防撤回补丁”? 在即时通讯软件里,“消息撤回”功能设计的初衷是给用户一个纠正错误的机会,比如打错字、发错人或者一时冲动说了不合适的话。但很多时候,这个功能也带来了信息不对等的…

2026/7/5 9:28:38 阅读更多 →
Folia:全屏沉浸式在线音乐播放器,多端体验+AI 主题生成带来独特听歌感受!

Folia:全屏沉浸式在线音乐播放器,多端体验+AI 主题生成带来独特听歌感受!

Folia 是一款以全屏沉浸式歌词播放为核心的在线音乐播放器,支持多平台,具备智能歌词匹配、AI 生成配色主题等功能,为用户带来独特听歌体验。项目亮点与特色Folia 支持网易云、navidrome 和本地音乐库。其独特之处在于智能歌词匹配&#xff0c…

2026/7/5 9:26:38 阅读更多 →
SQL注入攻防全解析:从原理到实战,掌握Web安全核心漏洞

SQL注入攻防全解析:从原理到实战,掌握Web安全核心漏洞

1. 项目概述:为什么SQL漏洞是面试官的“心头好”? 干了这么多年安全,也面过不少人,我发现一个挺有意思的现象:无论你是应聘渗透测试、安全开发还是安全运维,面试官几乎都会把SQL注入漏洞拎出来问一遍。从“…

2026/7/5 9:26:37 阅读更多 →
Weex架构安卓商城APP逆向工程包:含完整源码结构、APK资源解包与AndroidX/Support双兼容支持

Weex架构安卓商城APP逆向工程包:含完整源码结构、APK资源解包与AndroidX/Support双兼容支持

本文还有配套的精品资源,点击获取 简介:一套真实上线商城App的逆向分析成果,主逻辑基于Weex框架(main.js驱动),集成weex-main-jsfm.js、weex-rax-api.js等核心运行时模块,支持RAX组件开发&am…

2026/7/5 9:20:36 阅读更多 →
山东大学编译原理PL0实验代码:Java实现的词法扫描、递归下降语法分析与P-code解释器

山东大学编译原理PL0实验代码:Java实现的词法扫描、递归下降语法分析与P-code解释器

本文还有配套的精品资源,点击获取 简介:一套开箱即用的PL/0语言编译器教学实现,基于Java开发,完整覆盖编译流程三大阶段:词法分析通过GETSYM函数识别关键字、标识符、数字和分界符;语法分析采用递归下降…

2026/7/5 9:18:36 阅读更多 →
从零部署Hermes Agent:构建可自我进化的AI智能体框架

从零部署Hermes Agent:构建可自我进化的AI智能体框架

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 这次我们来看一个能自我进化的 AI 智能体项目——Hermes Agent。它由 Nous Research 团队开源,在 GitHub 上已经获得了超过…

2026/7/5 9:18:36 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻