AudioTrack的基本使用

AudioTrack

之前我们讲过MediaPlayer,MediaPlayer就相当于AudioTrack的包装层,它可以播放MP3,WAV,OGG,AAC,MIDI等,而AudioTrack只能播放PCM数据流

AudioTrack的构造方法

public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode) { ... }

streamType 音频流类型

AudioManager.STREAM_MUSIC:用于音乐播放的音频流。
AudioManager.STREAM_SYSTEM:用于系统声音的音频流。
AudioManager.STREAM_RING:用于电话铃声的音频流。
AudioManager.STREAM_VOICE_CALL:用于电话通话的音频流。
AudioManager.STREAM_ALARM:用于警报的音频流。
AudioManager.STREAM_NOTIFICATION:用于通知的音频流。
AudioManager.STREAM_BLUETOOTH_SCO:用于连接到蓝牙电话时的手机音频流。
AudioManager.STREAM_SYSTEM_ENFORCED:在某些国家实施的系统声音的音频流。
AudioManager.STREAM_DTMF:DTMF音调的音频流。
AudioManager.STREAM_TTS:文本到语音转换(TTS)的音频流。

sampleRateInHz 采样率
播放的音频每秒钟会有多少次采样,MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100,目前为常用的采样率
channelConfig 声道数(通道数)
一般可选的就两种,单声道CHANNEL_IN_MONO,双声道CHANNEL_IN_STEREO,建议选择单声道
audioFormat 数据位宽
只支持AudioFormat.ENCODING_PCM_8BIT(8bit)和AudioFormat.ENCODING_PCM_16BIT(16bit)两种,后者支持所有Android手机
bufferSizeInBytes 音频缓冲区大小
建议使用AudioTrack.getMinBufferSize()这个方法获取,参数如上
mode 播放模式
Android 提供了两种播放模式:
MODE_STATIC,一次性将所有数据都写入播放缓冲区中,简单高效,一般用于铃声,系统提醒音,内存比较小的。
MODE_STREAM,需要按照一定的时间间隔,不断的写入音频数据,理论上它可以应用于任何音频播放的场景。

public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,int mode, int sessionId) { ... }
静态播放
// ************ 静态播放模式 ************ 
// 直接获取文件大小
InputStream in = getResources().openRawResource(R.raw.ding);
try {
   try {
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       for (int b; (b = in.read()) != -1; ) {
           out.write(b);
       }
       audioData = out.toByteArray();
   } finally {
       in.close();
   }
} catch (IOException ioe) {
   ioe.printStackTrace();
   Log.d(TAG, "读取数据失败!");
}
//构造AudioTrack对象,写入数据并播放
audioTrack = new AudioTrack(
new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .build(),
new AudioFormat.Builder().setSampleRate(22050)
        .setEncoding(AudioFormat.ENCODING_PCM_8BIT)
        .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
        .build(),
audioData.length,
AudioTrack.MODE_STATIC,
AudioManager.AUDIO_SESSION_ID_GENERATE);
audioTrack.write(audioData, 0, audioData.length);
if(audioTrack.getState() == AudioTrack.STATE_UNINITIALIZED){
    Toast.makeText(this,"AudioTrack初始化失败!",Toast.LENGTH_SHORT).show();
    return;
} 
audioTrack.play();
流播放模式
// ************ 流播放 ************ 
final int minBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE_INHZ, AudioFormat.CHANNEL_OUT_MONO, AUDIO_FORMAT);
// 创建 AudioTrack 对象
audioTrack = new AudioTrack(
 new AudioAttributes.Builder()
         .setUsage(AudioAttributes.USAGE_MEDIA)
         .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
         .build(),
 new AudioFormat.Builder().setSampleRate(SAMPLE_RATE_INHZ)
         .setEncoding(AUDIO_FORMAT)
         .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
         .build(),
 minBufferSize,
 AudioTrack.MODE_STREAM,
 AudioManager.AUDIO_SESSION_ID_GENERATE
);
// 检查初始化是否成功
if(audioTrack.getState() == AudioTrack.STATE_UNINITIALIZED){
    Toast.makeText(this,"AudioTrack初始化失败!",Toast.LENGTH_SHORT).show();
    return;
} 
// 播放
audioTrack.play();
//子线程中文件流写入
workHandler.post(new Runnable() {
   @Override
   public void run() {
       try {
           final File file = new File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.pcm");
           FileInputStream fileInputStream = new FileInputStream(file);
           byte[] tempBuffer = new byte[minBufferSize];
           while (fileInputStream.available() > 0) {
               int readCount = fileInputStream.read(tempBuffer);
               if (readCount == AudioTrack.ERROR_INVALID_OPERATION ||
                       readCount == AudioTrack.ERROR_BAD_VALUE) {
                   continue;
               }
               if (readCount != 0 && readCount != -1) {
                   audioTrack.write(tempBuffer, 0, readCount);
               }
           }
           fileInputStream.close();
       } catch (IOException ioe) {
           ioe.printStackTrace();
       }
   }
});
停止播放,销毁资源
// 停止线程
handlerThread.quit();
workHandler.removeCallbacksAndMessages(null);
if(audioTrack.getState() != AudioTrack.STATE_UNINITIALIZED){
    audioTrack.stop();
    audioTrack.release();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值