Преобразование БПФ в ИКМ

У меня есть данные БПФ, 257 измерений, каждые 10 мс, 121 кадр, т.е. 1,21 сек. Я думаю, что первое измерение, вероятно, что-то еще, а остальные, я думаю, являются коэффициентами БПФ. Вероятно, это просто данные спектрограммы. Из комментария о данных БПФ к ним могли быть применены sqrt10 и нормализация среднего отклонения.

Оттуда я хочу вычислить некоторый сигнал PCM для 44,1 Гц, чтобы я мог воспроизвести звук. Я задал тот же вопрос более математически здесь, но, возможно, StackOverflow это лучшее место, потому что я действительно хочу реализовать это. Я также задал тот же вопрос о теории здесь, на DSP SE.

Как бы я это сделал? Может быть, мне нужна дополнительная информация (которую я должен как-то узнать) - какая? Может быть, эту недостающую информацию можно как-то разумно угадать?

Этот вопрос касается как теории, так и практической реализации. Реализация тривиальна, я думаю. Но конкретный пример на каком-то языке был бы полезен для понимания теории. Может быть, С++ с FFTW? Я пропустил документы FFTW, но не понимаю всей терминологии и некоторых предпосылок, например. здесь. Почему именно от сложного к реальному или наоборот, я хочу только реальное к реальному. Что это за РЕДФТ? Что такое DCT, DFT, DST? FFTW_HC2R?

Я прочитал все данные БПФ, т.е. 121 * 257 чисел с плавающей запятой, в вектор freq_bins.

std::vector<float32_t> freq_bins; // FFT data
int freq_bins_count = 257;
size_t len = 121;

std::vector<float32_t> pcm; // output, PCM data

int N = freq_bins_count;
std::vector<double> out(N), orig_in(N);

// inspiration: https://stackoverflow.com/questions/2459295/invertible-stft-and-istft-in-python/6891772#6891772
for(int f = 0; f < len; ++f) {
    size_t pos = freq_bins_count * f;
    for(int i = 0; i < N; ++i)
        out[i] = pow(freq_bins[pos + i] + offset, 10);  // fft was sqrt10 + mvn
    fftw_plan q = fftw_plan_r2r_1d(N, &out[0], &orig_in[0], FFTW_REDFT00, FFTW_ESTIMATE);
    fftw_execute(q);
    fftw_destroy_plan(q);

    // naive overlap-and-add
    auto start_frame = size_t(f * dt * sampleRate);
    for(int i = 0; i < N; ++i) {
        sample_t frame = orig_in[i] * scale / (2 * (N - 1));
        size_t idx = start_frame + i;
        while(idx >= pcm.size())
            pcm.push_back(0);
        pcm[idx] += frame;
    }
}

Но это неправильно, я думаю. Я просто выбрасываю мусор.

Связанным может быть этот вопрос. Или это.


person Albert    schedule 15.08.2015    source источник
comment
Учитывая, что вы говорите о реализации (а не о теории), а также упоминаете библиотеки в комментариях ниже, вы должны пометить этот вопрос языком, который вы собираетесь использовать...   -  person Oliver Charlesworth    schedule 16.08.2015
comment
@OliverCharlesworth: Это касается и того, и другого, или даже больше теории. Реализация тривиальна, я думаю. Но конкретный пример на каком-то языке был бы полезен для понимания теории. Может быть, С++ с FFTW? Я пропустил документы FFTW, но не понимаю всей терминологии и некоторых предпосылок, например. здесь. Почему именно от сложного к реальному или наоборот, я хочу только реальное к реальному. Что это за РЕДФТ? Что такое DCT, DFT, DST? И Т. Д.   -  person Albert    schedule 16.08.2015
comment
Если вопрос касается теории, то, вероятно, лучше всего подойдет dsp.stackexchange.com.   -  person Oliver Charlesworth    schedule 16.08.2015


Ответы (2)


Если данные, которые у вас есть, реальны, то данные, которые у вас есть, скорее всего, являются данными спектрограммы, и если данные, которые вы получаете, сложны, тогда у вас, скорее всего, есть необработанное кратковременное преобразование Фурье ( STFT) данные (см. диаграмму в этом сообщении чтобы увидеть, как создаются данные STFT/спектрограммы). Данные спектрограммы создаются путем возведения в квадрат величины данных STFT и, таким образом, необратимы, потому что вся информация о фазе в аудиосигнале была потеряна, но необработанные данные STFT обратимы, поэтому, если это то, что у вас есть, вы можете поискать библиотеку, выполняющую обратную функцию STFT, и попробуйте ее использовать.

Что касается вопроса о том, что представляют собой размеры БПФ в ваших данных, я считаю, что 257 точек данных, которые вы получаете каждые 10 мс, являются результатом 512-точечного БПФ, используемого в процессе STFT. Первая выборка - это частота 0 Гц, а остальные из 256 точек данных составляет половину спектра БПФ (другая половина данных БПФ была отброшена, потому что входные данные для БПФ реальны, и поэтому одна половина данных БПФ представляет собой просто комплексно-сопряженное значение другой половины).

В дополнение к этому, я хотел бы отметить, что только потому, что вы получаете данные БПФ каждые 10 мс 121 раз, это не означает, что аудиосигнал равен 1,21 с. STFT обычно создается с использованием перекрывающихся окон, поэтому ваш аудиосигнал может быть короче. чем 1,21 с.

person KillaKem    schedule 16.08.2015
comment
У меня есть только те 257 измерений. Даже если я не могу воспроизвести истинный сигнал, могу ли я каким-то образом воспроизвести какой-либо сигнал, который будет давать те же данные БПФ? - person Albert; 16.08.2015
comment
Проще говоря, если у вас есть необработанные данные STFT (т. е. данные о частоте, у вас есть матрица комплексных чисел, представляющая звук), вы можете инвертировать данные, чтобы вернуть аудиосигнал, но если у вас есть данные спектрограммы (т. е. данные о частоте, которые вы иметь матрицу действительных чисел, представляющих данные), тогда вы не сможете инвертировать ее или даже получить сигнал, который звучит близко к исходному сигналу, потому что вся информация о фазе была отброшена. Подробнее об инвертировании STFT см. здесь: eeweb.poly.edu/iselesni/EL713/STFT/stft_inverse.pdf - person KillaKem; 16.08.2015
comment
У меня просто есть эти 257 измерений реальных данных (или, может быть, это 128 сложных + 1 реальное? но они все выглядят одинаково, поэтому я думаю, что 257 реальных имеет больше смысла). Итак, я предполагаю, что это спектрограмма (как именно вы получаете ее из необработанного STFT? sqrt (abs (fft)) или что-то в этом роде?). Могу ли я каким-то образом воссоздать некоторые фазовые данные? Если я просто предположу 0 или что-то в этом роде, получу ли я ту же спектрограмму? Если нет, могу ли я как-то угадать фазовые данные, чтобы получить такую ​​же спектрограмму? Или вы хотите сказать, что два звука с одинаковой спектрограммой могут звучать совершенно по-разному? Это почему? Это очень контринтуитивно для меня. - person Albert; 16.08.2015
comment
Нет, вы не можете угадать фазовые данные, и если вы установите фазу на 0 для всех выборок в спектрограмме, вы, скорее всего, получите мусорный звук после выполнения обратного STFT; звук не будет звучать как исходный звук, даже если спектрограмма, созданная обоими, будет одинаковой. Вы только надеетесь восстановить звук, если данные, которые у вас есть, являются полными данными STFT, а не только спектрограммой. - person KillaKem; 27.08.2015
comment
Я также хотел бы указать вам, что только потому, что 2D-массив, который у вас есть, выглядит реальным, потому что все элементы в нем являются реальными числами, не обязательно означает, что данные, представленные им, реальны. Некоторые библиотеки (например, FFTW) есть варианты для представления сложных массивов данных как реальных, сначала перечисляя реальную часть массива, а затем перечисляя мнимую часть массива, например, см. это: fftw.org/doc/The-Halfcomplex_002dformat-DFT.html - person KillaKem; 27.08.2015

Вы просто протолкнете эти данные через обратное преобразование Фурье. Все библиотеки БПФ предлагают функции прямого и обратного преобразования.

person datenwolf    schedule 15.08.2015
comment
Не могли бы вы дать дополнительную информацию? В настоящее время я не использую такую ​​библиотеку. Какой из них я бы использовал и как именно я мог бы получить свои данные PCM? Может быть, вы можете привести пример кода для какой-то библиотеки? - person Albert; 15.08.2015