欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android音视频之AudioTrack播放音频(二)

程序员文章站 2022-05-03 11:51:01
前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入到AudioTrack中就可以了,先贴代码 播放的方法,是传入文件路径,AudioRecordMan ......

讲了如何录制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方法跳转到指定位置,可实现播放、暂停、继续播放的功能。