Форум программистов, компьютерный форум, киберфорум
Цифровая обработка сигналов
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.53/86: Рейтинг темы: голосов - 86, средняя оценка - 4.53
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
1

Автокорреляционная функция и частота основного тона (ЧОТ)

05.04.2013, 06:54. Просмотров 16001. Ответов 21
Метки нет (Все метки)

Добрый день!

Пытаюсь написать выделитель ЧОТ с приминением АКФ, но когда подаю гармонический сигнал (200Гц), то значение ЧОТ колеблется(хотя должно быть статично 200Гц) и определяется не правильно.

Ниже приведена функция для выделения ЧОТ
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
double TON (short in[208]) //размер массива равен двум максимальным периодам ОТ
{
    int fd = 8000; //Частота дискретизации
    int minOT   = fd * 0.0030f; // минимальный шаг - 3 мс (330 Гц)
    int maxOT   = fd * 0.013f;  // максимальный шаг - 13 мс (77 Гц)
    int deltaOT = fd * 0.0001f; // шаг - 0,1 мс
    if (deltaOT==0) deltaOT=1;
    
        int OT=0;//ЧОТ
    int maxAC=-10000L;
 
    for (int pitch=minOT;pitch<=maxOT;pitch+=deltaOT)
    {
        double max=-10000L,val=0;
        
                for(int j=0;j<=2*maxOT;j++)
        {
            double p=in[j];
            double q=in[j+pitch];
 
            val=p*q;       //Считаем значение автокорреляции
            if(val>max) max=val; //находим максимум при данном значении ОТ
        }
 
        if (max>maxAC)//находим максимум АКФ
        {
            maxAC=max;
            OT=pitch;
        }
    }
    return (double)fd/(OT); //возвращаем ЧОТ
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.04.2013, 06:54
Ответы с готовыми решениями:

Выделение основного тона
Здравствуйте. Я разрабатываю аплет нахождения основного тона, по ходу дела появились вопросы,...

Зависимость частоты основного тона струны от её параметров
Найдите зависимость частоты колебаний основного тона струны от её длины L,Плотности p,площади...

Кепстральный метод оценки периода основного тона речевого сигнала
Всем доброго времени суток) Задача в общем такая: разбить входной сигнал на сегменты по 160...

Автокорреляционная функция
Здравствуйте! Есть массив (String) в виде &quot;1&quot; и &quot;0&quot;. Т.е. последовательность бит типа:...

21
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 09:38 2
Цитата Сообщение от Ebis Посмотреть сообщение
определяется не правильно.
странно что вообще работает.
Цитата Сообщение от Ebis Посмотреть сообщение
double q=in[j+pitch];
в этой строке явно выход за границу массива. А по поводу самого метода - надо искать не первый максимум, а второй. Первый должен быть на нуле...

Добавлено через 4 минуты
Цитата Сообщение от vital792 Посмотреть сообщение
надо искать не первый максимум
а, ну да, правильно, первый отсекается. Тогда попробуйте просто во втором цикле
Цитата Сообщение от Ebis Посмотреть сообщение
for(int j=0;j<=2*maxOT;j++)
убрать двойку...
1
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 09:58  [ТС] 3
Убрал двойку, стало правильно находить частоту, но иногда вместо 200гц выскакивает значение на 100ГЦ, хаотичным образом.
0
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 10:23 4
Цитата Сообщение от Ebis Посмотреть сообщение
выскакивает значение на 100ГЦ, хаотичным образом.
покажите вызов функции и генерацию сигнала. Видимо проблема где то там
1
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 11:23  [ТС] 5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int main(int argc, char* argv[])
{
    FILE *f,*fton;
    int size;
    short *buf;
 
 
 
 
    if (!argv[1])   {   cout<<"Enter the name of file!"<<endl;      system("pause");        return -1;  }
 
    f=fopen(argv[argc-1],"rb"); //исходный файл с голосом
    if (f==NULL){   cout<<"Open error!"<<endl;      system("pause");        return -1;  }
 
    fseek(f,0,2);
    size=ftell(f)/sizeof(short);//Кол-во отсчетов
 
    fseek(f,0,0);
    buf=(short*)malloc(size*sizeof(short));
    fread(buf,sizeof(short),size,f); //считываем отсчеты
    int bs=(int)(2*fd * 0.013f);
    short in[208];//bs
    int t;
    fton=fopen("Freq.pcm","w");
 
    for(int i=0;i<size/bs;i++)
    {
        for(int j=0;j<=bs;j++)
        {in[j]=buf[i*bs+j];}
 
        t=(int)TON(in);
        fprintf(fton,"%d \n ",t);
    }
    
 
    fclose(f);
    fclose(fton);
    return 0;
}
freq.pcm - значение ЧОТ
ton.pcm - сигнал (200Гц)
0
Вложения
Тип файла: zip Freq.zip (81.4 Кб, 39 просмотров)
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 11:35  [ТС] 6
забыл сказать, формат сигнала 8000Гц-частота дискр., 16бит
вот прикрепил, заново созданный сигнал и его ЧОТ.
111.pcm - сигнал
0
Вложения
Тип файла: zip 111.zip (47.0 Кб, 39 просмотров)
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 12:07 7
Цитата Сообщение от Ebis Посмотреть сообщение
забыл сказать, формат сигнала 8000Гц-частота дискр., 16бит
да, я догадался по коду) Сигнал посмотрел в звуковом редакторе - ниче не понял, сгенерил новый. Просто тон 200 гц. Придираться к стилю написания кода не буду) ошибки были все также из-за выхода за границы
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <iostream>
 
using namespace std;
 
int fd = 8000; //Частота дискретизации
 
double TON (const short *in) //размер массива равен двум максимальным периодам ОТ
{
    int minOT   = fd * 0.0030f; // минимальный шаг - 3 мс (330 Гц)
    int maxOT   = fd * 0.013f;  // максимальный шаг - 13 мс (77 Гц)
    int deltaOT = fd * 0.0001f; // шаг - 0,1 мс
    if (deltaOT==0) deltaOT=1;
 
        int OT=0;//ЧОТ
    int maxAC=-10000L;
 
    for (int pitch=minOT;pitch<=maxOT;pitch+=deltaOT)
    {
        double max=-10000L,val=0;
 
                for(int j=0;j<maxOT;j++)
        {
            double p=in[j];
            double q=in[j+pitch];
 
            val=p*q;       //Считаем значение автокорреляции
            if(val>max) max=val; //находим максимум при данном значении ОТ
        }
 
        if (max>maxAC)//находим максимум АКФ
        {
            maxAC=max;
            OT=pitch;
        }
    }
    return (double)fd/(OT); //возвращаем ЧОТ
}
 
int main(int argc, char* argv[])
{
    FILE *f,*fton;
    int size;
    short *buf;
 
//    if (!argv[1])   {   cout<<"Enter the name of file!"<<endl;      system("pause");        return -1;  }
 
    f=fopen("ton200.pcm", "rb"); //исходный файл с голосом
    if (f==NULL)
    {
        cout<<"Open error!"<<endl;
        system("pause");
        return -1;
    }
 
    fseek(f,0,2);
    size=ftell(f)/sizeof(short);//Кол-во отсчетов
 
    fseek(f,0,0);
    buf=(short*)malloc(size*sizeof(short));
    fread(buf,sizeof(short),size,f); //считываем отсчеты
    int bs=(int)(2*fd * 0.013f);
    short in[208];//bs
    int t;
    fton=fopen("Freq.pcm","w");
 
    for(int i=0;i<size/bs;i++)
    {
        for(int j=0;j<bs;j++)
        {in[j]=buf[i*bs+j];}
 
        t=(int)TON(in);
        fprintf(fton,"%d \n ",t);
    }
 
 
    fclose(f);
    fclose(fton);
    return 0;
}
ton.zip
1
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 12:09 8
кажется не тот файл прикрепил. В общем ton200.pcm - просто синус 200 гц 8 кгц fs 16 бит
0
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 14:17 9
я кажется понял почему у вас перескакивала частота. Оказалось все просто: акф периодической функции тоже периодическая, с тем же периодом. Соответственно ваша задача - найти положения первого максимума акф относительно центрального пика. Он и будет определять частоту сигнала. Но! Вы анализируете временной интервал длительностью 2 периода. По идее акф должна медленно убывать, но в вашем случае уровень пиков акф настолько близок, что происходит перескок между ними и соответственно частота делится на 2(т.к. второй пик относительно первого на таком же расстоянии). Вот как выглядят отсчеты вашей акф:
Автокорреляционная функция и частота основного тона (ЧОТ)

Чтобы этого избежать, возможно следует сократить временное окно по длительности... Попробуйте уменьшить первый цикл отсчетов на 20-30
1
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 18:16  [ТС] 10
Вобщем протестировал эту программку на сигналах до 150ГЦ включительно, она все определяет правильно, если частота сигнала больше, то появляются выбросы, и они не всегда кратны 2.
Уменшил цикл и ЧОТ стал определяться не правильно
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
06.04.2013, 12:41  [ТС] 11
Сгенерировал в один файл несколько тонов различно частоты начиная от 10ГЦ и до 370Гц, и результат получился не очень
Ошибки определения нижних (до 77Гц) и высоких (после 330 Гц) понятны, так как они не входят в диапазон искомой ЧОТ, а вот почему некоторые частоты правильно определяет, а некоторые нет, не могу понять

В прикрепленном архиве сигнал allton.pcm и его ЧОТ
0
Вложения
Тип файла: zip allTon.zip (281.1 Кб, 19 просмотров)
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
06.04.2013, 15:48 12
да, метод далеко не идеален. Я немного переписал функцию, может будет лучше работать, хотя и она не без греха. Сначала рассчитываю акф целиком. В этом случае она получается гарантированно убывающей от середины в обе стороны. Затем нахожу положение второго максимума и по нему определяю частоту:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
double ton(const short in[], int frameLength)
{
    int pitch, j, OT = 0, max = 0;
    int beginSampleToFindMax = 20;//frameLength/2;
 
    int *corrFunc = (int*)calloc(frameLength*2, sizeof(int));
 
    for(pitch=0; pitch<frameLength; pitch++)
    {
        for(j=0; j<frameLength; j++)
        {
            corrFunc[pitch+j] += (int)in[pitch]*in[frameLength-j];
        }
    }
 
    for(j=frameLength+beginSampleToFindMax; j<frameLength*2; j++)
    {
        if(corrFunc[j] > max)
        {
            max = corrFunc[j];
            OT = j;
        }
    }
    free(corrFunc);
 
    return (double)fd / (OT-frameLength);
}
Для низких частот само собой работать не будет - в окно анализа должен попасть минимум период, а лучше два, иначе второго пика вообще не будет. Для высоких частот в акф получается много пиков и трудно выбрать именно второй. Я ввел переменную beginSampleToFindMax, с помощью которой отсекаю первый пик - ее значение тоже зависит от частоты, при малой частоте значения 20 будет не достаточно, при большой она отсечет и второй пик. По хорошему, конечно этот код либо должен работать на известном узком диапазоне частот, либо его можно унифицировать следующим образом: сначала сглаживаете сигнал нч фильтром(опять же надо знать верхний предел, чтобы не отфильтровать основной тон). Далее получаете его акф, в ней ищите перегибы соответствующие максимумам, сортируете их по убыванию и ищите разницу между первыми двумя(или еще лучше усредненную разницу между всеми)
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
06.04.2013, 15:55  [ТС] 13
Вообще определитель ЧОТ я пишу для детектора речи в диапазоне от 80 до 300ГЦ. При старой функции он работал вполне сносно, но когда я начал проверять функцию определения ЧОТ гармоническими сигнала из указанного диапазона частот, то увидел что он криво работает, а мне надо чтобы он четко определял ЧОТ, чтобы с помощью него анализировать реакцию на помехи.

Щас попробую использовать вашу функцию, и отпишусь о результате.
0
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
06.04.2013, 15:59 14
хм, от 80 до 300 придется подбирать значения длины окна и соответственно ему переменной beginSampleToFindMax. Но это завтра, а сегодня мне пора...
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
06.04.2013, 16:07  [ТС] 15
Ну как прочитал в описании метода, длина окна должна включать в себя минимум 2 периода ОТ, тобишь около 26мс при fd=8000(13 мс = мин. частота 77Гц)
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 09:57  [ТС] 16
Возник такой вопрос, если настроить данный модуль ЧОТ, так чтобы он правильно определял частоты гармонических функций, он будет также правильно определять ЧОТ голоса?
Вопрос возник потому, что у меня пока не получается удовлетворить обоим случаям, вот и спрашиваю возможно ли?
0
10205 / 6587 / 493
Регистрация: 28.12.2010
Сообщений: 21,165
Записей в блоге: 1
09.04.2013, 10:19 17
...при работе с речью используют понятие формант, нет там одного основного тона.
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 11:24  [ТС] 18
в данном случае мне нужно выделить ЧОТ речи с помощью автокорреляции
0
2008 / 1280 / 60
Регистрация: 05.06.2010
Сообщений: 2,213
09.04.2013, 14:18 19
Цитата Сообщение от Ebis Посмотреть сообщение
если настроить данный модуль ЧОТ, так чтобы он правильно определял частоты гармонических функций, он будет также правильно определять ЧОТ голоса?
далеко не факт. Не понимаю, почему вы вообще взялись проверять на синусоиде, а не сразу на фрагменте речевого сигнала
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 14:55  [ТС] 20
Цитата Сообщение от vital792 Посмотреть сообщение
далеко не факт. Не понимаю, почему вы вообще взялись проверять на синусоиде, а не сразу на фрагменте речевого сигнала
Просто я хотел поглядеть как будет вести себя ЧОТ в зависимости от разного рода сигналов(с речью более меня работает), сперва решил проверить на синусойде, а в идеале хотел проверить реакцию на импульсную помеху
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.04.2013, 14:55

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Автокорреляционная функция
Помогите создать программу на Паскале по этой теме: Сгенерировать случайную последовательность...

Автокорреляционная функция
Добрый день! Есть сигнал first_step=0; step_t=0.01; last_step=1; N_=101;...

Автокорреляционная функция С/А-кода
Добрый день) Сформировала с/а-код и написала алгоритм который строит автокор. функцию, ставя в...

Автокорреляционная функция синусоидального сигнала
Подскажите пожалуйста почему не правильно строится автокорреляционная функция синусоидального...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.