安卓平台和声音录制与播放相关的主要是4个类:MediaRecorder,MediaPlayer,SoundPool,AudioRecord和AudioTrack。
- 「MediaRecorder」 可以录制视频和音频到文件
- 「MediaPlayer」 可以播放视频和音频文件
- 「SoundPool」 用于播放比较短的音频片段
- 「AudioRecord」 可以提供接口读取音频流数据(byte数组或者short数组)
- 「AudioTrack」 提供接口用于播放音频流数据。
其中MediaRecorder和AudioRecord用于声音录制,SoundPool、MediaPlayer和AudioTrack用于声音播放。AudioRecord和AudioTrack用于操作音频流数据,操作对象是byte数组(或者short数组),而MediaRecorder和MediaPlayer提供了经过更高层抽象和封装接口,直接对文件进行操作,而且它俩功能更丰富,同时支持音频和视频。
MediaRecorder
MediaRecorder是Android提供的一个用于音视频录制的高级类。封装了底层的音视频编码器(通常是MediaCodec)和其他相关组件。如果不需要对音视频进行更底层的控制,只是想要方便地进行录制操作,那么可以选择使用MediaRecorder。
图片
MediaRecorder提供了一系列的方法用于配置和控制录制过程,例如设置音频和视频源、设置输出格式和编码、开始和停止录制等。还提供了错误监听器和信息监听器,以便在录制过程中处理错误事件和获取录制信息。
在配置MediaRecorder时,需要先创建一个MediaRecorder实例,设置音频和视频源,以及输出文件的格式和编码。例如,可以使用setAudioSource()方法设置音频来源,使用setVideoSource()方法设置视频来源,使用setOutputFormat()和setVideoEncoder()等方法设置输出格式和视频编码。
完成配置后,调用MediaRecorder的prepare()方法准备录制,调用start()方法开始录制。当录制完成后调用stop()方法停止录制,最后调用release()方法释放录制资源。
MediaRecorder主要方法:
setAudioChannels(int numChannels) //设置录制的音频通道数
setAudioEncoder(int audio_encoder) //设置audio的编码格式
setAudioEncodingBitRate(int bitRate) //设置录制的音频编码比特率
setAudioSamplingRate(int samplingRate) //设置录制的音频采样率
setAudioSource(int audio_source) //设置用于录制的音源
setAuxiliaryOutputFile(String path) //辅助时间的推移视频文件的路径传递
setAuxiliaryOutputFile(FileDescriptor fd)//在文件描述符传递的辅助时间的推移视频
setCamera(Camera c) //设置一个recording的摄像头
setCaptureRate(double fps) //设置视频帧的捕获率
setMaxDuration(int max_duration_ms) //设置记录会话的最大持续时间(毫秒)
setMaxFileSize(long max_filesize_bytes) //设置记录会话的最大大小(以字节为单位)
setOutputFile(FileDescriptor fd) //传递要写入的文件的文件描述符
setOutputFile(String path) //设置输出文件的路径
setOutputFormat(int output_format) //设置在录制过程中产生的输出文件的格式
setPreviewDisplay(Surface sv) //表面设置显示记录媒体(视频)的预览
setVideoEncoder(int video_encoder) //设置视频编码器,用于录制
setVideoEncodingBitRate(int bitRate) //设置录制的视频编码比特率
setVideoFrameRate(int rate) //设置要捕获的视频帧速率
setVideoSize(int width, int height) //设置要捕获的视频的宽度和高度
setVideoSource(int video_source) //开始捕捉和编码数据到setOutputFile(指定的文件)
setLocation(float latitude, float longitude) //设置并存储在输出文件中的地理数据(经度和纬度)
setProfile(CamcorderProfile profile) //指定CamcorderProfile对象
setOrientationHint(int degrees) //设置输出的视频播放的方向提示
setOnErrorListener(MediaRecorder.OnErrorListener l) //注册一个用于记录录制时出现的错误的监听器
setOnInfoListener(MediaRecorder.OnInfoListener listener) //注册一个用于记录录制时出现的信息事件
getMaxAmplitude() //获取在前一次调用此方法之后录音中出现的最大振幅
prepare() //准备录制。
release() //释放资源
reset() //将MediaRecorder设为空闲状态
start() //开始录制
stop() //停止录制
MediaRecorder主要配置参数:
- 「视频编码格式」MediaRecorder.VideoEncoder
default,H263,H264,MPEG_4_SP,VP8
- 「音频编码格式」MediaRecorder.AudioEncoder
default,AAC,HE_AAC,AAC_ELD,AMR_NB,AMR_WB,VORBIS
- 「视频资源获取方式」MediaRecorder.VideoSource
default,CAMERA,SURFACE
- 「音频资源获取方式」MediaRecorder.AudioSource
defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,voice_recognition, voice_uplink
- 「资源输出格式」MediaRecorder.OutputFormat
amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp,aac_adif, aac_adts, output_format_rtp_avp, output_format_mpeg2ts ,webm
MediaPlayer
MediaPlayer是Android平台上的一个多媒体框架,支持播放各种常见的媒体类型,如音频、视频和图片,能够轻松地将这些媒体内容集成到应用中。
图片
MediaPlayer提供了丰富的API和功能能够灵活地控制媒体的播放。通过MediaPlayer的API可以播放存储在应用资源中的媒体文件、文件系统中的独立文件,或者通过网络连接接收到的数据流中的音频或视频。
在使用MediaPlayer时,需要创建一个MediaPlayer实例,通过调用setDataSource()方法来指定要播放的媒体文件或流的来源。调用prepare()或prepareAsync()方法使MediaPlayer对象进入Prepared状态,准备播放媒体内容。在媒体准备好之后调用start()方法来开始播放。
MediaPlayer还提供了各种控制选项,如暂停、恢复、停止播放,以及调整音量和播放速度等。可以使用MediaPlayer来监听媒体播放过程中的事件,如播放完成、播放错误等,以便进行相应的处理。
MediaPlayer主要方法:
- 「实例化方式」
MediaPlayer mp = new MediaPlayer();
//或
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
- 「设置播放源」
setDataSource(String path)//指定装载path路径所代表的文件。
setDataSource(Context context, Uri uri, Map<String, String headers)//指定装载uri所代表的文件。
setDataSource(Context context, Uri uri)//指定装载uri所代表的文件。
setDataSource(FileDescriptor fd, long offset, long length)//指定装载fd所代表的文件中从offset开始长度为length的文件内容。
setDataSource(FileDescriptor fd)//指定装载fd所代表的文件。
- 「配置播放参数」
setAudioStreamType(int streamtype)//设置音频流的类型。
setDisplay(SurfaceHolder sh)//设置显示方式。
setLooping(boolean looping)//设置是否循环播放。
setNextMediaPlayer(MediaPlayer next)//设置当前流媒体播放完毕,下一个播放的MediaPlayer。
setScreenOnWhilePlaying(boolean screenOn)//设置是否使用SurfaceHolder来显示。
setSurface(Surface surface)//设置Surface。
setVideoScalingMode(int mode)//设置视频缩放的模式。
setVolume(float leftVolume, float rightVolume)//设置播放器的音量。
setWakeMode(Context context, int mode)//为MediaPlayer设置低级电源管理行为。
- 「播放控制函数」
start()//开始或恢复播放。
stop()//停止播放。
pause()//暂停播放。
prepare()//准备播放(装载音频),调用此方法会使MediaPlayer进入Prepared状态。
prepareAsync()//准备播放异步音频。
release()//释放媒体资源
reset()//重置MediaPlayer进入未初始化状态。
seekTo(int msec)//指定的时间位置。
- 「监听事件函数」
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)//注册一个回调函数,在网络视频流缓冲变化时调用。
setOnCompletionListener(MediaPlayer.OnCompletionListener listener)//为Media Player的播放完成事件绑定事件监听器。
setOnErrorListener(MediaPlayer.OnErrorListener listener)//为MediaPlayer的播放错误事件绑定事件监听器。
setOnPreparedListener(MediaPlayer.OnPreparedListener listener)//当MediaPlayer调用prepare()方法时触发该监听器。
setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener)//当MediaPlayer调用seek()方法时触发该监听器。
setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)//注册一个用于监听视频大小改变的监听器。
- 「获取参数函数」
getCurrentPosition()//获取当前播放的位置。
getDuration()//获取音频的时长。
getVideoHeight()//获取视频的高度。
getVideoWidth()//获取视频的宽度。
isLooping()//判断MediaPlayer是否正在循环播放。
isPlaying()//判断MediaPlayer是否正在播放。
SoundPool
SoundPool是Android提供的一个音频播放工具类,主要用于播放较短的音频文件,例如音效、提示音等。
SoundPool特点:
- 「低延迟」:SoundPool使用较低的延迟来播放音频,特别适合实时性要求较高的场景。
- 「资源管理」:SoundPool能够管理多个音频资源,并且可以预加载音频文件,从而提高播放的响应速度。
- 「多次播放」:SoundPool支持多次播放同一个音频文件,能够实现连续播放、循环播放等效果。
- 「多声道支持」:SoundPool支持多声道播放,可以同时播放多个音频文件。
使用SoundPool的基本流程:创建一个SoundPool对象->载入要播放的音频->播放某个音频->在需要时停止播放某个音频。每个载入的音频在SoundPool中都会对应一个SoundID,播放时通过SoundID来指定要播放的音频。
SoundPool的应用场景广泛,包括游戏开发、多媒体应用、音频提示等。在游戏开发中,可以使用SoundPool来播放游戏音效、背景音乐等;在多媒体应用中,可以使用SoundPool来播放短音频片段,如按钮点击音效、提示音等;在音频提示方面,可以使用SoundPool来实现闹钟、提醒等功能。
SoundPool加载的音频资源是加载进内存,所以要求尽可能的短。每个音频资源的大小被限制在1M左右(相当于时长5.6s、采样率在44.1kHz的双声道音频资源)。如果超过这个限制大小,音频会被裁剪。
SoundPool主要方法:
- 「实例化方式」
//参数:
//maxStreams:指定支持多少个声音,SoundPool对象中允许同时存在的最大流的数量,该值太大就会报错AudioFlinger could not create track, status: -12 ,就听不到声音
//streamType:指定声音类型,流类型可以分为STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING,STREAM_MUSIC 和STREAM_ALARM四种类型。在AudioManager中定义。
//srcQuality:指定声音品质(采样率变换质量),一般直接设置为0
SoundPool(int maxStreams, int streamType, int srcQuality)
在低版本中使用上述构造方法,API 21(Android 5.0)后这个构造方法过时了,使用SoundPool.Builder实例化SoundPool:
SoundPool.Builder spb = new SoundPool.Builder();
spb.setMaxStreams(10);
spb.setAudioAttributes(null); //转换音频格式
SoundPool sp = spb.build(); //创建SoundPool对象
- 「加载音频资源文件」
load(Context context, int resId, int priority) //从res资源载入
load(String path, int priority) //文件路径,文件的绝对路线,如存放在sd卡中的音频 priority:没什么用的一个参数,建议设置为1,保持和未来的兼容性
load(FileDescriptor fd, long offset, long length, int priority) //文件描述符
load(AssetFileDescriptor afd, int priority) //从asset目录读取某个资源文件,context.getAssets().openFd("xxx"),xxx表示文件名
上述方法都会返回一个Integer类型的音频ID,后续使用该ID进行播放。
- 「播放音频文件」
//soundID:Load()返回的声音ID号,以上可以通过map.get(1)获取
//leftVolume:左声道音量设置 一般为0-1,默认填1
//rightVolume:右声道音量设置 一般为0-1,默认填1
//priority:指定播放声音的优先级,数值越高,优先级越大。默认填0
//loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
//rate:指定播放速率:1.0的播放率可以使声音按照其原始频率,而2.0的播放速率,可以使声音按照其 原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0。
play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate); //其返回值为一个int类型的数字
如果SoundPool刚调用加载load方法之后,直接调用SoundPool的play方法可能出现error "sample 1 not READY",建议调用加载资源函数load之后,实现资源加载结束的监听函数,在监听到资源加载结束之后,再进行播放音频文件。
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
soundPool.play(1, 1, 1, 0, 0, 1);
}
});
- 卸载音频或者停止播放重置资源
//streamID:通过play()返回
soundPool.pause(int streamID) //暂停指定播放流的音效
//streamID:通过play()返回
soundPool.resume(int streamID) //继续播放指定播放流的音效
//streamID:通过play()返回
soundPool.stop(int streamID) //终止指定播放流的音效
//soundID:load()返回的音频ID
soundPool.unload(int soundID) //卸载一个指定的音频资源.
soundPool.release() //释放SoundPool中的所有音频资源.
AudioRecord
AudioRecord为Android应用提供了一个强大而灵活的音频录制工具。AudioRecord都能提供高质量的音频数据,可用于语音识别、电话录音和其他音频处理任务。
- 「音频源」:AudioRecord支持从多种音频源中录制音频数据,例如麦克风、电话线路、语音识别等。
- 「音频格式」:AudioRecord允许选择不同的音频格式来录制音频数据,如PCM(脉冲编码调制)、AAC(高级音频编码)等。这些格式的选择可以根据应用场景和编码需求进行。
- 「缓冲区」:AudioRecord使用一个缓冲区来存储录制的音频数据。可以指定缓冲区的大小,以适应不同的录制需求。
- 「配置参数」:通过AudioRecord的API接口可以设置录制设备的参数,包括采样率、声道数、音频格式等。
- 「工作流程」:使用AudioRecord进行音频录制的工作流程包括配置参数、初始化内部音频缓冲区、开始采集音频数据、通过线程不断从缓冲区读取数据,并在需要时停止采集和释放资源。
- 「性能与特点」:由于AudioRecord直接与Android的音频硬件交互,在性能上具有显著优势。AudioRecord还具备线程安全、低延迟录制、多格式支持、实时处理、可扩展性强等特点,使得它在各种音频录制场景中都能表现出色。
AudioRecord的工作流程:
(1) 配置参数,初始化内部的音频缓冲区
(2) 开始采集
(3) 需要一个线程,不断地从 AudioRecord 的缓冲区将音频数据“读”出来,注意,这个过程一定要及时,否则就会出现“overrun”的错误,该错误在音频开发中比较常见,意味着应用层没有及时地“取走”音频数据,导致内部的音频缓冲区溢出。
(4) 停止采集,释放资源
AudioRecord的参数配置:
- 「audioSource」 参数指的是音频采集的输入源,可选的值以常量的形式定义在 MediaRecorder.AudioSource 类中,常用的值包括:DEFAULT(默认),VOICE_RECOGNITION(用于语音识别,等同于DEFAULT),MIC(由手机麦克风输入),VOICE_COMMUNICATION(用于VoIP应用)等等。
- 「sampleRateInHz」 采样率,注意,目前44100Hz是唯一可以保证兼容所有Android手机的采样率。
- 「channelConfig」 通道数的配置,可选的值以常量的形式定义在 AudioFormat 类中,常用的是 CHANNEL_IN_MONO(单通道),CHANNEL_IN_STEREO(双通道)。
- 「audioFormat」 这个参数是用来配置“数据位宽”的,可选的值也是以常量的形式定义在 AudioFormat 类中,常用的是 ENCODING_PCM_16BIT(16bit),ENCODING_PCM_8BIT(8bit),注意,前者是可以保证兼容所有Android手机的。
AudioTrack
AudioTrack是Android平台下用于管理和播放单一音频资源的类,特别适合低延迟的播放和流媒体的播放,提供了强大的控制能力。
- 「音频播放」:AudioTrack主要用于播放已经解码的PCM流。通过配置AudioTrack实例,调用其play方法,将AudioTrack切换到播放状态,并启动播放线程循环向AudioTrack的缓冲区写入数据,可以实现音频的播放。
- 「数据加载模式」:AudioTrack提供了两种数据加载模式:MODE_STREAM和MODE_STATIC。MODE_STREAM模式下,音频数据通过write操作一次次写入AudioTrack中,在一定程度上会引入延时。而MODE_STATIC模式下,所有数据在play之前一次性写入AudioTrack的内部缓冲区,后续无需再传递数据,需注意一次性写入的数据量不能过多,以免系统无法分配足够内存。
- 「音频流类型」:在配置AudioTrack时,需要指定音频流类型,如系统声音的音频流、音乐播放的音频流、用于通话的音频流、用于通知的音频流等。有助于系统正确管理音频资源。
- 「实时处理」:AudioTrack可用于播放本地保存的音频文件,还适用于实时音频处理和播放。例如,可以实现音频录制和回放功能,将采集到的音频数据写入AudioTrack对象并播放出来。
AudioTrack的工作流程:
(1) 配置参数,初始化内部的音频播放缓冲区
(2) 开始播放
(3) 需要一个线程,不断地向AudioTrack的缓冲区“写入”音频数据,注意,这个过程一定要及时,否则就会出现“underrun”的错误,该错误在音频开发中比较常见,意味着应用层没有及时地“送入”音频数据,导致内部的音频播放缓冲区为空。
(4) 停止播放,释放资源
AudioTrack的参数配置:
- 「streamType」 这个参数代表着当前应用使用的哪一种音频管理策略,当系统有多个进程需要播放音频时,这个管理策略会决定最终的展现效果,该参数的可选的值以常量的形式定义在 AudioManager 类中,主要包括:
STREAM_VOCIE_CALL:电话声音
STREAM_SYSTEM:系统声音
STREAM_RING:铃声
STREAM_MUSCI:音乐声
STREAM_ALARM:警告声
STREAM_NOTIFICATION:通知声
- 「sampleRateInHz」 采样率,从AudioTrack源码的“audioParamCheck”函数可以看到,这个采样率的取值范围必须在4000Hz~192000Hz之间。
- 「mode」 AudioTrack提供了两种播放模式,一种是static方式,一种是streaming方式,前者需要一次性将所有的数据都写入播放缓冲区,简单高效,通常用于播放铃声、系统提醒的音频片段; 后者则是按照一定的时间间隔不间断地写入音频数据,理论上它可用于任何音频播放的场景。可选的值以常量的形式定义在AudioTrack类中,一个是MODE_STATIC,另一个是MODE_STREAM,根据具体的应用传入对应的值即可。
音频录制选择
MediaRecorder是一个高级别的音频/视频录制工具,集成了录音、编码、封装复用等功能,操作起来相对简单。录制的音频文件经过压缩处理,并可以直接使用系统自带的播放器进行播放。MediaRecorder的简单易用性使其适用于对音频处理要求不高的场景。由于它更多地是系统音频API的封装,对于需要实时处理音频、进行网络传输或直播等高级应用场景,可能并不适用。
AudioRecord则更加接近底层,提供了更加灵活和自由的音频采集和处理能力。支持多种音频编码格式,如PCM、WAV、MP3等,可以满足不同场景下的需求。AudioRecord还设计了灵活的数据处理接口,可以方便地添加自定义的音频处理模块,实现如混响、均衡器等效果。这使得AudioRecord在需要对音频进行进一步算法处理、采用第三方编码库进行压缩、进行网络传输和直播等高级应用场景中表现出色。AudioRecord还具有线程安全、性能优异、可扩展性强等特点,保证了其在多线程环境中的稳定运行,并预留了丰富的接口供拓展定制。
对于音频处理要求不高的场景,可以选择使用MediaRecorder,简单易用,能够直接录制并播放压缩后的音频文件。对于需要对音频进行进一步算法处理、采用第三方编码库进行压缩、进行网络传输和直播等高级应用场景,推荐使用AudioRecord,提供了更加灵活和自由的音频采集和处理能力。
音频播放选择
在选择时需要考虑以下因素:
- 「音频文件的类型」:如果需要播放长时间的音乐或视频文件,MediaPlayer可能是更好的选择;如果需要播放短音频片段,可以考虑使用SoundPool。
- 「播放需求」:如果需要同时播放多个音频,SoundPool是一个很好的选择;如果需要对音频进行更精细的控制,例如调整音量、播放速率等,那么AudioTrack可能更适合。
- 「性能需求」:SoundPool通常具有较低的CPU占用率和反应延迟,适合性能要求较高的应用;而AudioTrack由于更底层,可能需要更多的开发工作,但可以实现更高级别的音频处理和控制。
MediaPlayer主要用于后台长时间播放本地音乐文件或在线流媒体文件。提供了一个高层次的封装,使播放音频变得相对简单。MediaPlayer特别适合那些需要连续播放较长时间音频的应用场景,例如音乐播放器或视频播放器。
SoundPool更适合播放较短的音频片段,如游戏声音、按键声音、铃声片段等。SoundPool可以同时播放多个音频,并且具有较低的CPU占用率和反应延迟。在需要频繁播放短音频的应用中表现出色,例如游戏或通知提示音。
AudioTrack是更加底层的API,主要用于管理和播放单一音频资源。提供了非常强大的控制能力,适合流媒体播放等场景。AudioTrack需要结合解码器来使用,对于需要进行底层音频处理的开发者来说更为适用。