如何在Android中找到单个乐器的和弦

时间:2014-03-05 11:13:43

标签: java android audio

我试图找到单个乐器的和弦,我怎么能找到它

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文件。我无法正确获得平均值。如何拆分音频数据并作为输入

1 个答案:

答案 0 :(得分:2)

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

您将面临的基本问题是在任何真实的乐器声音上叠加谐波。在基本层面上,协和是有效的,因为来自和弦的组成音符的谐波对齐。这些可能导致频率峰值的频率不是和弦中的一个音符的基础。

您需要处理的其他问题是仪器的光谱峰值不是它们在开始时的基本,打击声 - 其光谱看起来更像是噪声。

可能需要采用统计方法来取消音符的叠加,可能需要对相关乐器的光谱特性有一些先验知识。

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

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

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