Мне нужно найти частоту выборки, хранящуюся (в vb) в виде массива байтов. Образец представляет собой синусоиду, известная частота, поэтому я могу проверить), но числа немного странные, а мои математические способности слабы. Полный диапазон значений 0-255. 99% чисел находятся в диапазоне от 235 до 245, но есть некоторые выбросы до 0 и 1 и до 255 в оставшемся 1%. Как мне нормализовать это, чтобы удалить выбросы (вычисление интервала 235-245, поскольку он может меняться для разных выборок), и как мне затем вычислить пересечение нуля, чтобы получить частоту? Извините, если это описание является мусором!
Математический анализ звукового образца (в виде массива чисел)
Ответы (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.
Теперь вы можете считать нулевые пересечения. Чтобы убедиться, что вас не обманывает шум, вы можете отслеживать наклон в нескольких последних точках и подсчитывать пересечения только тогда, когда средний уклон идет в правильном направлении.
Стандартный метод решения этой проблемы состоит в том, чтобы рассмотреть один блок данных, желательно, по крайней мере, в два раза превышающий фактическую частоту (брать больше данных неплохо, так что лучше немного переоценить), а затем взять БПФ и предположить, что частота соответствует наибольшему числу в результирующем спектре БПФ.
Кстати, очень похожие проблемы уже задавались здесь раньше - вы можете поискать и эти ответы.
Используйте преобразование Фурье, оно гораздо менее чувствительно к шуму, чем подсчет пересечений нуля.
Изменить: @WaveyDavey
Я нашел библиотеку F# для выполнения БПФ: отсюда
Как оказалось, лучшей бесплатной реализацией, которую я нашел для пользователей F#, по-прежнему является фантастическая библиотека FFTW. На их сайте есть предварительно скомпилированная Windows DLL. Я написал минимальные привязки, которые обеспечивают потокобезопасный доступ к FFTW из F# как с гуру, так и с простыми интерфейсами. Производительность отличная, 32-битная Windows XP Pro всего на 35% медленнее, чем 64-битная Linux.
Теперь я уверен, что вы можете вызвать библиотеку F# из VB.net, C# и т. д., которая должна быть в их документах.
Если я правильно понял из вашего описания, то у вас есть сигнал, представляющий собой комбинацию синуса плюс константа плюс некоторые случайные глюки. Скажи, как
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) периода.
Хотя я бы согласился с большинством и сказал, что кажется, что вам нужно решение fft (алгоритм fft довольно быстр), если fft не является ответом по какой-либо причине, вы можете попытаться подогнать синусоиду к данным, используя программа подгонки и считывание подобранной частоты.
Используя Fityk, вы можете загрузить данные и подогнать их к a*sin(b*x-c)
, где 2*pi/b
даст вам Частота после установки.
Fityk можно использовать из графического интерфейса, из командной строки для сценариев и имеет C++ API, поэтому его можно напрямую включать в ваши программы.
Я погуглил «базовый ффт». Visual Basic FFT Ваш вопрос кричит о БПФ, но будьте осторожны, используя БПФ, не понимая даже немного о DSP может привести к результатам, которые вы не понимаете или не знаете, откуда они берутся.
загрузите анализатор частоты по адресу http://www.relisoft.com/Freeware/index.htm и запустите его и посмотрите на код.