2008-09-17 8 views
10

Necesito encontrar la frecuencia de una muestra, almacenada (en vb) como una matriz de bytes. La muestra es una onda sinusoidal, frecuencia conocida, así que puedo verificar), pero los números son un poco extraños, y mi matemática-foo es débil. Rango completo de valores 0-255. El 99% de los números están en el rango de 235 a 245, pero hay algunos valores atípicos hasta 0 y 1, y hasta 255 en el 1% restante. ¿Cómo normalizo esto para eliminar valores atípicos (calculando el intervalo 235-245 ya que puede cambiar con diferentes muestras) y cómo puedo calcular cero cruces para obtener la frecuencia? Disculpa si esta descripción es basura.Análisis matemático de una muestra de sonido (como una matriz de números)

+0

no basura. buena pregunta en realidad. – Purfideas

+0

Es posible que desee cambiar el título a "como una matriz de números" –

Respuesta

6

La FFT es probablemente la mejor respuesta, pero si realmente quiere hacerlo por su método, intente esto:

para normalizar, en primer lugar hacer un histograma para contar el número de ocurrencias de cada valor de 0 a 255 . a continuación, tirar a cabo un X por ciento de los valores de cada extremo con algo como:

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

Ahora normalizar con

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

Bote resultados fuera del rango -128..127.

Ahora puede contar los cruces por cero. Para asegurarse de que no se deje engañar por el ruido, es posible que desee realizar un seguimiento de la pendiente en los últimos puntos, y solo contar los cruces cuando la pendiente promedio va por el camino correcto.

3

Usar la transformada de Fourier, es mucho más ruido insensibles que contar los cruces por cero

Editar: @WaveyDavey

encontré un # biblioteca F para hacer una FFT: From here

Como resulta fuera, la mejor implementación gratuita que he encontrado para los usuarios de F # hasta ahora sigue siendo la fantástica biblioteca FFTW. Su sitio tiene una DLL de Windows precompilada . He escrito enlaces mínimos que permiten acceso a hilos a FFTW desde F #, con interfaz simple y guru. El rendimiento es excelente, 32 bits Windows XP Pro es solo hasta 35% más lento que Linux de 64 bits.

Ahora estoy seguro de que puede llamar F # lib de VB.net, C#, etc, que debe estar en sus documentos

+0

¿Alguna sugerencia para novato para hacer DFT/FFT en VB desde una matriz de bytes? –

+0

Si los documentos no están claros, me gustaría hacer una pregunta etiquetada .net, "¿cómo llamar a F # lib desde VB?" – Purfideas

5

El método estándar para atacar este problema es considerar un bloque de datos, es de esperar al menos el doble de la frecuencia real (tomar más datos no es malo, por lo que es bueno sobreestimar un poco), luego tome el FFT y suponga que la frecuencia corresponde al número más grande en el espectro de FFT resultante.

Por cierto, aquí se han planteado problemas muy similares; también podría buscar esas respuestas.

0

Busqué en Google para "basic fft". Visual Basic FFT Su pregunta grita FFT, pero tenga cuidado, usar FFT sin entender siquiera un poco acerca de DSP puede conducir a resultados que usted no entiende o no sabe de dónde vienen.

1

Si entendí bien de su descripción, lo que tiene es una señal que es una combinación de un seno más una constante más algunos fallos aleatorios. Diga, como

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

donde N [n] es el ruido "fallo" del que desea deshacerse.

Si los problemas técnicos son de una muestra de longitud, puede eliminarlos utilizando un filtro mediano que debe ser mayor que la longitud de falla. En ambos lados del problema. Glitches de longitud 1 significa que tendrá suficiente con una mediana de 3 muestras de longitud.

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

La mediana se calcula así: Tome las muestras de x que desea filtrar (x [n-1], x [n], x [n + 1]), clasificarlos, y su salida es el del medio.

Ahora que la señal de ruido está ausente, elimine la señal constante. Entiendo que el buffer es de una longitud limitada y conocida, por lo que puede calcular la media de todo el buffer. Substraerlo.

Ahora tiene su señal seno única. Ahora puede calcular la frecuencia fundamental contando los cruces por cero. Cuente la cantidad de muestras por encima de 0 en que la muestra anterior estaba por debajo de 0. El período es la cantidad total de muestras de su memoria intermedia divididas por esta, y la frecuencia es la opuesta (1/x) del período.

1

Aunque me quedaría con la mayoría y diría que parece que lo que quieres es una solución fft (el algoritmo fft es bastante rápido), si fft no es la respuesta por la razón que sea, intenta ajustar una curva sinusoidal a los datos usando un programa de adaptación y leyendo la frecuencia ajustada.

Usando Fityk, puede cargar los datos, y ajustarlos al a*sin(b*x-c) donde 2*pi/b le dará la frecuencia después del ajuste.

Fityk se puede utilizar desde una interfaz gráfica de usuario, desde una línea de comandos para scripts y tiene una API de C++, por lo que podría incluirse directamente en sus programas.

Cuestiones relacionadas