0

我一直在实现复音信号音高检测器,所以我开始编写我的程序(记录数据、转换数据、零填充、窗口化、FFT、峰值检测)。起初,我用我已经知道应该获得哪些值的声音对其进行了测试,并且效果很好。

我遇到的问题是使用 Audiorecord 类用我的手机录音时。

例如:我用手机播放和录制了两三个纯音,而我在 Audiorecord 类中得到的值不正确。从我的手机中获取错误的数据并不能让我进行良好的分析。

这是我记录数据(短)并将数据短转换为双倍的代码(这一步是我认为问题所在)

这是我的代码:

void recordAudio() {

mShouldContinue= true;

    new Thread(new Runnable() {
        @Override
        public void run() {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);


            // buffer size in short
            bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); //Consigue el minimo tamaño de buffer para poder analizar

            if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) {
                bufferSize = sampleRate * 2; // si el buffersize obtenido por nuestro getMinBufferSize es apto  usaremos el encontrado si no utilizaremos el doble de nuestra frecuencia de sampleo
            }


            short[] audioBuffer = new short[bufferSize];

            if (audioBuffer.length % 2 == 0){ // Aseguramos que nuestro buffer input tenga una tamaño impar para una mejor R.F.
                audioBuffer = new short[bufferSize +1];
            }


            AudioRecord record = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); //Instancia de la clase AudioRecord

            if (record.getState() != AudioRecord.STATE_INITIALIZED) { // Si audiorecord no ha sido inicializado displeamos un mensaje advirtiendo.
                Log.e(LOG_TAG, "Audio Record can't initialize!");
                return;
            }
            record.startRecording(); //Empezamos a grabar con nuestros parámetros ya definidos.

            Log.v(LOG_TAG, "Start recording");  //mensaje informativo

            long shortsRead = 0;

            while (mShouldContinue) {

                int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length); //audiobuffer.length
                shortsRead += numberOfShort;





                DFT(audioBuffer);



                try { // Dormimos el programa durante un segundo
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }

            }

                record.stop();
                record.release();

                Log.v(LOG_TAG, String.format("Recording stopped. Samples read: %d", shortsRead));




        }
    }).start();
}

Inputsignal 是 audiobuffer 和 N 是长度的转换(内部 DFT 函数):

for(int i = 0; i < N; i++){
    doubley[i] = (double)(InputSignal[i])/32768.0;

}
4

1 回答 1

1

FFT 幅度峰值检测器不是可靠的音高(频率/音符)估计器。它通常会为某些音色找到谐波频率。

相反,查找一些音高检测/估计方法(加权自相关、AMDF、HPS、倒谱、决策、CDNN 等),并尝试其中一种,而不是(错误)使用频谱频率估计器。

于 2017-05-16T16:08:16.363 回答