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

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

05.04.2013, 06:54. Показов 20990. Ответов 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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.04.2013, 06:54
Ответы с готовыми решениями:

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

Вычисление частоты основного тона
Здравствуйте! Для моей диссертации мне необходимо вычислить частоту основного тона голоса и провести исследование на испытуемых. Для...

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

21
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 09:38
Цитата Сообщение от 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  [ТС]
Убрал двойку, стало правильно находить частоту, но иногда вместо 200гц выскакивает значение на 100ГЦ, хаотичным образом.
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 10:23
Цитата Сообщение от Ebis Посмотреть сообщение
выскакивает значение на 100ГЦ, хаотичным образом.
покажите вызов функции и генерацию сигнала. Видимо проблема где то там
1
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 11:23  [ТС]
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Гц)
Вложения
Тип файла: zip Freq.zip (81.4 Кб, 42 просмотров)
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
05.04.2013, 11:35  [ТС]
забыл сказать, формат сигнала 8000Гц-частота дискр., 16бит
вот прикрепил, заново созданный сигнал и его ЧОТ.
111.pcm - сигнал
Вложения
Тип файла: zip 111.zip (47.0 Кб, 42 просмотров)
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 12:07
Цитата Сообщение от 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
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 12:09
кажется не тот файл прикрепил. В общем ton200.pcm - просто синус 200 гц 8 кгц fs 16 бит
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
05.04.2013, 14:17
я кажется понял почему у вас перескакивала частота. Оказалось все просто: акф периодической функции тоже периодическая, с тем же периодом. Соответственно ваша задача - найти положения первого максимума акф относительно центрального пика. Он и будет определять частоту сигнала. Но! Вы анализируете временной интервал длительностью 2 периода. По идее акф должна медленно убывать, но в вашем случае уровень пиков акф настолько близок, что происходит перескок между ними и соответственно частота делится на 2(т.к. второй пик относительно первого на таком же расстоянии). Вот как выглядят отсчеты вашей акф:

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

В прикрепленном архиве сигнал allton.pcm и его ЧОТ
Вложения
Тип файла: zip allTon.zip (281.1 Кб, 22 просмотров)
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
06.04.2013, 15:48
да, метод далеко не идеален. Я немного переписал функцию, может будет лучше работать, хотя и она не без греха. Сначала рассчитываю акф целиком. В этом случае она получается гарантированно убывающей от середины в обе стороны. Затем нахожу положение второго максимума и по нему определяю частоту:
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  [ТС]
Вообще определитель ЧОТ я пишу для детектора речи в диапазоне от 80 до 300ГЦ. При старой функции он работал вполне сносно, но когда я начал проверять функцию определения ЧОТ гармоническими сигнала из указанного диапазона частот, то увидел что он криво работает, а мне надо чтобы он четко определял ЧОТ, чтобы с помощью него анализировать реакцию на помехи.

Щас попробую использовать вашу функцию, и отпишусь о результате.
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
06.04.2013, 15:59
хм, от 80 до 300 придется подбирать значения длины окна и соответственно ему переменной beginSampleToFindMax. Но это завтра, а сегодня мне пора...
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
06.04.2013, 16:07  [ТС]
Ну как прочитал в описании метода, длина окна должна включать в себя минимум 2 периода ОТ, тобишь около 26мс при fd=8000(13 мс = мин. частота 77Гц)
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 09:57  [ТС]
Возник такой вопрос, если настроить данный модуль ЧОТ, так чтобы он правильно определял частоты гармонических функций, он будет также правильно определять ЧОТ голоса?
Вопрос возник потому, что у меня пока не получается удовлетворить обоим случаям, вот и спрашиваю возможно ли?
0
 Аватар для raxper
10236 / 6614 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
09.04.2013, 10:19
...при работе с речью используют понятие формант, нет там одного основного тона.
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 11:24  [ТС]
в данном случае мне нужно выделить ЧОТ речи с помощью автокорреляции
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
09.04.2013, 14:18
Цитата Сообщение от Ebis Посмотреть сообщение
если настроить данный модуль ЧОТ, так чтобы он правильно определял частоты гармонических функций, он будет также правильно определять ЧОТ голоса?
далеко не факт. Не понимаю, почему вы вообще взялись проверять на синусоиде, а не сразу на фрагменте речевого сигнала
0
0 / 0 / 0
Регистрация: 03.03.2010
Сообщений: 94
09.04.2013, 14:55  [ТС]
Цитата Сообщение от vital792 Посмотреть сообщение
далеко не факт. Не понимаю, почему вы вообще взялись проверять на синусоиде, а не сразу на фрагменте речевого сигнала
Просто я хотел поглядеть как будет вести себя ЧОТ в зависимости от разного рода сигналов(с речью более меня работает), сперва решил проверить на синусойде, а в идеале хотел проверить реакцию на импульсную помеху
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.04.2013, 14:55
Помогаю со студенческими работами здесь

Алгоритм нахождения частоты основного тона речевого сигнала в Matlab
Помогите пожалуйста разобраться, нашел и доработал код для вычисления частоты основного тона, центроида сигнала и энергии в Матлабе....

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru