java - 如何在Android中查找单个乐器的和弦

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

最佳答案

您似乎想要实现的是复调音高检测。这是一个困难的过程,充其量只是一个近似的过程,在一般情况下很难发挥作用。

您将面临的根本问题是谐波在任何真实乐器声音上的叠加。从根本上讲,协和音之所以有效,是因为和弦的组成音符中的和声是对齐的。这些可能会导致频谱峰值的频率不是和弦中音符之一的基音。

您需要处理的其他问题是乐器的频谱峰值不是其基本的、在音符开始时的打击声音 - 其频谱看起来更像噪音。

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

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

我对这个评论有点困惑。自相关不是 FFT。一般来说,自相关被认为是现实世界音频信号频率检测的糟糕算法选择。
对于复调音高检测,您可能最好使用 FFT 方法 - 然而 - 这也不是特别简单。

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

关于java - 如何在Android中查找单个乐器的和弦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22196101/

相关文章:

python - 如何分析 Python 中的声音输出?

iphone - 是否可以转换带有一些音符的音频文件?

java - mvn assembly :single and mvn compile assembly:single 和有什么区别

java - 尝试在空对象引用 finishComposingText() 上调用接口(interface)方法

java - 遍历对象树的有效方法?

android - 即时信号强度

java - 添加两个大的二进制数

android - 从 Android 中的 Intent 中检索调用 Activity

android - 是否有针对 Android 设备的设备特定错误的汇编?

audio - 重新调整对数dB值刻度