【问题标题】:Android, live amplitude and pitch detectionAndroid,实时幅度和音高检测
【发布时间】:2019-05-16 13:57:31
【问题描述】:

我正在编写一个需要聆听麦克风并为我提供实时幅度和音高输出的应用。我已经弄清楚如何进行音高识别。我一直在对fft进行大量研究。发现 Android 库 TarsosDSP 让聆听音高变得非常简单:

AudioDispatcher dispatcher = 
        AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
PitchDetectionHandler pdh = new PitchDetectionHandler() {
    @Override
    public void handlePitch(PitchDetectionResult res, AudioEvent e){
        final float pitchInHz = res.getPitch();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                processPitch(pitchInHz);
            }
        });
    }
};
AudioProcessor pitchProcessor = new PitchProcessor(PitchEstimationAlgorithm.FFT_YIN, 22050, 1024, pdh);
dispatcher.addAudioProcessor(pitchProcessor);

Thread audioThread = new Thread(dispatcher, "Audio Thread");
audioThread.start();

我还想出了如何仅使用内置的 android .getMaxAmplitude() 方法进行幅度检测。

但我的问题是,我一生都无法弄清楚如何同时做到这两点。问题是您显然可以运行多个麦克风实例。就像您尝试在单独的线程上运行两个单独的实时录制一样。我已经浏览了整个互联网,试图寻找一些示例代码来让我继续前进,但我找不到任何东西。有没有人做过类似的事情?

编辑 我发现您可以使用 Pitchdetectionhandler 中的 AudioEvent。 audioevent.getbytebuffer() 根据文档返回一个字节数组,其中包含以字节为单位的音频数据:https://0110.be/releases/TarsosDSP/TarsosDSP-latest/TarsosDSP-latest-Documentation/

如果我在转换为 short[] 时没有弄错,那么最大值就是最高幅度,对吧?

但是:

final byte[] audioBytes = e.getByteBuffer();
 short[] shortArray = new short[audioBytes.length];
         for (int index = 0; index < audioBytes.length; index++) {
                    shortArray[index] = (short) audioBytes[index];
                            float item = shortArray[index];
                               if (item > amp){
                                        amp = item;
                                    }
                                }

在这种情况下,amp 总是返回 127。而且这种方法真的不能在现场工作吗?

还有三个问题。我的基本想法是对的,如果是这样,为什么它总是返回 127,我将如何在实时环境中使用它。

【问题讨论】:

  • 我不使用 Android API 但不能pitchInHz = res.getPitch(); 后面也跟.getMaxAmplitude(); 代码?
  • 不,不幸的是它不能,不过那会很棒

标签: java android audio tarsosdsp


【解决方案1】:

自己找到了解决方案。您可以执行 audioEvent.getFloatBuffer() 然后通过一些 fft 方法运行该缓冲区,然后您可以从缓冲区中提取幅度值。缓冲区非常小,所以我最终在该缓冲区运行时从该缓冲区获得了最大幅度,这将为您提供每秒多次的幅度读数,这对我来说已经足够了。 编辑 示例:

 public void handlePitch(PitchDetectionResult result, final AudioEvent e) {

                        final float pitchInHz = result.getPitch();
                        final float[] amplitudes = new float[e.getBufferSize()];

                        new Thread(new Runnable() {
                            public void run() {
                                if (pitchInHz > pitch) {
                                    pitch = pitchInHz;
                                }

                                float[] audioFloatBuffer = e.getFloatBuffer();
                                float[] transformBuffer = new float[e.getBufferSize() * 2];
                                FFT fft = new FFT(e.getBufferSize());
                                System.arraycopy(audioFloatBuffer, 0, transformBuffer, 0, audioFloatBuffer.length);
                                fft.forwardTransform(transformBuffer);
                                fft.modulus(transformBuffer, amplitudes);


                                for (int index = 0; index < amplitudes.length; index++) {
                                    if (amplitudes[index] > amp) {
                                        amp = amplitudes[index];
                                    }
                                }
                            }
                        }).start();
                    }

【讨论】:

  • 您能发布您的解决方案吗?这对我们非常有用,因为我们大多数人也在寻找检测实时振幅的方法
  • 哇,不知道这个旧帖子仍然受到关注,我用我使用的解决方案更新了答案。请记住,这是第一次做这样的事情,从那以后真的没有做过类似的事情。我不知道这是否是一个好方法,它对我有用。
猜你喜欢
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 2017-05-30
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多