【问题标题】:Best way to use Androids Audiotrack使用 Androids Audiotrack 的最佳方式
【发布时间】:2013-07-22 22:04:02
【问题描述】:

我正在实现一个 Android 应用来处理 PCM 声音数据(对于长声音,即音乐曲目)。 我决定使用 AudioTrack 类来播放音乐,但它不能与 Activity 放在同一个线程中,因为它会阻塞整个应用程序 - 这是问题 - 我应该将 AudioTrack 操作放在单独的线程中还是在异步任务(或任何其他选项)中?最好的方法是什么? 我需要播放/暂停/停止和更改音乐文件。

现在我正在尝试通过一个 java 线程来管理它,它几乎没问题 - 播放没问题,几乎暂停(它“丢弃”了一部分声音),但是当我更改音乐文件时,前一个没有停止并且有混合输出(我认为我的线程实现有问题)。

而且 - 不,我不能在这个应用程序中使用 MediaPlayer(我想即时修改 PCM 数据)。

我在 google 和 stackoverflow 上寻找一些帮助,但没有任何帮助。

这是我目前的实现,如果有人想看看。

public class AudioPlayerManager {

private AudioTrack track;
private Thread thread;
private AudioTrackThread trackThread = new AudioTrackThread();

public int getPlayState() {
    return track.getPlayState();
}

public int getAudioSession() {
    return track.getAudioSessionId();
}

class AudioTrackThread implements Runnable {
    private String filePath = "/music/wav/musicfile.wav";

    @Override
    public void run() {
        try {
            playWaveFile();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public void playWaveFile() throws FileNotFoundException {       
        int minSize = AudioTrack.getMinBufferSize(44100,
                AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT);
        track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
                AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, minSize,
                AudioTrack.MODE_STREAM);

        File file = new File(FileListingUtils.getExternalStorageRootFile(),
                filePath);
        InputStream is = new FileInputStream(file);

        byte[] music = new byte[512];
        track.play();

        try {
            handleSound(is, music);
        } catch (IOException e) {
            e.printStackTrace();
        }

        track.stop();
        track.release();
    }

    private void handleSound(InputStream is, byte[] music)
            throws IOException {
        int i;
        while ((i = is.read(music)) != -1) {
            track.write(music, 0, i);
        }
    }
}

public void playNew() {
    if (track != null) {
        track.stop();
        //track.flush();
        track.release();
    }

    thread = new Thread(trackThread);
    thread.start();
}

public void playOrResume() {
    this.track.play();
}

public void pause() {
    this.track.pause();
}

}

感谢您的每一个帮助!

M.

【问题讨论】:

    标签: android multithreading pcm audiotrack


    【解决方案1】:

    您的线程生命周期似乎不正确。首先,每次播放停止或完成时,您都必须关闭(中断)当前线程,并创建线程的新实例并关闭旧线程。

    其次,您从线程外部调用track.stop()。你必须在你的线程中实现一个公共停止方法,然后在那里插入终结代码,然后在你的 playNew() 方法中调用 yourthread.stop()。

    所以这里是伪代码:

    public void playNew() {
    
    //the following if clause should go to thread's stop() method.
      // if (track != null) {
      //  track.stop();
     //track.flush();
     //    track.release();
    // }
      //create a new thread if its null
    if(thread ==null){
    thread = new Thread(new AudioTrackThread());
    thread.start();}
    //stop the current thread
    else{
    thread.stop();
    thread=null;}
    }
    

    关于您的实现,我在某处读到播放音乐,服务和线程将是更好的选择。在android documentation 中阅读有关服务和线程的信息。

    【讨论】:

    • 感谢您的回复!但不幸的是,效果是一样的。我已经稍微改变了我的实现,现在除了加载下一首曲目外一切正常。但我以后会回到这个问题。谢谢!
    • 不客气。请发布您的答案,这可能对其他人有帮助。
    • 请问答案在哪里?
    猜你喜欢
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多