- 浏览: 1291 次
- 来自: ...
文章分类
最新评论
[转]Android Audio简述
转自:http://vaero.blog.51cto.com/4350852/834880
Android Audio简述
简单点MediaPlayer,复杂点……不会啊T^T,怎么办!
一、MediaPlayer
在package android.media包内,MediaPlayer的API说明得很详细了^^。摘张图过来:
另外,在其Valid and invalid states一节中列了张表格,详细的描述了MediaPlayer各方法在各状态下是否有效。(就不摘过来了^^)
二、音乐播放器
MediaPlayer控制音乐文件播放的简易实现,就是控制上图的流程^^。
1)播放控制接口
定义了播放器基本模式、状态及控制操作方法。
2)文件列表控件
自定义的ListView控件,主要实现功能如下:
1. 异步搜索/mnt/sdcard/music/目录下所有mp3文件
2. 以自定义适配器方式,使得选中的Item保持高亮背景色
3)文件列表播放器
用MediaPlayer实现了IPlayer播放控制接口。
4)播放器活动
界面上各点击事件与播放控制接口结合。
5)其他设置(样例中未写==)
5.1)播放进度
使用MediaPlayer提供了如下3个方法即可:
1. getDuration():获得总持续时间(毫秒)
{Idle, Initialized, Error}状态时,该方法无效。
2. getCurrentPosition():获得当前播放位置(毫秒)
{Error}状态时,该方法无效。
3. seekTo(int msec):跳至指定的时间位置(毫秒)
{Idle, Initialized, Stopped, Error}状态时,该方法无效。
5.2)音量控制
使用AudioManager的setStreamVolume(int streamType, int index, int flags)方法。第一个参数设置为AudioManager.STREAM_MUSIC,即为音乐音量。
三、其他音频类
一样是在package android.media包内,还有好几个以Player后缀结束的类呢T^T。没用过,也不多作介绍了。
这节呢,主要是想介绍下SoundPool,以及它与MediaPlayer的利弊及使用场合。
1)利弊及场合
MediaPlayer资源占用多、延迟长、不支持多个音频同时播放。在快速连续播放音效时,尤其会感受到。而SoundPool则不同,占用少、延迟短、支持多音频播放。因为其限制最大只能申请1M的内存,也就意味着是用于播放音频片断的。
总结就是,MediaPlayer播放长音乐,SoundPool播放短音效==。
2)SoundPool注意点
1. 音效文件不易过大(限制1M内存)
如果音效文件过大而没有载入完成,调用play()可能会产生严重的后果。当然可以用SoundPool.OnLoadCompleteListener来判断是否载入完成。
2. pause&stop方法建议不轻易使用
有时会使你程序莫名终止。也有反映不会立即终止,而是等缓冲区播放完,会多一秒。
3. 音频格式建议使用OGG格式。
说是WAV在音效播放间隔较短的情况下会出现异常关闭的情况。另外说是,目前只对16位的WAV支持较好。(目前不知道指什么时候==)
参考自网络,未亲自证实,尽量避免就行了^^。
3)SoundPool的使用
SoundPool基本的播放控制方法。方法的详细说明都在注释了^^。
四、MediaRecorder
在Camera摄像里,MediaRecorder用来录制视频了。这里是介绍录制音频了^^。好吧,再摘张图过来(真心觉着看看API就好了,可以把我忽视==):
五、简易录音机
简易的录音机,就是能录音和回放一下的那种==。
1)录音机对象
录音机的简单实现。MediaRecorder控制录音、MediaPlayer用于播放,设置了其各个阶段状态。
2)录音机活动
录音机控制界面。进行录音&播放控制,并显示有时间。
3)其他设置(样例中未写)
MediaRecorder的getMaxAmplitude()可以获得音频资源的最大振幅,可以用于展示下录音时的波幅线条?
增加设置文件大小限制或物体空间限制,提示剩余时间。物理空间可以用package android.os包内的StatFs类。StatFs是Unix statfs()的一个包装,用于检索文件系统空间的整体信息。在之前Camera摄像的CameraVideoActivity内稍带用了下的^^。
当然,这些功能在系统自带的录音机里都有实现了的,直接可以用==。
六、后记
1)扩展内容
1.1)android获取多媒体信息之音频文件
http://hi.baidu.com/shiwl111/blog/item/98b42ed041ea7c2d960a16d8.html
1.2)RandomMusicPlayer:Service方式如何进行音乐播放控制(官方例子)
http://developer.android.com/resources/samples/RandomMusicPlayer/index.html
1.3)Jamendo:一款开源在线音乐播放器
Google Code:http://code.google.com/p/jamendo/
源码分析系列:http://blog.csdn.net/gaomatrix/article/category/900092
2)模块概览
2.1)Audio MediaPlayer
2.2)Audio SoundPool
2.3)Audio MeidaRecorder
Audio MeidaRecorder
3)运行效果
3.1)音乐播放器
Audio MeidaRecorder
3.2)SoundPool
Audio MeidaRecorder
3.3)简单录音机
Audio MeidaRecorder
本文出自 “-_--___---_-” 博客,请务必保留此出处http://vaero.blog.51cto.com/4350852/834880
Android Audio简述
简单点MediaPlayer,复杂点……不会啊T^T,怎么办!
一、MediaPlayer
在package android.media包内,MediaPlayer的API说明得很详细了^^。摘张图过来:
另外,在其Valid and invalid states一节中列了张表格,详细的描述了MediaPlayer各方法在各状态下是否有效。(就不摘过来了^^)
二、音乐播放器
MediaPlayer控制音乐文件播放的简易实现,就是控制上图的流程^^。
1)播放控制接口
定义了播放器基本模式、状态及控制操作方法。
public interface IPlayer { // 播放模式 enum PlayMode { ONCE, CYCLE } // 播放状态 enum Status { PLAYING, STOPPED, PAUSING }; // 获得当前播放模式 PlayMode getMode(); // 设置当前播放模式 void setMode(PlayMode mode); // 获得当前播放状态 Status getStatus(); // 指向上一首音乐 File prev(); // 指向下一首音乐 File next(); // 播放当前音乐 boolean play(); // 暂停当前音乐 boolean pause(); // 恢复播放音乐 boolean resume(); // 停止当前音乐 boolean stop(); // 释放资源 void release(); }
2)文件列表控件
自定义的ListView控件,主要实现功能如下:
1. 异步搜索/mnt/sdcard/music/目录下所有mp3文件
2. 以自定义适配器方式,使得选中的Item保持高亮背景色
3)文件列表播放器
用MediaPlayer实现了IPlayer播放控制接口。
public class FileListViewPlayer implements IPlayer, AdapterView.OnItemClickListener { private MediaPlayer mMediaPlayer; // MediaPlayer对象 private FileListView mFileListView; // FileListView组件 private ArrayList<File> musicFileList; // 音乐文件列表 private int index = 0; // 当前索引 private PlayMode mPlayMode = PlayMode.CYCLE; // 播放模式 private Status mStatus = Status.STOPPED; // 播放状态 private OnMusicClickListener listener; // 音乐文件点击监听 // 音乐点击事件监听接口 public interface OnMusicClickListener { // 返回true及时播放,false则不及时播放 boolean onMusicClick(File musicFile); } public FileListViewPlayer(FileListView fileListView) { this.mFileListView = fileListView; fileListView.setOnItemClickListener(this); // 设置Item点击时间监听 mMediaPlayer = new MediaPlayer(); // 创建MediaPlayer对象 } // 是否有音乐 private boolean hasMusic() { musicFileList = mFileListView.getMusicFileList(); return (null != musicFileList && musicFileList.size() >= 1); } // 选中某项&设置索引 private void setSelection(int position) { mFileListView.setSelectItem(position); // 选中position index = position; // 指向position } @Override public PlayMode getMode() { return mPlayMode; } @Override public void setMode(PlayMode mode) { this.mPlayMode = mode; } @Override public Status getStatus() { return mStatus; } @Override public File prev() { if (hasMusic()) { int location = index - 1 >= 0 ? index - 1 : musicFileList.size() - 1; setSelection(location); return musicFileList.get(location); } return null; } @Override public File next() { if (hasMusic()) { int location = index + 1 < musicFileList.size() ? index + 1 : 0; setSelection(location); return musicFileList.get(location); } return null; } @Override public boolean play() { if (mStatus != Status.STOPPED || !hasMusic()) { return false; } try { mMediaPlayer.reset(); mMediaPlayer.setDataSource(musicFileList.get(index).toString()); mMediaPlayer.prepare(); mMediaPlayer.start(); // 如果是顺序循环播放 if (mPlayMode == PlayMode.CYCLE) { mMediaPlayer .setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { stop(); // 停止 next(); // 下首 play(); // 播放 } }); } mStatus = Status.PLAYING; return true; } catch (Exception e) { e.printStackTrace(); } return false; } @Override public boolean pause() { if (mStatus != Status.PLAYING) { return false; } mMediaPlayer.pause(); mStatus = Status.PAUSING; return true; } @Override public boolean resume() { if (mStatus != Status.PAUSING) { return false; } mMediaPlayer.start(); mStatus = Status.PLAYING; return true; } @Override public boolean stop() { if (mStatus != Status.STOPPED) { mMediaPlayer.stop(); mStatus = Status.STOPPED; return true; } return false; } @Override public void release() { stop(); mMediaPlayer.release(); mMediaPlayer = null; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { setSelection(position); if (null != listener && hasMusic()) { if (listener.onMusicClick(musicFileList.get(position))) { stop(); // 停止 play(); // 播放 } } } public void setOnMusicClickListener(OnMusicClickListener listener) { this.listener = listener; } }
4)播放器活动
界面上各点击事件与播放控制接口结合。
5)其他设置(样例中未写==)
5.1)播放进度
使用MediaPlayer提供了如下3个方法即可:
1. getDuration():获得总持续时间(毫秒)
{Idle, Initialized, Error}状态时,该方法无效。
2. getCurrentPosition():获得当前播放位置(毫秒)
{Error}状态时,该方法无效。
3. seekTo(int msec):跳至指定的时间位置(毫秒)
{Idle, Initialized, Stopped, Error}状态时,该方法无效。
5.2)音量控制
使用AudioManager的setStreamVolume(int streamType, int index, int flags)方法。第一个参数设置为AudioManager.STREAM_MUSIC,即为音乐音量。
三、其他音频类
一样是在package android.media包内,还有好几个以Player后缀结束的类呢T^T。没用过,也不多作介绍了。
这节呢,主要是想介绍下SoundPool,以及它与MediaPlayer的利弊及使用场合。
1)利弊及场合
MediaPlayer资源占用多、延迟长、不支持多个音频同时播放。在快速连续播放音效时,尤其会感受到。而SoundPool则不同,占用少、延迟短、支持多音频播放。因为其限制最大只能申请1M的内存,也就意味着是用于播放音频片断的。
总结就是,MediaPlayer播放长音乐,SoundPool播放短音效==。
2)SoundPool注意点
1. 音效文件不易过大(限制1M内存)
如果音效文件过大而没有载入完成,调用play()可能会产生严重的后果。当然可以用SoundPool.OnLoadCompleteListener来判断是否载入完成。
2. pause&stop方法建议不轻易使用
有时会使你程序莫名终止。也有反映不会立即终止,而是等缓冲区播放完,会多一秒。
3. 音频格式建议使用OGG格式。
说是WAV在音效播放间隔较短的情况下会出现异常关闭的情况。另外说是,目前只对16位的WAV支持较好。(目前不知道指什么时候==)
参考自网络,未亲自证实,尽量避免就行了^^。
3)SoundPool的使用
SoundPool基本的播放控制方法。方法的详细说明都在注释了^^。
public class SoundPoolActivity extends Activity implements SoundPool.OnLoadCompleteListener { private static final int SOUND_BASE = 0; private static final int SOUND_THUNDER = SOUND_BASE + 1; private static final int SOUND_NIGHTINGALE = SOUND_BASE + 2; private SoundPool mSoundPool; // SoundPool对象 private HashMap<Integer, Integer> soundPoolMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.audio_pool); initSounds(); // 初始化SoundPool } // 初始化SoundPool private void initSounds() { /* * SoundPool(int maxStreams, int streamType, int srcQuality) * * maxStreams:同时播放的流的最大数量 * streamType:流的类型(AudioManager类中描述的)。例如:游戏应用一般使用STREAM_MUSIC * srcQuality:采样率转化质量。当前无效果,使用0作为默认值 */ mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); /* * Android 2.2(API 8及以上)才有这接口== */ mSoundPool.setOnLoadCompleteListener(this); soundPoolMap = new HashMap<Integer, Integer>(); /* * load()有四种方法,如下: * * 1)int load(Context context, int resId, int priority) * 从APK资源载入(一般在res/raw目录下) * 2)int load(FileDescriptor fd, long offset, long length, int priority) * 从FileDescriptor对象载入 * 3)int load(AssetFileDescriptor afd, int priority) * 从Asset对象载入 * 4)int load(String path, int priority) * 从完整文件路径名载入 * * 最后priority参数为优先级,播放多文件时处理用。 */ soundPoolMap .put(SOUND_THUNDER, mSoundPool.load(this, R.raw.thunder, 1)); soundPoolMap.put(SOUND_NIGHTINGALE, mSoundPool.load(this, R.raw.nightingale, 2)); } // 雷声 public void bird(View v) { /* * play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) * * soundID:load()方法返回的int值 * leftVolume:左音量。范围=[0.0,1.0] * rightVolume:右音量。范围=[0.0,1.0] * priority:优先级。最低=0 * loop:循环次数。不循环=0;永远循环=-1 * rate:速率。正常=1;范围=[0.5,2.0] */ mSoundPool.play(soundPoolMap.get(SOUND_THUNDER), 1, 1, 0, 0, 1); } // 雷声+夜莺 public void mix(View v) { mSoundPool.play(soundPoolMap.get(SOUND_THUNDER), 1, 1, 0, 0, 1); mSoundPool.play(soundPoolMap.get(SOUND_NIGHTINGALE), 1, 1, 0, 0, 1); } @Override public void onBackPressed() { super.onBackPressed(); mSoundPool.release(); } @Override public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { // Log.d("TAG", "==" + sampleId + "=="); } }
四、MediaRecorder
在Camera摄像里,MediaRecorder用来录制视频了。这里是介绍录制音频了^^。好吧,再摘张图过来(真心觉着看看API就好了,可以把我忽视==):
五、简易录音机
简易的录音机,就是能录音和回放一下的那种==。
1)录音机对象
录音机的简单实现。MediaRecorder控制录音、MediaPlayer用于播放,设置了其各个阶段状态。
public class Recorder implements OnCompletionListener, OnErrorListener { // 录音机状态 public enum Status { IDLE, RECORDING, PLAYING } // 当前状态 private Status mStatus = Status.IDLE; // 媒体录制对象 private MediaRecorder mRecorder = null; // 媒体播放对象 private MediaPlayer mPlayer = null; // 录制的文件 File mSampleFile = null; // 录音或播放开始时间 long mSampleStart = 0; private OnRecorderListener listener; // 播放器接口 public interface OnRecorderListener { void error(); void playOver(); } // 返回录音机状态 public Status getStatus() { return mStatus; } // 是否录过音 public boolean isRecorded() { return mSampleFile != null; } // 返回时间进度(秒) public int progress() { if (mStatus == Status.RECORDING || mStatus == Status.PLAYING) return (int) ((System.currentTimeMillis() - mSampleStart) / 1000); return 0; } // 开始录音 public void startRecording() { stop(); // 停止 if (mSampleFile == null) { // 创建文件,以createTempFile方式避免覆盖 try { File dir = new File(Environment.getExternalStorageDirectory() + "/AndroidMedia/"); if (!dir.exists()) { dir.mkdirs(); } mSampleFile = File.createTempFile("join_", ".3gpp", dir); } catch (IOException e) { e.printStackTrace(); return; } } mRecorder = new MediaRecorder(); // 创建MediaRecorder对象 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置音频信号源:麦克风 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // 设置输出格式 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置音频编码器 mRecorder.setOutputFile(mSampleFile.getAbsolutePath()); // 设置输出文件 try { mRecorder.prepare(); // 准备录音 } catch (Exception e) { mRecorder.reset(); // 重置空闲 mRecorder.release(); // 释放资源 mRecorder = null; // 重置为null return; // 返回 } try { mRecorder.start(); // 开启录音 } catch (RuntimeException e) { // 可能开启不了,如果是来电的话,可以如下判断: // AudioManager.getMode() == MODE_IN_CALL || MODE_IN_COMMUNICATION mRecorder.reset(); // 重置空闲 mRecorder.release(); // 释放资源 mRecorder = null; // 重置为null return; // 返回 } mSampleStart = System.currentTimeMillis(); // 初始化开始时间 mStatus = Status.RECORDING; // 设置录音状态 } // 停止录音 public void stopRecording() { if (mRecorder == null) return; mRecorder.stop(); // 停止录音 mRecorder.release(); // 释放资源 mRecorder = null; // 重置为null mStatus = Status.IDLE; // 设为空闲状态 } // 开始录音 public void startPlayback() { stop(); // 停止 mPlayer = new MediaPlayer(); // 创建MediaPlayer对象 try { mPlayer.setDataSource(mSampleFile.getAbsolutePath()); // 设置数据资源路径 mPlayer.setOnCompletionListener(this); // 设置完成监听接口 mPlayer.setOnErrorListener(this); // 设置错误监听接口 mPlayer.prepare(); // 准备 mPlayer.start(); // 播放 } catch (Exception e) { mPlayer = null; // 重置为null return; } mSampleStart = System.currentTimeMillis(); // 初始化开始时间 mStatus = Status.PLAYING; // 设置录音状态 } // 停止录音 public void stopPlayback() { if (mPlayer == null) return; mPlayer.stop(); // 停止播放 mPlayer.release(); // 释放资源 mPlayer = null; // 重置为null mStatus = Status.IDLE; // 设为空闲状态 } // 停止操作 public void stop() { stopRecording(); stopPlayback(); } @Override public boolean onError(MediaPlayer mp, int what, int extra) { stop(); // 停止 if (null != listener) { listener.error(); } return true; } @Override public void onCompletion(MediaPlayer mp) { stop(); // 停止 if (null != listener) { listener.playOver(); } } // 设置播放器接口 public void setOnRecorderListener(OnRecorderListener listener) { this.listener = listener; } }
2)录音机活动
录音机控制界面。进行录音&播放控制,并显示有时间。
3)其他设置(样例中未写)
MediaRecorder的getMaxAmplitude()可以获得音频资源的最大振幅,可以用于展示下录音时的波幅线条?
增加设置文件大小限制或物体空间限制,提示剩余时间。物理空间可以用package android.os包内的StatFs类。StatFs是Unix statfs()的一个包装,用于检索文件系统空间的整体信息。在之前Camera摄像的CameraVideoActivity内稍带用了下的^^。
当然,这些功能在系统自带的录音机里都有实现了的,直接可以用==。
六、后记
1)扩展内容
1.1)android获取多媒体信息之音频文件
http://hi.baidu.com/shiwl111/blog/item/98b42ed041ea7c2d960a16d8.html
1.2)RandomMusicPlayer:Service方式如何进行音乐播放控制(官方例子)
http://developer.android.com/resources/samples/RandomMusicPlayer/index.html
1.3)Jamendo:一款开源在线音乐播放器
Google Code:http://code.google.com/p/jamendo/
源码分析系列:http://blog.csdn.net/gaomatrix/article/category/900092
2)模块概览
2.1)Audio MediaPlayer
2.2)Audio SoundPool
2.3)Audio MeidaRecorder
Audio MeidaRecorder
3)运行效果
3.1)音乐播放器
Audio MeidaRecorder
3.2)SoundPool
Audio MeidaRecorder
3.3)简单录音机
Audio MeidaRecorder
本文出自 “-_--___---_-” 博客,请务必保留此出处http://vaero.blog.51cto.com/4350852/834880
相关推荐
### Android Audio 音频调试技巧 在Android平台上进行音频调试是一项重要的技能,它涉及到音频硬件、软件以及系统级配置等多个方面。本文将详细介绍如何利用不同的工具和技术来诊断和解决音频问题,包括查看声卡...
主要介绍 述写了Android Audio部分,感觉 很不错的
Android 11 Audio相关流程时序图,需要使用EA画图工具打开。包含Audio中音量获取/设置、焦点申请/放弃、属性设置等相关流程,从APP层到Hal层。详细讲解相关文章参考:...
在Android平台上,音频录制是应用程序开发中的一个常见需求,`AudioRecord`类是Android SDK提供的一种用于低级音频数据录制的API。这个`Android audioRecord录音Demo`将向我们展示如何利用`AudioRecord`类来实现一个...
android audio 框架流程分析图
在Android平台上,AudioRecord类是音频输入的核心组件,它允许开发者录制音频数据并进行处理。这个"Android AudioRecord Demo.zip"文件很可能包含了演示如何使用AudioRecord类的一个示例项目。让我们深入了解一下...
在Android系统中,Audio HAL(Hardware Abstraction Layer)是操作系统与硬件之间的重要接口,它负责处理音频输入和输出的低级操作。这篇关于"android_audio_HAL"的详细文档,主要涵盖了Android音频HAL的移植和Audio...
android AudioRecord AudioTrack实现录音并播放 并支持参数选择(频率、编码格式、声道) 更多信息可参考http://blog.sina.com.cn/u/1788464665
首先,`AudioRecord`是Android提供的一个低级API,允许开发者直接访问音频硬件来录制声音。它提供了高度的自定义性,可以控制采样率、通道数、位深度等参数。使用`AudioRecord`进行录音的基本步骤如下: 1. 初始化`...
最后,日志中提到了`audio_policy.conf`文件的重要性,这个文件用于描述音频系统的输入和输出设备,如果缺失或配置不正确,可能导致音频系统工作异常。 ### 总结 综上所述,Android音频系统是一个复杂但功能强大的...
一个挺简单的Android audio多媒体编程实例,在源代码中:声明一个ImageButton,TextView,MediaPlayer变量,声明一个Flag作为确认音乐是否暂停的变量并默认为false,通过findViewById构造器创建TextView与ImageView...
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 往SDCard写入数据权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 在SDCard中创建与删除文件权限 ...
在Android平台上,`AudioRecord`类是用于音频输入的核心组件,它允许开发者捕获设备麦克风的声音数据。本文将深入探讨如何使用`AudioRecord`进行录音,并结合图形绘制技术,实时展示音频波形,实现一个简易的音频...
本文将深入探讨Android音频框架,特别是AudioTrack、AudioRecord、AudioSystem、AudioPolicyService、AudioFlinger以及Audio HAL,并讨论它们在音视频处理中的作用。 1. AudioTrack: AudioTrack是Android应用程序...
根据提供的文档信息,本文将对Android Audio架构进行深入解析,并重点介绍Audio HAL层驱动的相关细节。 ### 一、Android Audio架构概述 #### 目标背景 随着Android系统的迅速崛起,其市场份额已经超越了iOS和...
AudioFlinger和AudioPolicy两者是Android Audio框架层最主要的两个服务,他们两个是Android框架层的本地服务,在init.rc中启动; AudioPolicyManager负责音频策略定制者,说白了就相当于Audio系统的司令。 Audio...
Android Audio 音频开发 Android 音频系统是 Android 平台中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。这个系统主要分成四个层次:媒体库提供的音频系统本地部分接口、AudioFlinger 作为音频系统...
在Android操作系统中,AudioFlinger是音频服务的核心组件,它负责处理音频的混合、路由、硬件交互以及与其他音频服务的协作。本分析将专注于在Android 12版本中,AudioFlinger在Rockchip RK3588处理器上的实现和优化...
以上就是使用Android AudioRecorder进行pcm录音和pcm转wav的核心知识。在提供的`AudioRecordDemo`项目中,可能包含了实现这些功能的具体代码,你可以参考学习,理解其中的逻辑和细节,以便在实际开发中灵活运用。