Гитарный тюнер в IOS: алгоритм Гертцеля не работает для 2 из 6 струн

Я пытаюсь реализовать гитарный тюнер в IOS 8, и я получил некоторый код от того, кто уже понял это: он имеет дело с алгоритмом Гертцеля, который в короткие сроки сравнивает величины фиксированных частот - как определено для струн EADGBE. - здесь подпрограмма, которая помещается в метод обратного вызова CoreAudio:

int currentString(SInt16 *samples, int N) {

int note0 = 82;
int note1 = 110;
int note2 = 147;
int note3 = 196;
int note4 = 247;
int note5 = 330;

int offset = 0.5;


double results[6];
// filter for the six strings
results[0] = (goertzelFilter(samples, note0+offset, N) +goertzelFilter(samples, note0, N) + goertzelFilter(samples, note0-offset, N))/3.0;

results[1] = (goertzelFilter(samples, note1+offset, N) +goertzelFilter(samples, note1, N) + goertzelFilter(samples, note1-offset, N))/3.0;

results[2] = (goertzelFilter(samples, note2+offset, N) +goertzelFilter(samples, note2, N) + goertzelFilter(samples, note2-offset, N))/3.0;

results[3] = (goertzelFilter(samples, note3+offset, N) +goertzelFilter(samples, note3, N) + goertzelFilter(samples, note3-offset, N))/3.0;

results[4] = (goertzelFilter(samples, note4+offset, N) +goertzelFilter(samples, note4, N) + goertzelFilter(samples, note4-offset, N))/3.0;

results[5] = (goertzelFilter(samples, note5+offset, N) +goertzelFilter(samples, note5, NN) + goertzelFilter(samples, note5-offset, N))/3.0;


int maxInd = -1;
double maxVal = 0.0;

for (int i=0; i<6; i++) {
    if (results[i] > maxVal) {

        if (i==0)
            NSLog(@"String %d - value: %f", i+1, results[i]);

        maxVal = results[i];
        maxInd = i;
    }
}

// if all levels are quite low, return -1
if (maxVal < 1) {
    maxInd = -1;
}
return maxInd;
}

Однако такая процедура работает только для нижней строки "DGBE". Что касается E- и D-строк, я получаю ошибочные результаты, и я считаю, что такое поведение связано с обертонами, так как они кажутся более сильными, чем искомые, - возможно, низкий "E" имеет "A" или "D" как обертон, с большей амплитудой.

Мой вопрос: так столкнулся с подобной проблемой? И решил это? Является ли Гёртцель правильным алгоритмом для этого, или БПФ или свертка - лучшее решение?

Последний здесь алгоритм Гертцеля, который я использую:

double goertzelFilter(SInt16* samples, double freq, int N) {
double s_prev = 0.0;
double s_prev2 = 0.0;
double coeff,normalizedfreq,power,s;
int i;
normalizedfreq = freq / 44100;
coeff = 2*cos(2*M_PI*normalizedfreq);
for (i=0; i<N; i++) {
    s = samples[i] + coeff * s_prev - s_prev2;
    s_prev2 = s_prev;
    s_prev = s;
}
power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2;
return power;
}

1 ответ

Решение

Алгоритм Гертцеля измеряет энергию на определенной частоте, а не на музыкальном поле (что является другим психоакустическим явлением). Наиболее сильные спектральные частоты, создаваемые многими струнными инструментами и голосами, скорее всего, будут обертонами или гармониками вместо частоты основного тона, а спектральная частота - это то, что фильтр Гертцеля видит вместо основного тона.

Для низкочастотных струнных звуков попробуйте использовать алгоритм обнаружения / оценки основного тона (такой как автокорреляция, ASDF, AMDF, RAPT, YAAPT и т. Д.) Вместо использования фильтра Гоэрцеля (или простой величины DFT) для оценки наличия основного тона.

Другие вопросы по тегам