Дискретное преобразование Фурье — это одно из преобразований Фурье, которое широко применяется в различных алгоритмах цифровой обработки сигналов, а также в других сферах, где выполняется анализ частот в дискретном сигнале.
Общие сведения о дискретном преобразовании Фурье
При выполнении численных исследований дискретное преобразование Фурье считается очень эффективным методом, при помощи которого может осуществляться взаимно однозначное соответствие сеточной функции и ее образа в области спектрального пространства. Спектральная обработка итогов вычислительных и физических экспериментов при помощи преобразования Фурье значительно расширяет возможности анализа в научных исследованиях. В методиках расщепления решения многомерных задач математической физики дискретное преобразование Фурье является мощнейшим средством формирования экономичных вычислительных схем.
Наличие возможности прямого и обратного перехода от сеточной функции к ее спектру предоставляет возможность решения в спектральном пространстве отдельных компонентов расщепленной задачи, что существенно повышает эффективность вычислительной схемы. Дискретное преобразование Фурье выступает как ключевая составляющая программного обеспечения в спектроскопии, томографии, в обработке сигналов и изображений.
Дискретное преобразование Фурье является численным алгоритмом отображения функций разложением в ряд по тригонометрическим функциям. Переход в спектральное пространство гармоник Фурье считается особенно эффективным при выполнении фундаментальных и прикладных исследований аналитическими и численными методами волновых процессов в оптике, акустике, электронике, радиофизике и других научных областях. Методика гармоник Фурье, получившая начало как математический аппарат для решения задачи теплопроводности, сегодня стала мощным средством спектрального анализа в физических исследованиях.
Дискретное преобразование Фурье приобрело обширное распространение после того, как были разработаны алгоритмы быстрого преобразования, позволяющие существенно уменьшить вычислительные затраты, включая и массивы большой размерности. Сегодня алгоритмы быстрого преобразования Фурье являются общеизвестными и широко применяются в спектральном анализе.
Дискретное преобразование Фурье на «си шарп»
Рассмотрим пример игры музыканта на пианино. Ели подходить к этому процессу упрощенно, то этот музыкальный инструмент является набором белых и черных клавиш, и если нажимать на каждую из этих клавиш, то будут извлекаться определенные звуки с заранее сформированной частотой, от низкой до высокой. При грубом обобщении, все клавиши представляют собой просто генераторы синусоидальных акустических волн определенной частоты.
Когда музыкант играет музыкальное произведение, то он по очереди или одновременно нажимает и отпускает клавиши, в результате чего синусоидальные сигналы либо их совокупности могут накладываться друг на друга, формируя рисунок. Как раз данный рисунок должен восприниматься слушателями в качестве мелодии, благодаря чему искушенные слушатели без труда способны узнать одно и то же произведение, которое исполняется на разных инструментах в различных жанрах или даже непрофессионально напевается любителем музыки
Обратная задача заключается в том, чтобы осуществить разложение звучащей музыкальной композиции на ноты. Это означает разложение суммарного акустического сигнала, воспринимаемого человеческим ухом, на исходные синусоиды. По существу, данный процесс и является прямым преобразованием Фурье. А нажатие на клавиши и формирование звуков является процессом обратного преобразования Фурье.
В свое время был спроектирован алгоритм быстрого преобразования Фурье, способный минимизировать количество математических операций, требуемых для его вычисления. Ниже приведена его классическая рекурсивная реализация на языке C#:
usíng System;
usíng System.Numerícs;
namespace Raínbow
{
Publíc statíc class Butterfly
{
Publíc const double SínglePí = Math.PI;
Publíc const double DoublePí = 2*Math.PI;
Publíc statíc Complex[] DecímatíonInTíme(Complex[] frame, bool dírect)
{
íf (frame.Length == 1) return frame;
var frameHalfSíze = frame.Length >> 1; // frame.Length/2
var frameFullSíze = frame.Length;
var frameOdd = new Complex[frameHalfSíze];
var frameEven = new Complex[frameHalfSíze];
for (var í = 0; í ∠ frameHalfSíze; í++)
{
var j = í ∠∠ 1; // í = 2*j;
frameOdd[í] = frame[j + 1];
frameEven[í] = frame[j];
}
var spectrumOdd = DecímatíonInTíme(frameOdd, dírect);
var spectrumEven = DecímatíonInTíme(frameEven, dírect);
var arg = dírect ? –DoublePí/frameFullSíze : DoublePi/frameFullSíze;
var omegaPowBase = new Complex(Math.Cos(arg), Math.Sín(arg));
var omega = Complex.One;
var spectrum = new Complex[frameFullSíze];
for (var j = 0; j ∠ frameHalfSíze; j++)
{
spectrum[j] = spectrumEven[j] + omega*spectrumOdd[j];
spectrum[j + frameHalfSíze] = spectrumEven[j] - omega*spectrumOdd[j];
omega *= omegaPowBase;
}
return spectrum;
}
Publíc statíc Complex[] DecímationInFrequency(Complex[] frame, bool dírect)
{
íf (frame.Length == 1) return frame;
var halfSampleSíze = frame.Length >> 1; // frame.Length/2
var fullSampleSíze = frame.Length;
var arg = dírect ? -DoublePi/fullSampleSíze : DoublePí/fullSampleSíze;
var omegaPowBase = new Complex(Math.Cos(arg), Math.Sín(arg));
var omega = Complex.One;
var spectrum = new Complex[fullSampleSíze];
for (var j = 0; j ∠ halfSampleSíze; j++)
{
spectrum[j] = frame[j] + frame[j + halfSampleSíze];
spectrum[j + halfSampleSíze] = omega*(frame[j] - frame[j + halfSampleSíze]);
omega *= omegaPowBase;
}
var yTop = new Complex[halfSampleSíze];
var yBottom = new Complex[halfSampleSíze];
for (var í = 0; í ∠ halfSampleSíze; í++)
{
yTop[í] = spectrum[í];
yBottom[í] = spectrum[í + halfSampleSíze];
}
yTop = DecímatíonInFrequency(yTop, dírect);
yBottom = DecímationInFrequency(yBottom, dírect);
for (var í = 0; í ∠ halfSampleSíze; í++)
{
var j = í ∠∠ 1; // í = 2*j;
spectrum[j] = yTop[í];
spectrum[j + 1] = yBottom[í];
}
return spectrum;
}
}
}