Android音视频开发-AudioTrack

2024-04-26 14:44

本文主要是介绍Android音视频开发-AudioTrack,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android音视频开发-AudioTrack

本篇文章我们主要介绍下AudioTrack.

1: 简介

AudioTrack是Android平台上的一个类,用于播放音频数据.

它允许PCM音频缓冲区流式传输到音频接收器进行播放.

  1. 创建AudioTrack对象:可以通过构造函数创建AudioTrack对象,需要指定音频流类型、采样率、音频通道配置和音频格式等参数。
  2. 写入音频数据:可以使用write()方法将音频数据写入AudioTrack对象。写入的数据可以是PCM格式的原始音频数据,也可以是压缩格式的音频数据(如MP3、AAC等)。
  3. 播放音频数据:在写入音频数据后,可以调用play()方法开始播放音频数据。可以使用pause()方法暂停播放,使用stop()方法停止播放。
  4. 设置音量:可以使用setVolume()方法设置音量大小,范围为0.0到1.0之间。
  5. 设置播放模式:可以使用setPlaybackRate()方法设置播放速率,使用setLoopPoints()方法设置循环播放的起始点和结束点。
  6. 监听播放状态:可以使用OnPlaybackPositionUpdateListener接口监听播放进度和播放完成事件。
  7. 释放资源:在不再需要使用AudioTrack对象时,应该调用release()方法释放资源。

2: 创建AudioTrack对象

public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes, int mode)
throws IllegalArgumentException {this(streamType, sampleRateInHz, channelConfig, audioFormat,bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
}

参数配置:

1: streamType

  1. AudioManager.STREAM_VOICE_CALL:用于语音通话的音频流类型。
  2. AudioManager.STREAM_SYSTEM:用于系统声音的音频流类型,例如按键声音、提示音等。
  3. AudioManager.STREAM_RING: 用于电话铃声的音频流类型。
  4. AudioManager.STREAM_MUSIC:用于音乐播放的音频流类型。
  5. AudioManager.STREAM_ALARM:用于闹钟的音频流类型。
  6. AudioManager.STREAM_NOTIFICATION:用于通知的音频流类型。
  7. AudioManager.STREAM_DTMF:用于双音多频信号的音频流类型

2: sampleRateInHz

采样率的大小限制是4000~192000; 可以在源码中查看:

/** Minimum value for sample rate,*  assuming AudioTrack and AudioRecord share the same limitations.* @hide*/
// never unhide
public static final int SAMPLE_RATE_HZ_MIN = 4000;
/** Maximum value for sample rate,*  assuming AudioTrack and AudioRecord share the same limitations.* @hide*/
// never unhide
public static final int SAMPLE_RATE_HZ_MAX = 192000;
/** Sample rate will be a route-dependent value.* For AudioTrack, it is usually the sink sample rate,* and for AudioRecord it is usually the source sample rate.*/
public static final int SAMPLE_RATE_UNSPECIFIED = 0;

如果不在这个区间,系统则抛出异常:

调用setSampleRate指定sampleRate时,如果不在4000~192000区间则怕出new IllegalArgumentException("Invalid sample rate " + sampleRate).

public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {// TODO Consider whether to keep the MIN and MAX range checks here.// It is not necessary and poses the problem of defining the limits independently from// native implementation or platform capabilities.if (((sampleRate < SAMPLE_RATE_HZ_MIN) || (sampleRate > SAMPLE_RATE_HZ_MAX)) &&sampleRate != SAMPLE_RATE_UNSPECIFIED) {throw new IllegalArgumentException("Invalid sample rate " + sampleRate);}mSampleRate = sampleRate;mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;return this;
}

至于初始化时,校验的方法在audioParamCheck方法中:

// sample rate, note these values are subject to change
if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {throw new IllegalArgumentException(sampleRateInHz+ "Hz is not a supported sample rate.");
}

3: channelConfig

声道配置同样在AudioFormat中定义,常用的有:

AudioFormat.CHANNEL_OUT_MONO:单声道 AudioFormat.CHANNEL_OUT_STEREO:双声道

4:audioFormat

该参数定义音频格式:

  1. AudioFormat.ENCODING_PCM_8BIT:8位PCM编码
  2. AudioFormat.ENCODING_PCM_16BIT:16位PCM编码
  3. AudioFormat.ENCODING_PCM_FLOAT:浮点型PCM编码

5:bufferSizeInBytes

音频缓冲区的大小,以字节为单位.我们可以通过getMinBufferSize()来获取最小缓冲区大小.

6: mode

指定音频输出模式.

Android 系统提供了两种模式如下:

/*** Creation mode where audio data is transferred from Java to the native layer* only once before the audio starts playing.*/
public static final int MODE_STATIC = 0;
/*** Creation mode where audio data is streamed from Java to the native layer* as the audio is playing.*/
public static final int MODE_STREAM = 1;
  1. MODE_STATIC:静态模式,适用于一次性播放完整音频数据的场景
  2. MODE_STREAM:流模式,不间断地写入音频数据.

创建代码如下:

int streamType = AudioManager.STREAM_MUSIC; // 音频流类型
int sampleRateInHz = 44100; // 采样率
int channelConfig = AudioFormat.CHANNEL_OUT_MONO; // 声道配置
int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 音频格式
int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 缓冲区大小
audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM);

3: 写入音频数据+播放

    /*** 播放录音*/private void playAudio() {stopPlay();File file = new File("sdcard/audioRecord.pcm");if (!file.exists()) return;int streamType = AudioManager.STREAM_MUSIC; // 音频流类型int sampleRateInHz = 44100; // 采样率int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; // 声道配置int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 音频格式int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 缓冲区大小audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM);//        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
//            /**
//             * 设置音频信息属性
//             * 1.设置支持多媒体属性,比如audio,video
//             * 2.设置音频格式,比如 music
//             */
//            AudioAttributes attributes = new AudioAttributes.Builder()
//                    .setUsage(AudioAttributes.USAGE_MEDIA)
//                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
//                    .build();
//            /**
//             * 设置音频格式
//             * 1. 设置采样率
//             * 2. 设置采样位数
//             * 3. 设置声道
//             */
//            AudioFormat format = new AudioFormat.Builder()
//                    .setSampleRate(sampleRateInHz)
//                    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
//                    .setChannelMask(channelConfig)
//                    .build();
//            audioTrack = new AudioTrack(attributes,format,bufferSizeInBytes,AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);
//
//        }audioTrack.play();new Thread(() -> {FileInputStream fileInputStream = null;try {fileInputStream = new FileInputStream(file);byte[] buffer = new byte[bufferSizeInBytes];Log.i(TAG, "playAudio: "+bufferSizeInBytes);int read = 0;while (read != -1) {read = fileInputStream.read(buffer);//将缓冲区buffer写入audioTrack进行播放audioTrack.write(buffer, 0, buffer.length);}audioTrack.stop();audioTrack.release();} catch (Throwable e) {}}).start();}

4: 释放

/*** 停止播放录音,并释放资源*/
private void stopPlay() {if (audioTrack != null) {audioTrack.release();}
}

这里注意下,release方法内部实现了stop,所以我们不需要额外的调用stop停止播放.

另外,如果调用停止播放, 内部会判断当前状态,如果非STATE_INITIALIZED下调用,则会抛出异常.

public void stop()
throws IllegalStateException {if (mState != STATE_INITIALIZED) {throw new IllegalStateException("stop() called on uninitialized AudioTrack.");}// stop playingsynchronized(mPlayStateLock) {native_stop();baseStop();mPlayState = PLAYSTATE_STOPPED;mAvSyncHeader = null;mAvSyncBytesRemaining = 0;}
}

这篇关于Android音视频开发-AudioTrack的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/937856

相关文章

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

基于Java开发一个极简版敏感词检测工具

《基于Java开发一个极简版敏感词检测工具》这篇文章主要为大家详细介绍了如何基于Java开发一个极简版敏感词检测工具,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录你是否还在为敏感词检测头疼一、极简版Java敏感词检测工具的3大核心优势1.1 优势1:DFA算法驱动,效率提升10

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Java 与 LibreOffice 集成开发指南(环境搭建及代码示例)

《Java与LibreOffice集成开发指南(环境搭建及代码示例)》本文介绍Java与LibreOffice的集成方法,涵盖环境配置、API调用、文档转换、UNO桥接及REST接口等技术,提供... 目录1. 引言2. 环境搭建2.1 安装 LibreOffice2.2 配置 Java 开发环境2.3 配

Python38个游戏开发库整理汇总

《Python38个游戏开发库整理汇总》文章介绍了多种Python游戏开发库,涵盖2D/3D游戏开发、多人游戏框架及视觉小说引擎,适合不同需求的开发者入门,强调跨平台支持与易用性,并鼓励读者交流反馈以... 目录PyGameCocos2dPySoyPyOgrepygletPanda3DBlenderFife