我正在尝试查找演奏的单个乐器的和弦

private AnalyzedSound getFrequency() {

    //audioData has the audio array of recored.
    elementsRead =
        audioData.getElements(audioDataAnalyzis,0,audioDataSize);

    double loudness = 0.0;
    for(int i=0; i<elementsRead; ++i)
        loudness+=Math.abs(audioDataAnalyzis[i]);

    //loudness of the data is divided by the elementsRead
    loudness/=elementsRead;
    // Check loudness first - it's root of all evil. loudnessThreshold = 30.0
    if(loudness<loudnessThreshold)
        return new AnalyzedSound(loudness,ReadingType.TOO_QUIET);

    //FFT computation analyzed data is in audioDataAnalyzis
    computeAutocorrelation();

    //chopOffEdges(0.2);

    double maximum=0;
    for(int i=1; i<elementsRead; ++i)
        maximum = Math.max(audioDataAnalyzis[i], maximum);

    int lastStart = -1;
    wavelengths = 0;
    boolean passedZero = true;
    for(int i=0; i<elementsRead; ++i) {
        if(audioDataAnalyzis[i]*audioDataAnalyzis[i+1] <=0) passedZero = true;
        if(passedZero && audioDataAnalyzis[i] > MPM*maximum &&
                audioDataAnalyzis[i] > audioDataAnalyzis[i+1]) {
            if(lastStart != -1)
                wavelength[wavelengths++]=i-lastStart;
            lastStart=i; passedZero = false;
            maximum = audioDataAnalyzis[i];
        }
    }
    if(wavelengths <2)
        return new AnalyzedSound(loudness,ReadingType.ZERO_SAMPLES);

    removeFalseSamples();

    double mean = getMeanWavelength(), stdv=getStDevOnWavelength();

    double calculatedFrequency = (double)AUDIO_SAMPLING_RATE/mean;

    //Log.d(TAG, "MEAN: " + mean + " STDV: " + stdv);
    //Log.d(TAG, "Frequency:" + calculatedFrequency);

    if(stdv >= maxStDevOfMeanFrequency)
        return new AnalyzedSound(loudness,ReadingType.BIG_VARIANCE);
    else if(calculatedFrequency>MaxPossibleFrequency)
        return new AnalyzedSound(loudness,ReadingType.BIG_FREQUENCY);
    else
        return new AnalyzedSound(loudness, calculatedFrequency);

}

但是我找不到平均值。这段代码可以实时记录,但我想分析一个保存的wav文件。我无法正确获取平均值。如何分割音频数据并作为输入

最佳答案

您似乎想要实现的是复音音高检测。这是一个艰难的过程,充其量只是一个近似的过程,在一般情况下很难进行工作。

您将面临的根本问题是谐波在任何真实乐器声音上的叠加。从根本上说,和声起作用是因为和弦对齐的成分音中的谐波。这些可能会导致频谱峰值出现在不是和弦中音符之一的基础的频率上。

您需要处理的其他问题是乐器的频谱峰值不是其开头提到的基本敲击声音-频谱看起来更像噪声。

可能需要一种统计方法来取消拾音的叠加,这可能需要先验了解所讨论乐器的光谱特性。

/FFT computation analyzed data is in audioDataAnalyzis
computeAutocorrelation();

我对此评论感到有些困惑。自相关不是FFT。通常,自相关被认为是对现实世界音频信号进行频率检测的算法的较差选择。
对于复音音高检测,最好使用FFT方法-但是,这也不是特别简单。

最后,通常在音频特征提取的背景下,对此问题空间进行了大量研究。我建议您看看Sonic Visualiser-存在其开源音调分析插件。

10-08 02:02