2016-08-19 1 views
0

В настоящее время я потерял попытку выяснить, как реализовать эквивалентную версию функции MATLAB hilbert() в C++. Я очень новичок в обработке сигналов, но, в конечном счете, я хотел бы выяснить способ фазового сдвига любого заданного сигнала на 90 градусов. Я пытался следовать методу, предложенному в this question on MATLAB central, который, по-видимому, работает на основе тестов с использованием GNU Octave.Вычислительный аналитический сигнал с использованием FFT в C++

У меня есть то, что я считаю рабочим выполнением как БПФ, так и обратного БПФ, и я попытался реализовать метод, описанный в ответе this post, чтобы вычислить аналитический сигнал. Я попытался сделать это, применив БПФ, установив верхнюю половину массива в ноль, а затем применив обратный БПФ, но, основываясь на графиках, которые я сделал на выходе из теста, должна быть проблема с тем, как я осуществил поиск аналитического сигнала.

Что было бы подходящим способом реализации функции hilbert() от MATLAB в C++ с учетом рабочей реализации БПФ и обратного БПФ? Есть ли лучший способ добиться сдвига фазы на 90 градусов?

+0

Я не уверен, о функции Гильберта в MATLAB, но учитывая комплексный коэффициент в вашем FFT 'а + я * b', вы можете выполнить фазовый сдвиг 90 градусов, заменив его на' -b + я * a' – jodag

+1

Также, если у вас есть MATLAB, вы можете набрать 'edit hilbert', чтобы увидеть реализацию, которую они используют. Он выглядит довольно прямо, как только вы выполняете FFT и обратный FFT. – jodag

+0

@jodag К сожалению, замена 'a + i * b' на' -b + i * a', похоже, не имеет желаемого эффекта. Может быть, реализация БПФ или обратного БПФ я использую неправильно? На самом деле я возвращаю те же данные до применения FFT. Кроме того, у меня нет MATLAB. – fakedad

ответ

3

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

signal hilbert(const signal &x) 
{ 
    int limit1, limit2; 
    signal xfreq = fft(x); 
    if (x.numel % 2 == 0) { 
     limit1 = x.numel/2; 
     limit2 = limit1 + 1; 
    } else { 
     limit1 = (x.numel + 1)/2; 
     limit2 = limit1; 
    } 
    // multiply the first half by 2 (except the first element) 
    for (int i = 1; i < limit1; ++i) { 
     xfreq[i].real *= 2; 
     xfreq[i].imag *= 2; 
    } 
    for (int i = limit2; i < x.numel; ++i) { 
     xfreq[i].real = 0; 
     xfreq[i].imag = 0; 
    } 
    return ifft(xfreq); 
} 

Редактировать: Забыл установить вторую половину в нули. Edit2: Исправлена ​​логическая ошибка. Я закодировал следующее в MATLAB, которое соответствует гильберту.

function h = hil(x) 
    n = numel(x); 
    if (mod(n,2) == 0) 
     limit1 = n/2; 
     limit2 = limit1 + 2; 
    else 
     limit1 = (n+1)/2; 
     limit2 = limit1+1; 
    end 

    xfreq = fft(x); 

    for i = 2:limit1 
     xfreq(i) = xfreq(i)*2; 
    end 
    for i = limit2:n 
     xfreq(i) = 0; 
    end 

    h = ifft(xfreq); 
end 
+4

Вот как это сделать: реализовать алгоритм в стиле C в Matlab, проверить, что вы получаете тот же ответ, что и встроенная функция, затем переносите его на фактический C (или Rust или что-то еще). –

+0

По какой-то причине у меня возникли проблемы с тем, чтобы это работало после переключения на использование FFTW. Какие-либо предложения? – fakedad

+0

Если вы работали с использованием предыдущей реализации FFT, вам, вероятно, следует создать простой случай и посмотреть, как FFTW отличается от предыдущей реализации. MATLAB использует FFTW на сервере, поэтому я уверен, что вы можете заставить его работать с помощью FFTW. – jodag