Android, определение амплитуды и высоты тона в реальном времени - PullRequest
1 голос
/ 16 мая 2019

Я пишу приложение, которое должно прослушивать микрофон и выводить мне амплитуду и высоту звука в реальном времени. Я понял, как сделать распознавание высоты тона. Я провел много исследований в 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();

Я также выяснил, как выполнить определение амплитуды, просто используя встроенный метод andget .getMaxAmplitude ().

но моя проблема в том, что я не могу понять, как сделать то и другое одновременно. проблема в том, что вы, очевидно, можете запустить более одного экземпляра микрофона. Как, например, если вы попытаетесь запустить две отдельные записи в прямом эфире в отдельных потоках Я просмотрел весь интернет, пытаясь найти какой-то пример кода, чтобы заставить меня работать, но я ничего не могу найти. Кто-нибудь когда-нибудь делал что-нибудь подобное?

редактировать Я понял, что вы можете использовать AudioEvent из обработчика Pitchdetection. audioevent.getbytebuffer () возвращает байтовый массив с аудиоданными в байтах в соответствии с документацией: https://0110.be/releases/TarsosDSP/TarsosDSP-latest/TarsosDSP-latest-Documentation/.

и если я не ошибаюсь при преобразовании в короткое [], самое высокое значение - это самая высокая амплитуда, верно?

но:

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, и как бы я использовал это в живом контексте.

1 Ответ

0 голосов
/ 22 мая 2019

нашел решение сам. Вы можете сделать audioEvent.getFloatBuffer (), затем запустить этот буфер через несколько методов fft, а затем вы можете извлечь значение амплитуды из буфера. буфер довольно маленький, так что я только что получил максимальную амплитуду из этого буфера во время его работы, что даст вам считывание амплитуды много раз в секунду, и этого достаточно для меня.

...