【问题标题】:Looping an audio file循环播放音频文件
【发布时间】:2015-11-13 00:27:47
【问题描述】:

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

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(),但是有一个短暂的延迟,而且我认为这不是正确的方法。

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

【问题讨论】:

    标签: android audio


    【解决方案1】:

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

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

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

    【讨论】:

    • 仍然没有运气...我尝试将缓冲区的大小设置为最小值的 10 倍。我是从错误的地方调用 setLoopPoints 吗?我在写完之后玩之前就有了。无论我投入什么,它似乎总是返回 -3。
    • 无效操作.....是啊...我认为您需要使用 MODE_STATIC,我不相信系统知道如何处理 MODE_STREAM 上的循环。
    • 就是这样!现在正在循环。虽然循环之间仍然有一点停顿,有没有办法摆脱这个?
    • 试试 track.setLoopPoints(0, signal.length/2-1, -1); ?您会丢失一点音频,但如果您真的很在意,那么(小心地)将轨道的开头拼接到结尾(因此轨道数据更长),然后保持循环帧长度。
    • 它还在那里,几乎听起来像是敲击声。我检查了我的缓冲区,第一个值为 0。我删除了它,但噪音仍然存在......嗯。信号只是一个方波,所以除了最小值/最大值之外,不应该有任何额外的值。
    【解决方案2】:

    要在 MODE_STREAM 中循环,请等待写入循环完成。然后设置循环点,然后再次调用播放。我对循环甚至非循环 AudioTrack 所做的一切都没有解决点击开始的问题。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我现在遇到了同样的问题,似乎循环不适合我,循环之间总是有一点“中断”,然后我尝试继续生成声音并输入音轨,它对我有用:

        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);
                }
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-26
          相关资源
          最近更新 更多