循环播放音频文件

时间:2011-04-27 00:24:40

标签: android audio

我正在尝试生成并播放方波。我正在生成信号,然后使用

track = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, minSize,
                AudioTrack.MODE_STREAM);    
track.write(signal, 0, signal.length);

然后调用track.play()。问题是它只播放一次。看起来有一种设置循环点的方法,但我不知道要为帧添加什么。

我也尝试在while循环中调用track.write()然后调用track.play(),但是有一个短暂的延迟,我认为这不是正确的方法。

无缝循环的正确方法是什么?

4 个答案:

答案 0 :(得分:6)

有一个非常相似的问题:https://stackoverflow.com/questions/4241724/androidaudiotrack-setlooppoint-issue

如果我正确阅读了Android文档,那么您使用的是16位样本,因此signal.length / 2是样本数。我试试:

track.setLoopPoints(0, signal.length/2, -1);

答案 1 :(得分:1)

要在MODE_STREAM中循环,请等到写循环结束。然后设置循环点,然后再次调用play。我没有做任何循环,甚至非循环的AudioTrack,已经治愈了点击开始。

答案 2 :(得分:0)

要无限次循环音频文件,请将循环设置为-1。要在循环播放音频文件时消除延迟,请使用SoundPool类而不是MediaPlayer

答案 3 :(得分:0)

我现在面临同样的问题,看起来循环对我来说效果不好,循环之间总有一点“休息”,然后我尝试继续生成声音并提供录音带,它对我有用:

class ToneGenerator {
    int sampleRate = 8000;
    double sample[] = null;
    byte generatedSnd[] = null;
    int m_ifreq = 400;
    Thread m_PlayThread = null;
    boolean m_bStop = false;
    AudioTrack m_audioTrack = null;
    int m_play_length = 1000;//in seconds

    static public void PlayTone(int freq, int play_length) {
        ToneGenerator player = new ToneGenerator();
        player.m_ifreq = freq;
        player.m_play_length = play_length;
        player.play();
    }

    synchronized void stop() {
        m_bStop = true;
        if (m_PlayThread != null) {
            try {
                m_PlayThread.interrupt();
                m_PlayThread.join();
                m_PlayThread = null;
            } catch (Exception e) {

            }
        }
        if (m_audioTrack != null) {
            m_audioTrack.stop();
            m_audioTrack.release();
            m_audioTrack = null;
        }
    }

    synchronized void play() {
        m_bStop = false;
        m_PlayThread = new Thread() {
            public void run() {
                try {
                    int iToneStep = 0;

                    m_audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                            sampleRate, AudioFormat.CHANNEL_OUT_MONO,
                            AudioFormat.ENCODING_PCM_16BIT, 2 * sampleRate,
                            AudioTrack.MODE_STREAM);

                    while (!m_bStop && m_play_length-- > 0) {
                        genTone(iToneStep++);

                        m_audioTrack.write(generatedSnd, 0, generatedSnd.length);
                        if (iToneStep == 1) {
                            m_audioTrack.play();
                        }
                    }
                } catch (Exception e) {
                    Log.e("Tone", e.toString());
                } catch (OutOfMemoryError e) {
                    Log.e("Tone", e.toString());
                }

            }
        };
        m_PlayThread.start();
    }

    //Generate tone data for 1 seconds
    synchronized void genTone(int iStep) {
        sample = new double[sampleRate];

        for (int i = 0; i < sampleRate; ++i) {
            sample[i] = Math.sin(2 * Math.PI * (i + iStep * sampleRate) / (sampleRate / m_ifreq));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        generatedSnd = new byte[2 * sampleRate];
        int idx = 0;
        for (final double dVal : sample) {
            // scale to maximum amplitude
            final short val = (short) ((dVal * 32767));
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
        }
    }

}