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

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

Я следил за уравнениями Википедии в качестве руководства о том, как это сделать, и мой код, кажется, соответствует уравнения, данные (на мой взгляд) с учетом этого кода:

ДПФ:

for (int k = 0; k < frequency_domain_magnitude.length; k++) {
    for (int n = 0; n < data.length; n++) {
        double val = (-2.0 * Math.PI * n * k / data.length);
        freq_imag[k] += data[n] * -Math.sin(val);
        freq_real[k] += data[n] * Math.cos(val);
    }
    frequency_domain_magnitude[k] = Math.sqrt(freq_imag[k] * freq_imag[k] + freq_real[k] * freq_real[k]);
}

IDFT:

for (int n = 0; n < data.length; n++) {
    doubleValue[n] = 0;
    for (int k = 0; k < freqUsed.length; k++) {
        double val = (2.0 * Math.PI * n * k / data.length);
        doubleValue[n] = freq_real[k] * Math.cos(val) - freq_imag[k] * Math.sin(val);
    }
    time_real[n] = (byte) (Math.floor(doubleValue[n]));
}

Может ли кто-нибудь помочь мне определить, в чем проблема?

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


person Matt    schedule 21.08.2011    source источник
comment
На мой взгляд, первый вопрос был на самом деле более ясным, и в любом случае, если вы недовольны формулировкой вопроса, отредактируйте, а не дублируйте.   -  person Stu Mackellar    schedule 22.08.2011
comment
Пожалуйста, задавайте подобные вопросы на странице Signal Processing(dsp.stackexchange.com)! :-)   -  person Peter K.    schedule 23.08.2011


Ответы (2)


Как минимум три вещи неверны:

Во-первых, вы не суммируете все частоты в своем IDFT. Это большая, большая проблема, в основном эквивалентная получению IDFT только одной дискретной частоты вместо данных всей частотной области. Во-вторых, у вас перевернута табличка в вашем IDFT.

Измените строку 5 фрагмента 2 на

    doubleValue[n] += freq_real[k] * Math.cos(val) + freq_imag[k] * Math.sin(val);

и убедитесь, что вы инициализируете doubleValue нулями.

В-третьих, вы захотите добавить шаг нормализации;

Измените строку 7 фрагмента 2 на

time_real[n] = (byte) (Math.floor(doubleValue[n] / data.length))

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

Это также может помочь получить чью-то реализацию ДПФ и IDFT и сравнить поведение с вашей реализацией на некоторых очень простых входных данных, чтобы отловить другие ошибки. Поскольку ДПФ представляет собой линейную алгебру, вы можете получить не совсем правильное решение, но все же увидеть качественно кажущиеся удовлетворительными ответы.

person ellisbben    schedule 22.08.2011

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

Однако, если вы реализуете DFT и IDFT правильно и полностью, данные во временной области могут быть воссозданы в пределах этой числовой ошибки. Возможно, что пара БПФ/ОБПФ будет давать меньшие числовые ошибки, чем пара ДПФ/ИДПФ.

Если вы отбросите какие-либо термины (сложные мнимые термины, частотные бины или что-то еще), результат будет дальше от оригинала. Например, если ваш Frequency_domain_magnitude.length или ваш freqUsed.length меньше, чем длина ваших данных, вы выбросите термины (если только вы не используете немного другой алгоритм и/или коэффициенты масштабирования).

В вашем IDFT также есть как минимум 1 или 2 фатальные опечатки, как упоминал @ellisbben.

person hotpaw2    schedule 22.08.2011