【问题标题】:Play PCM stream in Android在 Android 中播放 PCM 流
【发布时间】:2017-05-23 08:33:03
【问题描述】:

我正在通过以太网端口获取 PCM 流。到目前为止,我能够捕获数据包并从中取出 pcm_payload 数据。

如何在 android 中播放这些原始 PCM 数据? PCM数据为16位2通道,44.1kHZ速率流。

我对 android 应用程序编程和音频编程都是新手。对不起,如果这是一个微不足道的问题。

【问题讨论】:

    标签: android audio audio-streaming pcm


    【解决方案1】:

    这是我的解决方案。将流写入文件并播放它

    public class AudioTrackPlayer {
    private String pathAudio;
    private AudioTrack audioPlayer;
    private Thread mThread;
    private int bytesread = 0, ret = 0;
    private int size;
    private FileInputStream in = null;
    private byte[] byteData = null;
    private int count = 512 * 1024; // 512 kb
    private boolean isPlay = true;
    private boolean isLooping = false;
    private static Handler mHandler;
    
    public AudioTrackPlayer() {
    
    }
    
    public void prepare(String pathAudio){
        this.pathAudio = pathAudio;
        mHandler = new Handler();
    }
    
    public void play(){
        stop();
    
        isPlay = true;
        bytesread = 0;
        ret = 0;
        if (pathAudio == null)
            return;
    
        audioPlayer = createAudioPlayer();
        if (audioPlayer == null) return;
        audioPlayer.play();
    
        mThread = new Thread(new PlayerProcess());
        mThread.start();
    }
    
    private final Runnable mLopingRunnable = new Runnable() {
        @Override
        public void run() {
            play();
        }
    };
    
    private AudioTrack createAudioPlayer(){
        int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT);
        AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
        if (audioTrack == null) {
            Log.d("TCAudio", "audio track is not initialised ");
            return null;
        }
    
        File file = null;
        file = new File(pathAudio);
    
        byteData = new byte[(int) count];
        try {
            in = new FileInputStream(file);
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    
        size = (int) file.length();
        return  audioTrack;
    }
    
    private class PlayerProcess implements Runnable{
    
        @Override
        public void run() {
            while (bytesread < size && isPlay) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
                try {
                    ret = in.read(byteData, 0, count);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (ret != -1) { // Write the byte array to the track
                    audioPlayer.write(byteData,0, ret);
                    bytesread += ret;
                } else break;
            }
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (audioPlayer!=null){
                if (audioPlayer.getState()!=AudioTrack.PLAYSTATE_STOPPED){
                    audioPlayer.stop();
                    audioPlayer.release();
                    mThread = null;
                }
            }
            if (isLooping && isPlay ) mHandler.postDelayed(mLopingRunnable,100);
        }
    }
    
    public void setLooping(){
        isLooping = !isLooping;
    }
    
    public void pause(){
    
    }
    
    public void stop(){
        isPlay = false;
        if (mThread != null) {
            mThread.interrupt();
            mThread = null;
        }
        if (audioPlayer != null) {
            audioPlayer.stop();
            audioPlayer.release();
            audioPlayer = null;
        }
    }
    
    public void reset(){
    
    }
    

    }

    【讨论】:

      【解决方案2】:

      您可以使用 AudioTrack 播放 PCM 数据!

      可能是这样的:

      int bufsize = AudioTrack.getMinBufferSize(44100,
                 AudioFormat.CHANNEL_OUT_STEREO,
                 AudioFormat.ENCODING_PCM_16BIT);
      
      AudioTrack audio = new AudioTrack(AudioManager.STREAM_MUSIC, 
                             44100, //sample rate
                             AudioFormat.CHANNEL_OUT_STEREO, //2 channel
                             AudioFormat.ENCODING_PCM_16BIT, // 16-bit
                             bufsize, 
                             AudioTrack.MODE_STREAM );
      audio.play()
      

      然后调用audio.write() 来写入您的 PCM 数据。

      【讨论】:

      • CHANNEL_CONFIGURATION_STEREO 似乎已经过时了。我改用了 CHANNEL_OUT_STEREO。有用。没事吧?
      • 是的,CHANNEL_CONFIGURATION_STEREO 和 CHANNEL_OUT_STEREO 都是 2 声道!
      • 好的。我只是相应地编辑了答案。此外,play() 必须在 write 之前被调用。只有一个 play() 就足以用于多个 write() 调用。但是,在写入 audioTrack() 之前,我必须将数据从大端转换为小端。经过我的编辑,如果您认为还需要编辑答案,请这样做。谢谢。
      • 很抱歉我的粗心大意,可能我表达的不是很清楚,您编辑和评论的内容似乎更清晰,更正确!
      • 有没有办法提供来自远程服务器的 PCM 流?我的意思是,对于audio.write() ?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 2013-01-05
      • 1970-01-01
      • 2014-01-19
      • 2015-04-23
      • 2014-02-13
      • 1970-01-01
      相关资源
      最近更新 更多