AFCViewerвид изнутри

Теперь о других частях AFCViewer. Поток обработки принятых звуковых данных организован с помощью класса Delphi TThread. Подробнее об этом можно прочитать в [1]. Процедура потока Execute представляет собой цикл, в котором опрашивается уже упоминавшийся флаг CapIs. Как только флаг устанавливается в состояние true, указывающее на приход данных, вызывается процедура вычисления амплитуды синусоидального сигнала CalcAmplitude. Правда, вызывается она не каждый раз. Дело в том, что при двойной буферизации очередная частота появляется на выходе звуковой карты не сразу, как только ее значение присваивается переменной содержащей текущую частоту сигнала, а в самом худшем случае почти через две половины буфера. Еще одна половина буфера воспроизведения должна быть полностью выведена, прежде чем можно будет надеятся, что в буфере ввода находится сигнал уже с новой частотой и ни что другое. За это время может произойти до трех событий ввода, которые должны быть пропущены. На всякий случай, значение константы Delay выбрано с небольшим запасом.

unit AFCThread;

interface

uses
  Classes, AFCDSTools;

type
  TAFCThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    procedure DrawGraph;
  end;

var
  DelayCount : integer;        // счетчик половин буфера
  SigAmp     : array of real;  // амплитуда сигнала в каждом канале

const
  Delay = 4;    // количество половин буфера ввода которое надо пропускать

implementation

uses
  AFCForm;      // чтобы иметь доступ к процедуре рисоваиня графика ThrDrawGraph

procedure TAFCThread.DrawGraph;
begin
  ThrDrawGraph; // процедура модуля главной формы
end;

//  процедура вычисления амлитуды синусоидального сигнала
procedure CalcAmplitude;
const
  pi2 = 2*pi;
var
  cn : integer;  // канал
  sinsum, cossum : real;
  ff, x : real;
  i : integer;
begin
  if not Assigned(SigAmp) or (Length(SigAmp) <> Length(Cap)) then
    SetLength(SigAmp, Length(Cap)); // количество каналов
  //  доля периода сигнала приходящаяся на один период дискретизации(угол)
  ff := SigFreq / DFreq;
  for cn:=0 to High(SigAmp) do begin
    sinsum:= 0;
    cossum:= 0;
    for i:=0 to High(Cap[cn]) do begin
      x:= pi2 * Frac(i*ff);  //  положение в периоде сигнала
      sinsum:= sinsum + sin(x)*Cap[cn,i];
      cossum:= cossum + cos(x)*Cap[cn,i];
    end;
    SigAmp[cn]:= Sqrt(sinsum*sinsum + cossum*cossum);
  end;
end;

procedure TAFCThread.Execute;
begin
  repeat;
    if CapIs then begin  //  новые данные
      if DelayCount > 0 then
        Dec(DelayCount)
      else begin
        CalcAmplitude;
        Synchronize(DrawGraph);
        DelayCount:= Delay;
      end;
      CapIs:= false;
    end;
  until Terminated;
end;

end.

Рассчитав амплитуду сигнала в каждом звуковом канале, процедура CalcAmplitude помещает результат в глобальную переменную SigAmp, преставляющую собой массив, число ячеек которого равно числу каналов. Затем вызывается процедура DrawGraph, рисующая очередную точку на графике в компоненте типа TChart главной формы. Рисовать в компонентах VCL из асинхронного потока просто так нельзя - будут сбои, причем случайные и от того, - трудно выявляемые. Чтобы всё работало надёжно, рисование графика обязательно следует делать в методе Synchronize класса TThread, причем передаваемая методу процедура должна быть объявлена как метод переменной этого класса. Для того, чтобы сделать модуль потока более универсальным, процедура DrawGraph не делает ничего, кроме вызова процедуры ThrDrawGraph из модуля главной формы, которая в свою очередь и рисует новую точку на графике. Кроме рисования графика, ThrDrawGraph выполняет общее управление процессом измерения амплитудно-частотной характеристики: устанавливает новую частоту сигнала, а когда частоты закончатся останавливает буферы DirectSound и завершает выполнение потока обработки. После того как процедура DrawGraph вернет управление, сбрасывается флаг CapIs, разрешая тем самым, заполнение массива Cap новым фрагментом сигнала из буфера ввода DirectSound. Далее цикл повторяется до завершения процесса измерения АЧХ.

Несколько слов о вычислении амплитуды дискретизированного синусоидального сигнала. На "человечьем" языке это звучит так. Мысленно представляем себе, что у нас не только массив с выборками реального сигнала, но и еще два массива такого же размера, один из которых заполнен выборками синуса, а другой выборками косинуса той же самой частоты, которую имеет сигнал и такой же частоте дискретизаци. Теперь поэлементно перемножаем массив синуса на массив сигнала и массив косинуса на массив сигнала. Получаем два массива произведений, после чего, у каждого полученного массива суммируем все элементы. Каждую полученную сумму возводим в квадрат, квадраты складываем, а из полученной итоговой суммы извлекаем квадратный корень. Это и будет искомая амплитуда. На математическом языке - амплитуда первой гармоники. А сами все эти действия - спектральный анализ для ряда с одной гармоникой. Важная деталь - размер массива с выборками сигнала должен быть таким, чтобы в нем помещалось больше половины периода нужной частоты, кроме того, размер должен быть одинаковым для всех частот. Подробное описание математической основы всего этого выходит за рамки данной статьи. Желающие могут почитать многочисленные книги по теории обработки дискретных сигналов, гармоническому (спектральному) анализу, преобразованию Фурье. Как пример можно привести книгу [2].

Вот собственно и все характерные особенности устройства AFCViewer. Как обычно, в статьях раздела "вид изнутри" не рассматриваются типовые вопросы создания прикладных программ. Предполагается, что базовыми навыками программирования читатель уже владеет. На последней странице этой статьи размещен исходный код модуля, содержащего массивы стандартных измерительных частот рядов 1/3, 1/6 октавы, массив ряда 1/12 октавы, а также процедура расчитывающая частоты для ряда 1/24 октавы. Вы можете свободно использовать этот модуль в своих проектах.

СПИСОК ЛИТЕРАТУРЫ
  1. Архангельский А.Я. Программирование в Delphi для Windows. Версии 2006, 2007, Turbo Delphi. - М.; ООО "Бином-пресс", 2007 г. - 1248 с.; ил.
  2. Дьяконов В.П. Справочник по алгоритмам и программам на языке бейсик для персональных ЭВМ: Справочник. - М.: Наука. Гл. ред. физ.-мат. лит., 1989. - 240 с. - ISBN 5-02-014530-0.

Назад: к общему описанию программы
Голос народа: отзывы, пожелания, мнения
1 2
3
4 5

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

Москва, 2013-2020 гг., © ZHarNS58
480