Android音视频之AudioTrack播放音频(二)
前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入到AudioTrack中就可以了,先贴代码
- package cn.sskbskdrin.record.audio;
- import android.media.AudioManager;
- import android.media.AudioTrack;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- /**
- * @author sskbskdrin
- * @date 2019/April/3
- */
- public class AudioTrackManager {
- private AudioTrack audioTrack;
- private boolean playing = false;
- public AudioParams playWav(String filepath, AudioRecordManager.RecordCallback callback) {
- RandomAccessFile file = null;
- AudioParams params = null;
- try {
- file = new RandomAccessFile(filepath, "r");
- params = readWavHeader(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (params == null) {
- return null;
- }
- int simpleRate = params.simpleRate;
- int channelConfig = params.getOutChannelConfig();
- int audioFormat = params.getEncodingFormat();
- int minBufSize = AudioTrack.getMinBufferSize(simpleRate, channelConfig, audioFormat);
- audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, simpleRate, channelConfig, audioFormat, minBufSize,
- AudioTrack.MODE_STREAM);
- final RandomAccessFile finalFile = file;
- new Thread(() -> {
- playing = true;
- audioTrack.play();
- byte[] buffer = new byte[minBufSize];
- try {
- finalFile.seek(44);
- while (playing) {
- int read = finalFile.read(buffer);
- if (read > 0) {
- audioTrack.write(buffer, 0, read);
- } else {
- finalFile.close();
- playing = false;
- audioTrack.stop();
- audioTrack.release();
- }
- if (callback != null) {
- callback.onRecord(buffer, read);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- return params;
- }
- public static AudioParams readWavHeader(RandomAccessFile file) throws IOException {
- file.seek(22);
- byte channelCount = file.readByte();
- file.seek(24);
- int sampleRate = file.readByte() & 0xff;
- sampleRate |= (file.readByte() & 0xff) << 8;
- sampleRate |= (file.readByte() & 0xff) << 16;
- sampleRate |= (file.readByte() & 0xff) << 24;
- file.seek(34);
- byte bits = file.readByte();
- return new AudioParams(sampleRate, channelCount, bits);
- }
- }
播放的方法,是传入文件路径,AudioRecordManager.RecordCallback可以为空。先是通过readWavHeader()方法读取wav文件的文件头信息,返回AudioParams,这个类是我前一篇文章有列出来,可以得到一些需要的数据。
关于读数据头部信息,可以参考这里,读取重要数据。
AudioTrack.getMinBufferSize(simpleRate, channelConfig, audioFormat)可以获取最小缓存大小。
AudioTrack的构造方法中,第一个参数为播放流的类型,有下面几种
AudioManager.STREAM_MUSIC //音乐
AudioManager.STREAM_VOICE_CALL //电话
AudioManager.STREAM_RING //铃声
AudioManager.STREAM_ALARM //闹钟
AudioManager.STREAM_NOTIFICATION //通知
最后了个参数是流写入的方式,有两种
AudioTrack.MODE_STREAM // 流写入
AudioTrack.MODE_STATIC //静态写入
AudioTrack.MODE_STREAM看名字大概就能知道是流的方式写入,边写边播。
AudioTrack.MODE_STATIC就是一次写完,然后播放,这种方式更适合比较短的声音播放,比如通知声音
开始播放时,先调用AudioTrack.play(),然后从wav文件的数据块开始读,即第44个字节开始,读完调用audioTrack.write写入pcm数据。当读不到数据时,停止AudioTrack,释放资源即可。
通过RandomAccessFile方式读取文件,可以记录读取的位置,并通过seek方法跳转到指定位置,可实现播放、暂停、继续播放的功能。
Android音视频之AudioTrack播放音频(二)的更多相关文章
- android音视频点/直播模块开发
音视频 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白, ...
- Android音视频点/直播模块开发实践总结-zz
随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...
- Android 音视频开发(一):PCM 格式音频的播放与采集
什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...
- Android Webview中解决H5的音视频不能自动播放的问题
在开发webview的时候,当加载有声音的网页的时候,声音不会自动播放, 解决方法:在webview中调用js方法.这个方法需要在webview的setWebViewClient方法之后在onPage ...
- Android 音视频开发学习思路
Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...
- Android 音视频同步机制
一.概述 音视频同步(avsync),是影响多媒体应用体验质量的一个重要因素.而我们在看到音视频同步的时候,最先想到的就是对齐两者的pts,但是实际使用中的各类播放器,其音视频同步机制都比这些复杂的多 ...
- Android 音视频开发(七): 音视频录制流程总结
在前面我们学习和使用了AudioRecord.AudioTrack.Camera.MediaExtractor.MediaMuxer API.MediaCodec. 学习和使用了上述的API之后,相信 ...
- Android音视频开发(1):H264 基本原理
前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...
- Android 音视频开发(六): MediaCodec API 详解
在学习了Android 音视频的基本的相关知识,并整理了相关的API之后,我们应该对基本的音视频有一定的轮廓了. 下面开始接触一个Android音视频中相当重要的一个API: MediaCodec.通 ...
随机推荐
- Ubuntu 命令手册
提示:命令太多,查找的时候请用Shift+F. 目录 • 1. 前言 • 2 安装升级 • 2.1 查看软件 xxx 安装内容 • 2.2 查找软件库中的软件 • 2.3 显示系统安装包的统计信息 • ...
- SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 简单概述一下本讲 别名,sql片段简单写一下,模糊查询多写一点 一.别名 <typeAliases> ...
- (WCF初体验)WCF的认证和消息保护
最近做WCF开发,有个需求是在服务端做认证,网上查资料了解到可以用UserName和Password 来做认证,只需要写好配置文件和在服务端写好验证类就行了,但是网上普遍的博文都是需要用证书,而我自己 ...
- LoadRunner Mysql性能优化
原文:https://blog.csdn.net/u011910905/article/details/49863787 一.查询与索引优化分析 1.show命令: show engines; 显示存 ...
- 富文本编辑器UEditor自定义工具栏(三、自定义工具栏功能按钮图标及工具栏样式简单修改)
导读 富文本编辑器UEditor提供丰富了定制配置项,如果想设置个性化的工具栏按钮图标有无办法呢?答案是肯定的!前两篇博文简要介绍了通过将原工具栏隐藏,在自定义的外部按钮上,调用UEditor各命令实 ...
- RabbitMQ (二)工作队列
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37620057 本系列教程主要来自于官网入门教程的翻译,然后自己进行了部分的修改与 ...
- MyEclipse代码提示设置
(一)普通代码提示 1. 打开MyEclipse ,然后"window"→"Preferences" 2. 选择"java",展开,&quo ...
- [python]多线程模块thread与threading
Python通过两个标准库(thread, threading)提供了对多线程的支持 thread模块 import time import thread def runner(arg): for i ...
- java 中 一个int类型的num,num&1
n&1 把n与1按位与,因为1除了最低位,其他位都为0,所以按位与结果取决于n最后一位,如果n最后一位是1,则结果为1.反之结果为0.(n&1)==1: 判断n最后一位是不是1(可能用 ...
- bzoj 2653 middle 二分答案 主席树判定
判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...