Математический анализ звукового образца (в виде массива чисел)

Мне нужно найти частоту выборки, хранящуюся (в vb) в виде массива байтов. Образец представляет собой синусоиду, известная частота, поэтому я могу проверить), но числа немного странные, а мои математические способности слабы. Полный диапазон значений 0-255. 99% чисел находятся в диапазоне от 235 до 245, но есть некоторые выбросы до 0 и 1 и до 255 в оставшемся 1%. Как мне нормализовать это, чтобы удалить выбросы (вычисление интервала 235-245, поскольку он может меняться для разных выборок), и как мне затем вычислить пересечение нуля, чтобы получить частоту? Извините, если это описание является мусором!


person David Shields    schedule 17.09.2008    source источник
comment
не мусор. хороший вопрос на самом деле.   -  person Purfideas    schedule 18.09.2008
comment
Возможно, вы захотите изменить заголовок на массив чисел   -  person Bob Cross    schedule 25.09.2008


Ответы (7)


БПФ, вероятно, лучший ответ, но если вы действительно хотите сделать это своим методом, попробуйте следующее:

Чтобы нормализовать, сначала сделайте гистограмму, чтобы подсчитать, сколько вхождений каждого значения от 0 до 255. Затем выбросьте X процентов значений с каждого конца, например:

for (i=lower=0;i< N*(X/100); lower++)
  i+=count[lower];
//repeat in other direction for upper

Теперь нормализуйте с

A[i] = 255*(A[i]-lower)/(upper-lower)-128

Отбросьте результаты за пределами диапазона -128..127.

Теперь вы можете считать нулевые пересечения. Чтобы убедиться, что вас не обманывает шум, вы можете отслеживать наклон в нескольких последних точках и подсчитывать пересечения только тогда, когда средний уклон идет в правильном направлении.

person AShelly    schedule 17.09.2008

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

Кстати, очень похожие проблемы уже задавались здесь раньше - вы можете поискать и эти ответы.

person Tyler    schedule 17.09.2008

Используйте преобразование Фурье, оно гораздо менее чувствительно к шуму, чем подсчет пересечений нуля.

Изменить: @WaveyDavey

Я нашел библиотеку F# для выполнения БПФ: отсюда

Как оказалось, лучшей бесплатной реализацией, которую я нашел для пользователей F#, по-прежнему является фантастическая библиотека FFTW. На их сайте есть предварительно скомпилированная Windows DLL. Я написал минимальные привязки, которые обеспечивают потокобезопасный доступ к FFTW из F# как с гуру, так и с простыми интерфейсами. Производительность отличная, 32-битная Windows XP Pro всего на 35% медленнее, чем 64-битная Linux.

Теперь я уверен, что вы можете вызвать библиотеку F# из VB.net, C# и т. д., которая должна быть в их документах.

person Purfideas    schedule 17.09.2008
comment
Любые указатели для noob для выполнения DFT/FFT в VB из массива байтов? - person David Shields; 18.09.2008
comment
Если документы неясны, я бы просто задал вопрос с тегом .net, как вызвать F # lib из VB? - person Purfideas; 18.09.2008

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

x[n] = A*sin(f*n + phi) + B + N[n]

где N[n] — шум «сбоев», от которого вы хотите избавиться.

Если сбои имеют длину в одну выборку, вы можете удалить их с помощью медианного фильтра, который должен быть больше, чем длина сбоя. С обеих сторон глюк. Глюки длины 1, значит, вам хватит медианы 3 сэмплов длины.

y[n] = median3(x[n])

Медиана вычисляется так: возьмите образцы x, которые вы хотите отфильтровать (x[n-1],x[n],x[n+1]), отсортируйте их, и ваш результат будет средним.

Теперь, когда шумовой сигнал отсутствует, избавьтесь от постоянного сигнала. Я понимаю, что буфер имеет ограниченную и известную длину, поэтому вы можете просто вычислить среднее значение всего буфера. Вычтите это.

Теперь у вас есть единственный синусовый сигнал. Теперь вы можете вычислить основную частоту, подсчитав пересечение нуля. Подсчитайте количество выборок выше 0, в которых предыдущая выборка была ниже 0. Период - это общее количество выборок вашего буфера, деленное на это, а частота - это противоположность (1/x) периода.

person cjanssen    schedule 17.09.2008

Хотя я бы согласился с большинством и сказал, что кажется, что вам нужно решение fft (алгоритм fft довольно быстр), если fft не является ответом по какой-либо причине, вы можете попытаться подогнать синусоиду к данным, используя программа подгонки и считывание подобранной частоты.

Используя Fityk, вы можете загрузить данные и подогнать их к a*sin(b*x-c), где 2*pi/b даст вам Частота после установки.

Fityk можно использовать из графического интерфейса, из командной строки для сценариев и имеет C++ API, поэтому его можно напрямую включать в ваши программы.

person Brendan    schedule 17.09.2008

Я погуглил «базовый ффт». Visual Basic FFT Ваш вопрос кричит о БПФ, но будьте осторожны, используя БПФ, не понимая даже немного о DSP может привести к результатам, которые вы не понимаете или не знаете, откуда они берутся.

person basszero    schedule 17.09.2008

загрузите анализатор частоты по адресу http://www.relisoft.com/Freeware/index.htm и запустите его и посмотрите на код.

person Community    schedule 18.09.2008