Re[9]: Частотная характеристика звука.
От: Шахтер Интернет  
Дата: 27.12.05 18:03
Оценка: 36 (1) +1
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, Шахтер, Вы писали:


Ш>>Держи код


A>Ни хрена не понял, но спасибо


Давай поясню математику.

Что делает генератор DTMF сигнала. Он выдаёт сумму двух синусоид одинаковой мощности.
После прохождения тракта ты получишь снова сумму двух синусоид.
Но вообще говоря, их частоты будут чуть-чуть сдвинуты, мощности не будут строго одинаковы и добавится шумок.

Пусть у нас частота синусоид F1 и F2, амплитуды A1 A2, частота дискретизации Fd.

Тогда сигнал на входе A1*sin(2*Pi*(F1/Fd)*k+phi1) + A2*sin(2*Pi*(F2/Fd)*k+phi2) + шум , где phi1 и phi2 неизвестные фазы сигналов.

Заметим что, A1*sin(2*Pi*(F1/Fd)*k+phi1) = A1*cos(phi1)*sin(2*Pi*(F1/Fd)*k) + A1*sin(phi1)*cos(2*Pi*(F1/Fd)*k).

Иными словами, данная составляющая сигнала есть линейнаю комбинация двух сигналов sin(2*Pi*(F1/Fd)*k) и cos(2*Pi*(F1/Fd)*k).

Эти два сигнала почти ортогональны (в общем случае, если число отсчетов достаточно велико, грубо говоря, содержит сотню периодов данной частоты, то неортогональностью можно пренебречь, что мы и будем делать).

Аналогично, у нас еcть вторая пара sin(2*Pi*(F2/Fd)*k) и cos(2*Pi*(F2/Fd)*k), которая к тому же почти ортогональна первой.

Т.е. фактически, нам нужно просто спроектировать полученный сигнал на две ортогональные плоскости плоскости и вычислить энергию проекций.
Что собственно мы и делаем. Дальше проверяем, что мощность на одной из пар стандартных частот превосходит порог.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Частотная характеристика звука.
От: Шахтер Интернет  
Дата: 26.12.05 17:07
Оценка: 36 (1)
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, Шахтер, Вы писали:


Ш>>Это не делают БПФ ом. Пороюсь в своих архивах, напишу позже.


A>Да? А у меня почти вышло


Держи код (не тестировал).
Если коротко -- то мы считаем энергию синусоидальной составляющей данной частоты (по 8 частотам). При поступлении нового отсчета надо сделать небольшой пересчет. Алгоритм получается очень экономным.


namespace DTMFDetect {

struct DTMFCode
 {
  int low; // 1-4 , 0 
  int hi;  // 1-4 , 0 
  
  public DTMFCode(bool fake/*false*/) { low=hi=0; }
  
  public DTMFCode(int low_,int hi_) { low=low_; hi=hi_; }
 }

class DTMFDetector
 {
   const int FreqCount=8;
   const int BufSize=512;        // Число отчетов фрейма сигнала, должно быть достаточным, чтобы вмещать
                                 // 10 или более периодов синуса искомых частот.
                                 // Увеличение этого числа приводит к увеличению селективности детектора.   
   
   const double Fd=22000;        // Частота дискретизации.
   const double Scale=(1<<15)-2;
   
   const double ELim=BufSize;                          // отсечение по энергии  
   const double ProdLim=((Scale*Scale*BufSize)/4)*0.9; // чувствительность по частоте
 
   Int16[] buf;
   int index;
   bool full;
   
   Int16[,] sinTable;
   Int16[,] cosTable;
   
   Int64 E;
   Int64[] sinProd;
   Int64[] cosProd;
   
   static double Norm(double x,double y) { return x*x+y*y; }
   
   DTMFCode check()
    {
     if( E>ELim )
       {
        for(int i=0; i<4 ;i++)
          {
           if( Norm(sinProd[i],cosProd[i])>E*ProdLim )
             {
              for(int j=4; j<8 ;j++)
                {
                 if( Norm(sinProd[j],cosProd[j])>E*ProdLim )
                   {
                    return new DTMFCode(i+1,j-4+1);
                   }
                }
             }
          }
       }
       
     return new DTMFCode(false);  
    }
   
  public DTMFDetector()
   {
    buf=new Int16[BufSize];
    sinTable=new Int16[FreqCount,BufSize];
    cosTable=new Int16[FreqCount,BufSize];
    
    index=0;
    full=false;
    
    E=0;
    
    sinProd=new Int64[FreqCount];
    cosProd=new Int64[FreqCount];
    
    int i=0;
    
    foreach(double F in new double[]{ 697,770,852,941, 1209,1336,1477,1633 })
      {
       double omega=2*Math.PI*(F/Fd);

       for(int j=0; j<BufSize ;j++)
         {
          sinTable[i,j]=(Int16)( Scale*Math.Sin(omega*j) );
          cosTable[i,j]=(Int16)( Scale*Math.Cos(omega*j) );
         }
      
       i++;
      }
   }
   
  public DTMFCode next(Int16 x)  
   {
    Int16 y=buf[index];

    // 
    // Фрейм сигнала хранится в циклическом буфере
    // При поступлении отсчета пересчитываем энергию фрейма и скалярные произведения с синусами и косинусами
    //

    E+=((Int64)x*x-(Int64)y*y);

    for(int i=0; i<FreqCount ;i++)
      {
       sinProd[i]+=((Int64)x-y)*sinTable[i,index];
       cosProd[i]+=((Int64)x-y)*cosTable[i,index];
      }

    buf[index]=x;
    
    if( ++index>=BufSize )
      {
       index=0;
       full=true;
      }
      
    return full?check():new DTMFCode(false);  
   }
 }

} // namespace DTMFDetect
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[11]: Частотная характеристика звука.
От: jhng Россия  
Дата: 26.12.05 21:14
Оценка: 36 (1)
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, jhng, Вы писали:


J>>Берешь один период синусоиды, вычисляешь ее АКФ


A>Что такое АКФ? Люди я в этом вопросе лопух, не надо кидаться непонятными словами


Во первых sorry за неправильную информацию в предыдущем посте. Оптимальным для выбранного сигнала будет являться такой фильтр, коэффициенты которого будут являться зеркальным отражением отсчетов исходного сигнала за период. Так что для грамонического сигнала sin(omega * t + phi) коэффициенты фильтра можно расчитать как 1 — sin(omega * t + phi). Соответственно сигнал на выходе будет совпадать с АКФ входного сигнала. В приведенный выше коде и реализован этот подход. Но все таки мне использование резонаторов кажеться лучше, поскольку они проще в реализации и могут дать лучшее разрешение по чатоте (а частоты в DTMF расположены очень близко). Однако это только в том случае, если отношение сигнал/шум на частоте резонанса достаточно велико (скорее всего это условие выполняется).

Собственно про АКФ. АКФ — автокорреляционная функция. Она показывает степень сходства сигнала со своей сдвинутой копией. Расчитывается по формуле R(t) = int(s(t) * s(t — tau) dtau). Пределы интегрирования [-inf; +inf]. В дискретной области АКФ расчитывается аналогично, только интеграл заменяется на сумму.

P.S. Поковырял в matlab методы спектрального оценивания. Без шума частоты оценивает просто супер.
А вот если шум добавить, тогда... Короче если даже небольшой шум в канале связи (-20 dB) — не прокатит, слишком близко частоты.

P.P.S. Если с математикой не очень — скажи все частоты DTMF и частоту дискретизации. Может сам фильтры посчитаю, если время будет
Re[5]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:09
Оценка: 36 (1)
Здравствуйте, adontz, Вы писали:

V>>Что-то мне кажется, что сама задача как-то неверно поставлена. Что требуется-то?


A>Распознавать DTMF


Это делается коррелляцией, даже точность синусоид никакая не нужна, распознает железно на корреляции с прямоугольными импульсами. У меня DTMF распознавали старенькие 8039 и одновременно делали кучу других вещей.

В общем, на каждую частоту из DTMF заводится 2 фильтра НЧ первого порядка (т.е. на каждом шаге что-то типа s=s-(s/4) ) и 2 ячейки-сумматора.

Делаем непрерывную корреляцию с прямоугольными импульсами, сдвинутыми на 90 градусов для каждой частоты. Т.е. просто прибавляем к сумме (если "1") или отнимаем ("0"). Подсчет накопительных сумм корреляций обычно производится для каждой частоты индивидуально, кратно целому числу периодов (1 период — нормально, но не обязательно). Затем эти суммы фильтруются упомянутыми фильтрами.

Искомая текущая мощность сигнала на каждой из исследуемых частот — это корень квадратный по теореме пифагора: sqrt(abs(ФНЧ1)^2+abs(ФНЧ2)^2). Считать корень квадратный вовсе не обязательно. Достаточно работать непосредственно с квадратами мощностей. Задача сводится к подбору порога отношения мощностей исследуемых частот к общей мощности входного сигнала. Вернее, к подбору квадрата этого отношения. (Разумеется, можно так же ограничить абсолютным порогом "чуствительности" снизу всю систему)

Как генерировать прямоугольные импульсы, сдвинутые на 90 градусов.

предположим у тебя 8кГц тактовая, а тебе нужна частота 1200Гц. Берем накопитель 2 байта, например, т.е. 65536. Считаем: 1200*65536/8000 = 9830,4 (грубо — 9830, для нашей задачи точности хватает, если у тебя 4-байтное слово, то точность получается просто астрономической).

Т.е. прибавляешь 9830 к накопителю каждый раз, старший бит — это искомая частота 1200. Чтобы получить сдвиг на 90 градусов — это XOR со следующим битом.
Re[12]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:19
Оценка: 36 (1)
Здравствуйте, jhng, Вы писали:

J>P.S. Поковырял в matlab методы спектрального оценивания. Без шума частоты оценивает просто супер.

J>А вот если шум добавить, тогда... Короче если даже небольшой шум в канале связи (-20 dB) — не прокатит, слишком близко частоты.

Потому что АКФ тут не к месту. Нужна обычная банальная корреляция с требуемыми частотами, она отлично работает даже при уровне шума превышающем уровень сигнала. Корреляция с некоей частотой считается как произведение отсчетов сигнала на сдвинутые на 90 градусов отсчеты синусоид исследуемой частоты.

Т.е. у нас есть отсчеты f и f' — это сдвинутые на 90 градусов отсчеты исследуемой частотной составляющей.
p — отсчеты входного сигнала.

на каждом шаге:
s += p * f;
s' += p * f';

s и s' небходимо фильтровать НЧ c нужным срезом (смотря какая нужна скорость реакции).

Текущая мощность — sqrt(s*s + s'*s'); ВСЕ!!!
Re: Частотная характеристика звука.
От: raskin Россия  
Дата: 25.12.05 07:32
Оценка: 33 (1)
adontz wrote:
> Надо получить частотну характеристику звука. Как я делаю ниже.
> Проблема в том, что в качестве пиков выдаются какие-то ну очень
> приблизительные значения (разброс 100-200 герц), хотя, скажем,
> soundforge по тому же сигналу определяет пики очень чётко.
> Формат записи 8бит, 22500Гц, моно.
Стандартные грабли — вроде, окно не используется. Дело в том, что БПФ от
отрезка звука — это БПФ его свёртки с прямоугольником,а при этом спектр
умножается на (sin x)/x . Поэтому для заглаживания краёв перед БПФ
сигнал умножают на окно — функцию, плавно спадающую до нуля в концах
отрезка (желательно — значение и производная по нулям, кажется) и
имеющую быстро спадающий спектр.
В справке MatLab,
http://www.mathworks.com/access/helpdesk/help/toolbox/signal/reftabl2.html#136851
приведены формулы для многих оконных функций.
В учебнике http://www.bores.com/courses/advanced/windows/ объяснено про
окна чуть подробнее.
Posted via RSDN NNTP Server 2.0
Re[15]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 02:55
Оценка: 33 (1)
Здравствуйте, adontz, Вы писали:

A>Есть бесконечный массив семплов (ну грубо говоря, сильно старые меня конечно не волнуют).

A>Есть частота дискретизацц D, частота которую надо распознать F, минимальная распознаваемая длительность сигнала T.
A>Для каждого sample[i], частоты D я вычисляю

A>sum1[F, i] += sample[i] * sin(2*pi*i/D);

A>sum2[F, i] += sample[i] * sin(2*pi*i/D + pi/2);
A>energy[F, i] = sqrt(sum1[F, i]*sum1[F, i]) + sqrt(sum2[F, i]*sum2[F, i])

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

A>Если есть такой промежуток [k — D*T, k], что на нём energy[F, i] всегда больше некоторого порогового значения, то считать, что сигнал распознан.


Нет, из-за шума и из-за второй частоты не все твои отсчеты будут больше некоторого порогового значения. Это все надо сглаживать. Если подобрать частоту среза ФНЧ 1/20мс, то достаточно обнаружить сам факт достижения порогового значения.

Затем надо не забыть обнаружить паузу

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


A>Насколько я понимаю, мне понадобиться считать и общую энергию сигнала.


Обязательно, порог — величина относительная. Громкость в канале не постоянная. Я тут давал уже как считать общую енергию. Ее тоже надо сглаживать точно таким же фильтром.

Короче, навскидку так:
    // фильтр НЧ
    public struct FNC {
        public double k;        // коэф
        public double outp;     // выход фильтра

        public void Step(double inp) {
            outp -= (outp - inp) * k;
        }

        public FNC(double k) {
            this.k = k;
            this.outp = 0;
        }
    }

    // подсчитываем квадрат текущей мощности сигнала
    public struct EnergySum {
        FNC fnc;

        public void Step(double inp) {
            fnc.Step(inp * inp);
        }

        public EnergySum(double k) {
            fnc = new FNC(k);
        }
    }

    // генерируем отсчеты
    public struct Generator {
        public double outp, outp90;
        double df, q;

        /// <param name="f_discr">частота дискретизации</param>
        /// <param name="f_generate">частота генератора</param>
        public Generator(double f_discr, double f_generate) {
            df = 2 * Math.PI * f_generate / f_discr;

            q = 0;
            outp = outp90 = 0;
        }

        public void Step() {
            q += df;
            if (q > 2 * Math.PI)
                q -= 2 * Math.PI;

            outp = Math.Sin(q);
            outp90 = Math.Cos(q);
        }
    }

    // целевой детектор частоты
    public class Detector {
        FNC fnc, fnc90;
        Generator generator;
        public double outp;            // выход детектора
        public bool signal;            // обнаружен сигнал выше порога

        const double reaction = 0.025; // 25 mc
        const double threshold = 0.2;

        public Detector(double f_discr, double f_detect) {
            double k = 1 - Math.Pow(Math.Sqrt(2) / 2, 1 / (2 * f_discr * reaction));
            fnc = new FNC(k);
            fnc90 = new FNC(k);
            generator = new Generator(f_discr, f_detect);
            outp = 0;
            signal = false;
        }

        public void Step(double inp, double energy) {
            generator.Step();
            fnc.Step(inp * generator.outp);
            fnc90.Step(inp * generator.outp90);
            outp = fnc.outp * fnc.outp + fnc90.outp * fnc90.outp;
            signal = energy * threshold < outp;
        }
    }

    // пересечение 2-х частот на клавиатуре
    public class Analizer {
        Detector horizontal;
        Detector vertical;
        public char symbol;
        public bool signal = false;

        public Analizer(Detector h, Detector v, char symb) {
            horizontal = h;
            vertical = v;
            symbol = symb;
        }

        public void Step() {
            signal = horizontal.signal && vertical.signal;
        }
    }


Могут быть всякие мелкие неточности.
С инкапсуляцией тоже не заморачивался.

Замечание.
Генератор вполне может генерить {0, 1}, а не просчитывать синусы/косинусы каждый раз. Если точности будет не хватать, то буквально в 3-х битах закодированая таблица синусоиды дает уже весьма точные результаты. Т.е. почти все здесь можно переводить на int.
Re[18]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 03:48
Оценка: 24 (1)
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, vdimas, Вы писали:


V>>Поэтому мы делаем непрерывное интегрирование. Подобрав правильную частоту среза в фильтрах мы обнаружим сигнал как раз если он будет длительностью не менее 20 мс.


A>Так, а что такое частота среза?


Частота среза — это такая частота фильтра, мощность которой падает вдвое при прохождении через фильтр. т.е. остается примерно 70% от амплитуды.

A>Я думал что это имеет смысл вроде 1/(длина окна), но только окно плавающее, а сейчас уже сомневаюсь.


Нет, нерекурсивные фильтры тоже бывают оконными. Так вот, частота среза не зависит от длины окна, она зависит от коэф. От длины окна зависит точность. В идеале окно должно быть бесконечным, а плавать — ровно на 1 отсчет. Поэтому мне более по душе рекурсивные фильтры (с бесконечной историей) и потоковые алгоритмы на их основе.


A>Вообще чем мучаться со мной, может кинуть в сеня ссылкой на документацию?


Хм... когда я всем этим занимался вплотную русскоязычного интернета еще не существовало. Я думаю, что "z-преобразование цифровые фильтры" — неплохое сочетания для гугла

--------
Вот нарыл сжатое нечто: http://www.npi.msu.su/structinc/lib/books/nuc_el/p1.pdf

Там и теория и практика. Возможно, что я неправильно расчитал k в своем ФНЧ в том исходнике. Как раз сможешь проверить или пересчитать.
Re[3]: Частотная характеристика звука.
От: raskin Россия  
Дата: 25.12.05 18:38
Оценка: 10 (1)
adontz wrote:

> Богатый выбор иногда рождает больше проблем, чем отсутствие выбора

> Какую оконную функцию брать-то?

Попробуйте blackman. Вероятно, устроит на каком-то этапе. Когда не
устроит — Вы уже будете знать, чем не устроило и сможете выбирать спокойно.
Posted via RSDN NNTP Server 2.0
Re: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 19:33
Оценка: 9 (1)
Здравствуйте, adontz, Вы писали:

Кстати!!! Как я забыл об одной офигительной вещи — EWB www.electronicsworkbench.com

В общем, что это за приблуда — это такой симулятор электрических и цифровых схем. Идеальный инструмент для твоего случая.

Как им пользоваться. У него есть большая бибилотека элементов, и если не ошибаюсь, DTMF генератор тоже есть. Если нет — не страшно, можно просто проссумировать выход 2-х синусоидальных генераторов.


Итак. Как я предлагаю использовать EWB для твоих экспериментов/расчетов?

Надо составить электрическую схему описанного мною алгоритма. Т.е. ставишь DTMF генератор, затем накидываешь на схему умножитель (для анализа мощности), выход пропускаешь через ФНЧ — получил оценивание квадрата мощности входного сигнала.

Затем накидываешь анализатор. Он состоит из генератора синусоиды с 2-мя выходами в 90 градусов, двух умножителей, двух фильтров НЧ. Выходы этих фильтров опять умножаем на себя и складываем (f1*f1+f2*f2) — получили квадрат мощности искомого сигнала.

Выход анализатора мощности сравниваем с выходом анализатора сигнала с помощью компаратора — порогового устройства.

К любой точке схемы можно подключать осциллограф и смотреть или записывать а потом внимательно смотреть на происходящее. Очень удобно будет отладить все параметры схемы, погонять его в разных условиях, подмешивая шум и т.д.

В общем, весьма и весьма рекомендую. Крайне полезный тул для подобных задач.

----------
Если не ошибаюсь, в последних версиях все ok с модульностью (последний раз серьезно работал с ним в 97-м), т.е. каждый элемент можно описать как модуль и затем использовать повторно. Короче, собрать ПОЛНУЮ схему анализатора DTMF, состоящего из отдельных анализаторов частот будет более чем просто.
Re[9]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 08:36
Оценка: +1
Здравствуйте, LelicDsp, Вы писали:

J>>Если все возможные частоты сигналов в канале зараннее известны, то можно использовать набор оптимальных фильтров (фильтров Винера) и анализировать уровень сигнала на выходе каждого из них.

LD>оптимальный фильтр для синусоиды как выглядит?

Ребята, ну хватит уводить человека в сторону. Задача не стоит — отфильтровать сигнал. Задача стоит — обнаружить факт наличия. Корреляция с эталоном — это самый простой и самый надежный способ. Прекрасно работает даже в условиях, когда шум сильно перекрывает основной сигнал.
Re[10]: Частотная характеристика звука.
От: Dmi_3 Россия  
Дата: 04.01.06 19:55
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Задача стоит — обнаружить факт наличия. Корреляция с эталоном — это самый простой и самый надежный способ. Прекрасно работает даже в условиях, когда шум сильно перекрывает основной сигнал.


Именно так! Когда я на синклере АОН делал то к этому же и пришел.
Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.12.05 02:44
Оценка:
Надо получить частотну характеристику звука. Как я делаю ниже.
Проблема в том, что в качестве пиков выдаются какие-то ну очень приблизительные значения (разброс 100-200 герц), хотя, скажем, soundforge по тому же сигналу определяет пики очень чётко.
Формат записи 8бит, 22500Гц, моно.
static void dsAudioCapture_OnCapture(CaptureParameters captureParameters, byte[] data)
{
    /* получили новые данные и добавили в буффер */
    foreach (byte sample in data)
    {
        buffer.Add(sample);
    }


    /* если данных в буффере достаточно для обработки */
    if (buffer.Count > BlockSize)
    {
        /* найдём минимальное и максимальное значения */
        double bufferMin = buffer[0];
        double bufferMax = buffer[0];
        
        for (int index = 0; index < BlockSize; ++index)
        {
            if (buffer[index] < bufferMin)
            {
                bufferMin = buffer[index];
            }

            if (buffer[index] > bufferMax)
            {
                bufferMax = buffer[index];
            }
        }

        /* тут хранится сам сигнал */
        Complex[] signal = new Complex[BlockSize];

        /* отмасштабируем данные, чтобы работать с числами определённого порядка и избежать ошибок округления */
        for (int index = 0; index < BlockSize; ++index)
        {
            signal[index] = new Complex((buffer[index] - bufferMin) / (bufferMax - bufferMin), 0.0);
        }

        /* выкинем обработанный блок из буффера */
        buffer.RemoveRange(0, BlockSize);

        /* тут будут записаны результаты */
        Complex[] result = new Complex[BlockSize];
        
        /* натравили БПФ */
        fft.Calculate(signal, result);

        /* тут будут храниться пары интенсивность-частота */
        SortedList<double, double> frequencyList = new SortedList<double, double>();

        /* интересуют частоты ниже 2КГц */
        int indexTo = (int)Math.Round(2000.0 * BlockSize / captureParameters.SamplePerSecondNumber);

        /* заполняем сортированный список частот. Самые интенсивные в конце */
        for (int index = 1; index < indexTo; ++index)
        {
            frequencyList.Add(
                result[index].Re,
                ((double)index) * ((double)captureParameters.SamplePerSecondNumber) / ((double)BlockSize));
        }

        /* только интересующие частоты */
        int frequencyFrom = 500;
        int frequencyTo = 2000;
        int frequencyCount = 0;

        /* есть ли среди 5 самых интенсивных частот интересующие? */
        for (int index = Math.Max(0, frequencyList.Count - 5); index < frequencyList.Count; ++index)
        {
            if ((frequencyList.Values[index] > frequencyFrom) && (frequencyList.Values[index] < frequencyTo))
            {
                ++frequencyCount;
            }
        }
        
        /* если да, то выводим их */
        if (frequencyCount > 0)
        {
            Console.Write("FREQ:");
            for (int index = Math.Max(0, frequencyList.Count - 5); index < frequencyList.Count; ++index)
            {
                if ((frequencyList.Values[index] > frequencyFrom) && (frequencyList.Values[index] < frequencyTo))
                {
                    Console.Write(" [{0}] ", Math.Round(frequencyList.Values[index]).ToString().PadLeft(5));
                }
            }
            Console.WriteLine();
        }
    }
}


Во избежание лишних вопросов, привожду так же код класса БПФ (Совершенно не оптимизирован, но мне пока важно, чтобы всё работало. E — even, O — odd.).
class FFT
{
    public void Calculate(Complex[] signal, Complex[] result)
    {
        if (signal.Length == 1)
        {
            result[0] = signal[0];
        }
        else
        {
            Complex[] signalE = new Complex[signal.Length / 2];
            Complex[] signalO = new Complex[signal.Length / 2];

            for (int index = 0; index < signal.Length / 2; ++index)
            {
                signalE[index] = signal[2 * index];
                signalO[index] = signal[2 * index + 1];
            }

            Complex[] resultE = new Complex[signal.Length / 2];
            Complex[] resultO = new Complex[signal.Length / 2];

            Calculate(signalE, resultE);
            Calculate(signalO, resultO);

            Complex omegaN = new Complex(Math.Cos(2 * Math.PI / signal.Length), Math.Sin(2 * Math.PI / signal.Length));
            Complex omega = new Complex(1.0);

            for (int index = 0; index < signal.Length / 2; ++index)
            {
                result[index] = resultE[index] + resultO[index] * omega;
                result[index + signal.Length / 2] = resultE[index] - resultO[index] * omega;

                omega = omega * omegaN;
            }
        }
    }
}

Ну то что я Complex реализовал правильно, надеюсь вы мне верите
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.12.05 12:32
Оценка:
Здравствуйте, raskin, Вы писали:

Богатый выбор иногда рождает больше проблем, чем отсутствие выбора
Какую оконную функцию брать-то?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 25.12.05 20:29
Оценка:
Здравствуйте, adontz, Вы писали:

A>Богатый выбор иногда рождает больше проблем, чем отсутствие выбора

A>Какую оконную функцию брать-то?

Что-то мне кажется, что сама задача как-то неверно поставлена. Что требуется-то? Определить частотные харктеристики на некоей регулярной сетке? Или выдавать мнгновенные (и нерегулярные, т.е. дробные) величины и фазы текущих частотных составляющих на каждом отсчете (скажем до 10 основных по можности тонов?)

Решал когда-то подобную задачу для электрогитарного синтезатора. Есть алгоритмы. Они обычно бесконечны, работают без окна и всяких БПФ, т.е. организованы как бесконечные фильтры, "следящие" за основными (по мощности) составляющими звука. Как раз мне под гитарный процессор подходило, ибо нужна была мгновенная точность основных составляющих.
Re[4]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.12.05 20:32
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Что-то мне кажется, что сама задача как-то неверно поставлена. Что требуется-то?


Распознавать DTMF
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[5]: Частотная характеристика звука.
От: Шахтер Интернет  
Дата: 26.12.05 10:26
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, vdimas, Вы писали:


V>>Что-то мне кажется, что сама задача как-то неверно поставлена. Что требуется-то?


A>Распознавать DTMF


Это не делают БПФ ом. Пороюсь в своих архивах, напишу позже.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 26.12.05 10:31
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Это не делают БПФ ом. Пороюсь в своих архивах, напишу позже.


Да? А у меня почти вышло
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[5]: Частотная характеристика звука.
От: jhng Россия  
Дата: 26.12.05 10:50
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, vdimas, Вы писали:


V>>Что-то мне кажется, что сама задача как-то неверно поставлена. Что требуется-то?


A>Распознавать DTMF


Я так понимаю, что нужно определять основную частоту сигнала. Для этого обычно используются методы параметрического спектрального анализа (например, MUSIC или EV). Точность получаемых результатов у них больше. Про эти методы можно, например почитать в "Цифровой спектральный анализ и его приложения" (Марпл-мл.).
Re[6]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 26.12.05 10:54
Оценка:
Здравствуйте, jhng, Вы писали:

A>>Распознавать DTMF

J>Я так понимаю, что нужно определять основную частоту сигнала.

Dual-Tone Multi-Frequency

Нужно найти интенсивности всех гармоник. Просто найти частоту основной гармоники мало.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[7]: Частотная характеристика звука.
От: jhng Россия  
Дата: 26.12.05 13:55
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, jhng, Вы писали:


A>>>Распознавать DTMF

J>>Я так понимаю, что нужно определять основную частоту сигнала.

A>Dual-Tone Multi-Frequency


A>Нужно найти интенсивности всех гармоник. Просто найти частоту основной гармоники мало.


Ну так ты прочитай про эти методы поподробнее. Они как раз и предназначены для определения частот и уровней гармонических составляющих сигнала.
Если все возможные частоты сигналов в канале зараннее известны, то можно использовать набор оптимальных фильтров (фильтров Винера) и анализировать уровень сигнала на выходе каждого из них. Затем по получаемым результатам принимать то или иное решение. Может так будет даже проще.
Re[8]: Частотная характеристика звука.
От: Trean Беларусь http://axamit.com/
Дата: 26.12.05 14:12
Оценка:
Здравствуйте, jhng, Вы писали:

J>Здравствуйте, adontz, Вы писали:


A>>Здравствуйте, jhng, Вы писали:


A>>>>Распознавать DTMF

J>>>Я так понимаю, что нужно определять основную частоту сигнала.

A>>Dual-Tone Multi-Frequency


A>>Нужно найти интенсивности всех гармоник. Просто найти частоту основной гармоники мало.


J>Ну так ты прочитай про эти методы поподробнее. Они как раз и предназначены для определения частот и уровней гармонических составляющих сигнала.

J>Если все возможные частоты сигналов в канале зараннее известны, то можно использовать набор оптимальных фильтров (фильтров Винера) и анализировать уровень сигнала на выходе каждого из них. Затем по получаемым результатам принимать то или иное решение. Может так будет даже проще.

А можно еще про вейвлеты почитать здесь, они как раз и предназначены для получения частотной информации по времени.
Re[8]: Частотная характеристика звука.
От: jhng Россия  
Дата: 26.12.05 16:00
Оценка:
Здравствуйте, jhng, Вы писали:

J>Здравствуйте, adontz, Вы писали:


A>>Здравствуйте, jhng, Вы писали:


A>>>>Распознавать DTMF

J>>>Я так понимаю, что нужно определять основную частоту сигнала.

A>>Dual-Tone Multi-Frequency


A>>Нужно найти интенсивности всех гармоник. Просто найти частоту основной гармоники мало.


Еще как вариант можно использовать банк резонансных контуров (с резистором в цепи конденсатора или катушки для ограничения коэффициента передачи по частоте). Тогда и групповая задержка у всех фильтров будет одинаковой на резонансной частоте (наверное... ), и затрат ресурсов/времени мало, поскольку разностные уравнения получаются простыми.
Re[8]: Частотная характеристика звука.
От: LelicDsp Россия  
Дата: 26.12.05 17:38
Оценка:
J>Если все возможные частоты сигналов в канале зараннее известны, то можно использовать набор оптимальных фильтров (фильтров Винера) и анализировать уровень сигнала на выходе каждого из них.
оптимальный фильтр для синусоиды как выглядит?
Re[8]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 26.12.05 18:02
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Держи код


Ни хрена не понял, но спасибо
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[9]: Частотная характеристика звука.
От: jhng Россия  
Дата: 26.12.05 19:18
Оценка:
Здравствуйте, LelicDsp, Вы писали:

J>>Если все возможные частоты сигналов в канале зараннее известны, то можно использовать набор оптимальных фильтров (фильтров Винера) и анализировать уровень сигнала на выходе каждого из них.

LD>оптимальный фильтр для синусоиды как выглядит?

Берешь один период синусоиды, вычисляешь ее АКФ. Полученные отсчеты АКФ и будут являться коэффициентами фильтра.
Нечто похожее Шахтер уже привел.
Re[10]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 26.12.05 19:21
Оценка:
Здравствуйте, jhng, Вы писали:

J>Берешь один период синусоиды, вычисляешь ее АКФ


Что такое АКФ? Люди я в этом вопросе лопух, не надо кидаться непонятными словами
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[7]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:09
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, Шахтер, Вы писали:


Ш>>Это не делают БПФ ом. Пороюсь в своих архивах, напишу позже.


A>Да? А у меня почти вышло


Это из пушки по воробъям
Re[12]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 01:14
Оценка:
Здравствуйте, jhng, Вы писали:

Большое спасибо за подробный ответ. А то я по АКФ только Аэрокосмический факультет нашёл

Что касается того что есть. Шумов практически нету. Точность нужна в 20Гц-50Гц (3% от частоты). Требований к вычислитеной сложности особых нет, но делаться всё должно в real-time.

Сейчас делаю так. Беру достаточно большой (около трети секунды) массив семплов. Конкретно 8192. Натравляю БПФ, ищу самые интенсивные гармоники. Сдвигаю всё на 2048 семплов. Работае в принципе неплохо, но есть минусы.
Формально надо распознавать сигналы длительностью от 30мс, а это 675 семплов или 15-30 полных колебаний. На таком объёме данных почему-то БПФ по чёрному обламывается. От оконных функций, если честно, особого эффекта так и не наблюдал, может как-то не не так пользуюсь.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[6]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 01:17
Оценка:
Здравствуйте, vdimas, Вы писали:

АКФ судя по всему важная вешь

А доки нету, а то что такое "2 фильтра НЧ первого порядка" я тоже не знаю. Я только с БПФ работал, да и то немного.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[13]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 01:22
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Потому что АКФ тут не к месту.


Вы меня совсем запутали

V>Нужна обычная банальная корреляция с требуемыми частотами, она отлично работает даже при уровне шума превышающем уровень сигнала.


А сколько колебаний её нужно для устойчивого распознавания частоты? 10-20 хватит?

V>Корреляция с некоей частотой считается как произведение отсчетов сигнала на сдвинутые на 90 градусов отсчеты синусоид исследуемой частоты.

V>Т.е. у нас есть отсчеты f и f' — это сдвинутые на 90 градусов отсчеты исследуемой частотной составляющей.
V>p — отсчеты входного сигнала.

V>на каждом шаге:

V>s += p * f;
V>s' += p * f';

V>s и s' небходимо фильтровать НЧ c нужным срезом (смотря какая нужна скорость реакции).


V>Текущая мощность — sqrt(s*s + s'*s'); ВСЕ!!!


Я так понимаю сигнал распознан, если эта самая текущая мошьность неменее какого-то порога на протящее какого-то промежука времени?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[13]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:27
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, jhng, Вы писали:


A>Большое спасибо за подробный ответ. А то я по АКФ только Аэрокосмический факультет нашёл


A>Что касается того что есть. Шумов практически нету. Точность нужна в 20Гц-50Гц (3% от частоты). Требований к вычислитеной сложности особых нет, но делаться всё должно в real-time.


A>Сейчас делаю так. Беру достаточно большой (около трети секунды) массив семплов. Конкретно 8192. Натравляю БПФ, ищу самые интенсивные гармоники. Сдвигаю всё на 2048 семплов. Работае в принципе неплохо, но есть минусы.

A>Формально надо распознавать сигналы длительностью от 30мс, а это 675 семплов или 15-30 полных колебаний. На таком объёме данных почему-то БПФ по чёрному обламывается. От оконных функций, если честно, особого эффекта так и не наблюдал, может как-то не не так пользуюсь.

Нет, формально надо распознавать за 20мс, иначе не поймаешь от некоторых старых телефонов, т.е. у тебя в распоряжении еще меньше полных колебаний. Никакая окна тебе не нужны, тебе нужен непрерывный процесс.

Если суть непонятна — пиши в приват, накатаю грубую реализацию.
Re[7]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:38
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, vdimas, Вы писали:


A>АКФ судя по всему важная вешь


Нет, это не АКФ, это просто КФ, она лучше подходит сюда.

A>А доки нету, а то что такое "2 фильтра НЧ первого порядка" я тоже не знаю. Я только с БПФ работал, да и то немного.


фильтр нижних частот первого порядка программируется крайне легко. Пусть p — отчеты сигнала, k — некий коеф, определяющий частоту среза относительно частоты дискретизации, s — выход фильтра.

На каждом шаге:
s = s * (1 — k) + p * k;

оно же:
s = s — (s-p) * k;

Если к==0.25, то это примерно так (привычка обходиться без умножения при обработке сигналов):
s = s — ( (s — p) >> 2)
Re[14]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 01:45
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Нет, формально надо распознавать за 20мс, иначе не поймаешь от некоторых старых телефонов, т.е. у тебя в распоряжении еще меньше полных колебаний. Никакая окна тебе не нужны, тебе нужен непрерывный процесс.


Я этим пользовался http://www.ece.utexas.edu/~mason/codesign/dtmf.html. Вроде как минимум 40мс, а от 23мс до 40мс как получится.

V>Если суть непонятна — пиши в приват, накатаю грубую реализацию.


Да нет, мне сами алгоритмы тоже интересны. Может потом опять пригодиться, хочу понять суть. Понятая мною суть пока такая (я сразу о реализации).

Есть бесконечный массив семплов (ну грубо говоря, сильно старые меня конечно не волнуют).
Есть частота дискретизацц D, частота которую надо распознать F, минимальная распознаваемая длительность сигнала T.
Для каждого sample[i], частоты D я вычисляю

sum1[F, i] += sample[i] * sin(2*pi*i/D);
sum2[F, i] += sample[i] * sin(2*pi*i/D + pi/2);
energy[F, i] = sqrt(sum1[F, i]*sum1[F, i]) + sqrt(sum2[F, i]*sum2[F, i])

Если есть такой промежуток [k — D*T, k], что на нём energy[F, i] всегда больше некоторого порогового значения, то считать, что сигнал распознан.
Насколько я понимаю, мне понадобиться считать и общую энергию сигнала.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[14]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 01:46
Оценка:
Здравствуйте, adontz, Вы писали:

V>>Потому что АКФ тут не к месту.


A>Вы меня совсем запутали


Нет, просто не надо путать автокорреляцию с обычной корреляцией. Автокорреляция — это корреляция сигнала самому себе, нам такое здесь не нужно.

V>>Нужна обычная банальная корреляция с требуемыми частотами, она отлично работает даже при уровне шума превышающем уровень сигнала.


A>А сколько колебаний её нужно для устойчивого распознавания частоты? 10-20 хватит?


вполне

V>>Корреляция с некоей частотой считается как произведение отсчетов сигнала на сдвинутые на 90 градусов отсчеты синусоид исследуемой частоты.

V>>Т.е. у нас есть отсчеты f и f' — это сдвинутые на 90 градусов отсчеты исследуемой частотной составляющей.
V>>p — отсчеты входного сигнала.

V>>на каждом шаге:

V>>s += p * f;
V>>s' += p * f';

V>>s и s' небходимо фильтровать НЧ c нужным срезом (смотря какая нужна скорость реакции).


V>>Текущая мощность — sqrt(s*s + s'*s'); ВСЕ!!!


A>Я так понимаю сигнал распознан, если эта самая текущая мошьность неменее какого-то порога на протящее какого-то промежука времени?


Прикол в том, что "протяжение какого-то промежутка времени" задается частотой среза ФНЧ. Поэтому достаточно просто факта достижения порога.

Опять обращаю внимание, что порог — величина относительная общей мощности сигнала.

Общую мощность сигнала считаем так:
sqrt(ФНЧ(p * p))
Re[15]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 02:15
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Общую мощность сигнала считаем так:

V>sqrt(ФНЧ(p * p))

А зачем нам ФНЧ (фильтр низкой частоты?) для подсчёта общей мощности?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[16]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 03:02
Оценка:
Здравствуйте, adontz, Вы писали:

V>>Общую мощность сигнала считаем так:

V>>sqrt(ФНЧ(p * p))

A>А зачем нам ФНЧ (фильтр низкой частоты?) для подсчёта общей мощности?


Хмм... проблема серьезного взаимонепонимания

Текущие отсчеты бывают разные, и мнговенные значения квадрата мощности тоже разные, иногда пиковые, иногда нулевые. Интересует некий интеграл за определенное время.

Однако суть самой задачи такова, что делить входную последовательность на окна — это все испортить. Например, если у нас реакция должна быть 20 мс, то какое нам брать окно, чтобы не прозевать эту рекию? 10мс? 5мс?

Поэтому мы делаем непрерывное интегрирование. Подобрав правильную частоту среза в фильтрах мы обнаружим сигнал как раз если он будет длительностью не менее 20 мс.
Re[17]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 03:15
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Поэтому мы делаем непрерывное интегрирование. Подобрав правильную частоту среза в фильтрах мы обнаружим сигнал как раз если он будет длительностью не менее 20 мс.


Так, а что такое частота среза? Я думал что это имеет смысл вроде 1/(длина окна), но только окно плавающее, а сейчас уже сомневаюсь.

Вообще чем мучаться со мной, может кинуть в сеня ссылкой на документацию?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[19]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.05 04:13
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Частота среза — это такая частота фильтра, мощность которой падает вдвое при прохождении через фильтр. т.е. остается примерно 70% от амплитуды.


По идее их две должно быть. Нет?

V>Вот нарыл сжатое нечто: http://www.npi.msu.su/structinc/lib/books/nuc_el/p1.pdf


Спасибо!
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[20]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 27.12.05 07:35
Оценка:
Здравствуйте, adontz, Вы писали:

V>>Частота среза — это такая частота фильтра, мощность которой падает вдвое при прохождении через фильтр. т.е. остается примерно 70% от амплитуды.


A>По идее их две должно быть. Нет?


Для полосового? Да, их две для полосового фильтра. А у фильтра низких частот есть только одна частота среза. На самом деле ФНЧ первого порядка имеет очень пологую характеристику среза, т.е. нет такого, что вот до какой-то частоты мы пропускаем, а потом — хлоп и нету. Речь лишь может идти о коэф. подавления сигнала.
За частоту среза выбрана такая частота, мощность сигнала на которой падает вдвое при прохождении через фильтр.

На ФНЧ удобно делать всякие сглаживатели, т..е например вот грубо сигнал после умножения на самого себя (синий) и после фильтрации неким фильтром низких частот (красный):



Примерно так у нас будет работать детектор мощности сигнала. Кстати, на рисунке частота среза ФНЧ — это примерно 4 периода основного синего сигнала. На практике, у тебя реакия = 25 мс, т.е. 40 Гц, а наименьшая входная частота 600 с копейками, т.е. на самом деле картинка будет еще более гладкой. Да, кстати, забыл сказать, чтобы перед подачей сигнала в систему предварительно отфильтровали его фильтром ВЧ, для убирания постоянной составляющей, и для отсекания лишней полосы шума. Кстати, неплохо это сделать и "сверху". Итого мы получим полосовой фильтр на входе, который выделяет интересующую нас полосу. Добавлю, что если полосовой фильтр будет 2-го порядка, то ты получишь очень покатые спады АЧХ, поэтому частоты среза фильтров надо выбирать с запасом примерно вдвое. Т.е. если крайняя нижняя полоса DTMF = 650, то бери на ФВЧ примерно 325.
Re[10]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 02.01.06 21:15
Оценка:
Здравствуйте, Шахтер, Вы писали:


Пара комментариев:

Ш>Иными словами, данная составляющая сигнала есть линейнаю комбинация двух сигналов sin(2*Pi*(F1/Fd)*k) и cos(2*Pi*(F1/Fd)*k).


Линейная комбинация — это суть векторная сумма. Зря ты убрал из формул sin(phy1) и cos(phy1) — стало непонятно слушателям.

Эти sin(phy1) и cos(phy1) и есть искомые проекции, модуль мощности мы потом считаем по теореме Пифагора, т.е. по правилу вычисления модуля векторов.

Ш>Т.е. фактически, нам нужно просто спроектировать полученный сигнал на две ортогональные плоскости плоскости и вычислить энергию проекций.


Роме: проекция вычисляется путем свертки с единичным сигналом.

Ш>Что собственно мы и делаем. Дальше проверяем, что мощность на одной из пар стандартных частот превосходит порог.


Угу, у меня примерно тоже самое http://www.rsdn.ru/Forum/Message.aspx?mid=1563751&amp;only=1
Автор: vdimas
Дата: 27.12.05


(правда, я вычисления синусов/косинусов не буферировал, т.к. в оригинальном варианте у меня вообще умножение на прямоугольные сигналы сдвинутые на 90 градусов).

Отличие от твоего варианта в том, что твой вариант реально требует довольно-таки длинной последовательности, иначе подобный детектор будет реагировать на входные частоты с большим отклонением, чем 3% в стандарте. К тому же, буфер каждый раз пересчитывается по кругу.

В общем, предлагаю вместо этого использовать "бесконечный" сумматор, выполненный в виде фильтра НЧ с частотой среза, обратной скорости реакции. Сама характеристика фильтра НЧ уже является некоей оконной ф-ией, где последние отсчеты будут больше влиять на результат, чем дальние. А в твоем варианте с кольцевым буфером "давние" отсчеты так же влияют на результат, как и самые последние. (Хотя, надо погонять оба варианта... Подход у них абсолютно одинаковый...)

Повторюсь, что мой вариант прекрасно работал с прямоугольными образцовыми сигналами, т.е. вместо умножения, делаем так: 1 — прибавляем, 0 — отнимаем. Точность по частоте в случае со сверткой с прямоугольными импульсами примерно обратна количеству полупериодов, т.е. получалась около 5%, что вполне хватает. Паразитные гармоники прямоугольного сигнала влияли не сильно, т.к. входной сигнал сначала отфильтровывался, т.е. подавался лишь сигнал из искомого диапазона. И к счастью, ближайшая значимая гармоника прямоугольного сигнала — третья (остальные — менее значимые), т.е. в случае с DTMF паразитные гармоники оказываются за пределами допустимых стандартом погрешностей. Когда я этим всем занимался, мне показалось, что частоты DTMF неспроста были выбраны именно так, старые аппаратные умножители для DTMF-детекторов делались на диодах, там как раз умножение с прямоугольным импульсом получалось.
Re[11]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 02.01.06 21:28
Оценка:
Здравствуйте, vdimas, Вы писали:

Отчитываюсь:

Сделал всё сам с нуля по объяснениям vdimas (кстати, кому лень — код Шахтёра замечательно работает). Всю целочисленную арифметику выкинул.
Единственная проблема с которой столкнулся это слишком большая избирательность по частоте. То есть даже скажем 703 вместо 697 уже не распознавалось. Поигрался с НЧ фильтром, вроде помогло, но с другой стороны теперь разрыв на 10мс, формально разрывом не являющийся, надо обрабатывать программно. Учитывая, что последовательные нажатия одной и той же цифры надо рассматривать как одно (то есть постобработка всё равно имеется) это не проблема. Думаю в конечном итоге неплохо будет сделать функцию автонастройки под телефон, чтобы все коэффициенты были на грани срабатывания.

В целом всем спасибо, вы мне очень помогли!
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[11]: Частотная характеристика звука.
От: Шахтер Интернет  
Дата: 03.01.06 16:32
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Шахтер, Вы писали:



V>Пара комментариев:


Ш>>Иными словами, данная составляющая сигнала есть линейнаю комбинация двух сигналов sin(2*Pi*(F1/Fd)*k) и cos(2*Pi*(F1/Fd)*k).


V>Линейная комбинация — это суть векторная сумма. Зря ты убрал из формул sin(phy1) и cos(phy1) — стало непонятно слушателям.


Линейной комбинацией двух векторов a и b называют вектор x*a+y*b, где x и y скаляры.

Ш>>Т.е. фактически, нам нужно просто спроектировать полученный сигнал на две ортогональные плоскости плоскости и вычислить энергию проекций.


V>Роме: проекция вычисляется путем свертки с единичным сигналом.


Не понял этой фразы. Причем здесь свертка?

Ш>>Что собственно мы и делаем. Дальше проверяем, что мощность на одной из пар стандартных частот превосходит порог.


V>Угу, у меня примерно тоже самое http://www.rsdn.ru/Forum/Message.aspx?mid=1563751&amp;only=1
Автор: vdimas
Дата: 27.12.05


Насколько я понял, ты используешь меандр вместо синуса. Так раньше делали на старых дохлых процах, на которых умножение было слишком дорогим удовольствием. Сейчас экономить на этом не имеет смысла.
Использовать меандр можно, предварительно отфильтровав сигнал, чтобы убрать высшие гармоники от искомых частот.
Тут возникает одна проблемка -- по-хорошему, энергию срезанной части тоже надо учитыват при рассчетах.

V>(правда, я вычисления синусов/косинусов не буферировал, т.к. в оригинальном варианте у меня вообще умножение на прямоугольные сигналы сдвинутые на 90 градусов).


V>Отличие от твоего варианта в том, что твой вариант реально требует довольно-таки длинной последовательности, иначе подобный детектор будет реагировать на входные частоты с большим отклонением, чем 3% в стандарте.


Это всё регулируется выбором порога срабатывания.

V>К тому же, буфер каждый раз пересчитывается по кругу.


Не понял, что ты имеешь ввиду?

V>В общем, предлагаю вместо этого использовать "бесконечный" сумматор, выполненный в виде фильтра НЧ с частотой среза, обратной скорости реакции. Сама характеристика фильтра НЧ уже является некоей оконной ф-ией, где последние отсчеты будут больше влиять на результат, чем дальние. А в твоем варианте с кольцевым буфером "давние" отсчеты так же влияют на результат, как и самые последние. (Хотя, надо погонять оба варианта... Подход у них абсолютно одинаковый...)


Ну так мы обсчитываем кусок сигнала -- с чего это старые отсчеты должны отличаться от новых?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[12]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 04.01.06 11:59
Оценка:
Здравствуйте, Шахтер, Вы писали:

V>>Линейная комбинация — это суть векторная сумма. Зря ты убрал из формул sin(phy1) и cos(phy1) — стало непонятно слушателям.


Ш>Линейной комбинацией двух векторов a и b называют вектор x*a+y*b, где x и y скаляры.


ok, ключевое слово было "векторная" (сумма векторная)


Ш>>>Т.е. фактически, нам нужно просто спроектировать полученный сигнал на две ортогональные плоскости плоскости и вычислить энергию проекций.


V>>Роме: проекция вычисляется путем свертки с единичным сигналом.


Ш>Не понял этой фразы. Причем здесь свертка?


Математически то, как ты ищешь проекции — это оно и есть. Свертка с некоей образцовой частотой.


Ш>Насколько я понял, ты используешь меандр вместо синуса.


Нет, там в коде у меня именно 2 синусоиды, это я устно делаю замечания, что для DTMF даже прямоугольного образцового сигнала достаточно.

Ш>Так раньше делали на старых дохлых процах, на которых умножение было слишком дорогим удовольствием. Сейчас экономить на этом не имеет смысла.


Согласен, речь шла не столько об умножении, сколько о вычислении sin и cos, которые не требовались в случае меандра, хотя, это тоже не проблема.


Ш>Использовать меандр можно, предварительно отфильтровав сигнал, чтобы убрать высшие гармоники от искомых частот.

Ш>Тут возникает одна проблемка -- по-хорошему, энергию срезанной части тоже надо учитыват при рассчетах.

Ты абсолютно прав. При сравнении нашего порога с общей энергией сигнала, последняя вычисляется от сигнала ДО фильтрации.

V>>Отличие от твоего варианта в том, что твой вариант реально требует довольно-таки длинной последовательности, иначе подобный детектор будет реагировать на входные частоты с большим отклонением, чем 3% в стандарте.


Ш>Это всё регулируется выбором порога срабатывания.


V>>К тому же, буфер каждый раз пересчитывается по кругу.


Ш>Не понял, что ты имеешь ввиду?


Ну, у тебя вроде "окно" движется (буфер), и ты каждый раз производишь вычисления над всем буфером. В моем варианте я произвожу вычисления только над текущим сэмплом.

V>>В общем, предлагаю вместо этого использовать "бесконечный" сумматор, выполненный в виде фильтра НЧ с частотой среза, обратной скорости реакции. Сама характеристика фильтра НЧ уже является некоей оконной ф-ией, где последние отсчеты будут больше влиять на результат, чем дальние. А в твоем варианте с кольцевым буфером "давние" отсчеты так же влияют на результат, как и самые последние. (Хотя, надо погонять оба варианта... Подход у них абсолютно одинаковый...)


Ш>Ну так мы обсчитываем кусок сигнала -- с чего это старые отсчеты должны отличаться от новых?


Тут речь о помехоустойчивости. Кратковременные мощные помехи на частотах близких к обнаруживаемым искажают "картинку" все время, пока они находятся в твоем окне (отсчеты помехи находятся в буфере), и даже возможны ложные срабатывания. Это действительно так — поэкспериментируй. В моем варианте ситуация сглаживается фильтром НЧ, и подобные по характеру помехи не приводят к срабатыванию детектора.
Re[12]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 04.01.06 12:30
Оценка:
Здравствуйте, adontz, Вы писали:

A>Отчитываюсь:


A>Сделал всё сам с нуля по объяснениям vdimas (кстати, кому лень — код Шахтёра замечательно работает). Всю целочисленную арифметику выкинул.

A>Единственная проблема с которой столкнулся это слишком большая избирательность по частоте. То есть даже скажем 703 вместо 697 уже не распознавалось.

Хм, мене 1%.. понятно... У меня использовался прямоугольный образцовый сигнал, избирательность была похуже, как раз по стандарту.

A>Поигрался с НЧ фильтром, вроде помогло, но с другой стороны теперь разрыв на 10мс, формально разрывом не являющийся, надо обрабатывать программно.


Не надо ничего обрабатывать программно. У тебя фильтры НЧ стоят на вычислении повернутых на 90 градусов проекций. Да, действительно, этот фильтр НЧ в таком случае надо сделать более быстрым. Но ведь ты можешь пропустить через допольнительный 20мс фильтр НЧ саму энергию, т.е. значения sqrt(f1*f1 + f1'*f1').

Тут важный момент в том, что весьма желательно, чтобы АЧХ фильтра, выявляющая общую энергию сигнала, была близка к АЧХ фильтра детектора конкретной частоты.

A>Учитывая, что последовательные нажатия одной и той же цифры надо рассматривать как одно (то есть постобработка всё равно имеется) это не проблема. Думаю в конечном итоге неплохо будет сделать функцию автонастройки под телефон, чтобы все коэффициенты были на грани срабатывания.


ИМХО, лучше все-таки привести систему в соответствии стандарту, и при этом добиться работоспособности даже при большом уровне шумов (например, громко говорить в трубку и при этом давить на клавиши — система должна срабатывать)

Чем ниже частота среза фильтра НЧ в этой системе, т.е. чем выше избирательность, тем выше помехоустойчивость. Надо вообще-то поискать, может быть последние стандарты более жесткие. Потому как мне трудно представить себе современную трубку, у которой погрешность излучения DTMF была бы 3%, реально у них погрешности — доли процента.
Re[13]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 04.01.06 12:43
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Хм, мене 1%.. понятно... У меня использовался прямоугольный образцовый сигнал, избирательность была похуже, как раз по стандарту.


Да мне просто ленб таблицу держать, я коэффициенты масштабирования запоминаю, а sin/cos считаю функциями.

V>Не надо ничего обрабатывать программно. У тебя фильтры НЧ стоят на вычислении повернутых на 90 градусов проекций. Да, действительно, этот фильтр НЧ в таком случае надо сделать более быстрым. Но ведь ты можешь пропустить через допольнительный 20мс фильтр НЧ саму энергию, т.е. значения sqrt(f1*f1 + f1'*f1').


То есть иметь два фильтра? Надо попробовать...

V>ИМХО, лучше все-таки привести систему в соответствии стандарту


Не факт что телефон будет очень соответствовать стандарту.

V>и при этом добиться работоспособности даже при большом уровне шумов (например, громко говорить в трубку и при этом давить на клавиши — система должна срабатывать)


С этим проблем нет. Я подавал на вход фильтра сигнал у которого уровень шума был даже выше уровня сигнала всё равпознаётся. В качестве генератора шума использовалcя генератор псевдослучайных чисел. Думаю шум получился вполне себе белый

V>Чем ниже частота среза фильтра НЧ в этой системе, т.е. чем выше избирательность, тем выше помехоустойчивость. Надо вообще-то поискать, может быть последние стандарты более жесткие. Потому как мне трудно представить себе современную трубку, у которой погрешность излучения DTMF была бы 3%, реально у них погрешности — доли процента.


Да на моём телефона всё как раз зашибись, но хотелось бы попробовать на всех.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[14]: Частотная характеристика звука.
От: vdimas Россия  
Дата: 04.01.06 20:35
Оценка:
Здравствуйте, adontz, Вы писали:

V>>Чем ниже частота среза фильтра НЧ в этой системе, т.е. чем выше избирательность, тем выше помехоустойчивость. Надо вообще-то поискать, может быть последние стандарты более жесткие. Потому как мне трудно представить себе современную трубку, у которой погрешность излучения DTMF была бы 3%, реально у них погрешности — доли процента.


A>Да на моём телефона всё как раз зашибись, но хотелось бы попробовать на всех.


вот поискал http://www.gaw.ru/html.cgi/txt/app/micros/msp430/slaae16.htm

там требуемая погрешность по частоте 1.8% указана...

Это я к чему... тут такие законы, что повысив избирательность вдвое, ты примерно вчетверо улучшаешь предельное отношение сигнал/шум.
Re[15]: Частотная характеристика звука.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 04.01.06 20:55
Оценка:
Здравствуйте, vdimas, Вы писали:

V>вот поискал http://www.gaw.ru/html.cgi/txt/app/micros/msp430/slaae16.htm

V>там требуемая погрешность по частоте 1.8% указана...
V>Это я к чему... тут такие законы, что повысив избирательность вдвое, ты примерно вчетверо улучшаешь предельное отношение сигнал/шум.

На самом деле мне проще попросить в Users Guide всех закнуться, чем объяснять почему на некоторых телефонах не срабатывает
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[13]: Частотная характеристика звука.
От: Шахтер Интернет  
Дата: 05.01.06 16:24
Оценка:
Здравствуйте, vdimas, Вы писали:

Ш>>Не понял этой фразы. Причем здесь свертка?


V>Математически то, как ты ищешь проекции — это оно и есть. Свертка с некоей образцовой частотой.


У нас похоже терминологические непонятки. Я вычисляю скалярное произведение, свертка сигналов -- это нечто иное.

V>>>К тому же, буфер каждый раз пересчитывается по кругу.


Ш>>Не понял, что ты имеешь ввиду?


V>Ну, у тебя вроде "окно" движется (буфер), и ты каждый раз производишь вычисления над всем буфером. В моем варианте я произвожу вычисления только над текущим сэмплом.


Нет, посмотри внимательно приведённый код. При поступлении очередного отсчета пересчитываются скалярные произведения, при этом нет нужды пересчитывать весь буфер -- мы учитываем только пришедший отсчет и ушедший. В сумме получается несколько операций умножения и сложения.

V>>>В общем, предлагаю вместо этого использовать "бесконечный" сумматор, выполненный в виде фильтра НЧ с частотой среза, обратной скорости реакции. Сама характеристика фильтра НЧ уже является некоей оконной ф-ией, где последние отсчеты будут больше влиять на результат, чем дальние. А в твоем варианте с кольцевым буфером "давние" отсчеты так же влияют на результат, как и самые последние. (Хотя, надо погонять оба варианта... Подход у них абсолютно одинаковый...)


Ш>>Ну так мы обсчитываем кусок сигнала -- с чего это старые отсчеты должны отличаться от новых?


V>Тут речь о помехоустойчивости. Кратковременные мощные помехи на частотах близких к обнаруживаемым искажают "картинку" все время, пока они находятся в твоем окне (отсчеты помехи находятся в буфере), и даже возможны ложные срабатывания. Это действительно так — поэкспериментируй. В моем варианте ситуация сглаживается фильтром НЧ, и подобные по характеру помехи не приводят к срабатыванию детектора.


Опять я чего-то не понял. Если у тебя идет такая помеха, что она задавила сигнал и сама из себя представляет DTMF тон, то сделать тут ты ничего не сможешь. Детектор должен на это дело реагировать. Но это случай исключительный. Обычно, мы находимя в ситуации, когда мощность помех значительно (хотя бы в несколько раз) меньше мощности полезного сигнала.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.