Tengo un archivo .wav que tiene 2 tipos de sonidos: largo y corto. Lo que tengo que hacer es codificarlos como bits y escribirlos en un archivo binario.

Recibí el código de esto, así que responda: https://stackoverflow.com/a/53309191/25883331 y usándolo i Obtenga esta trama para mi archivo de entrada WAV:

frequencies

Como puede ver, hay partes más cortas y más anchas en la primera trama en cuanto a los sonidos más cortos y más largos en mi archivo.

Mi pregunta es ¿cómo puedo codificar cada uno de los sonidos como un bit? Al igual que tener cada sonido largo en el archivo representa un 1 y un sonido corto representa un 0.

Edición: Los 2 tipos de sonido difieren por cuánto tiempo juegan y por frecuencia también. El sonido más largo es también la frecuencia más baja y el sonido más corto también es una frecuencia más alta. Puede encontrar una muestra del archivo aquí: https://vocaroo.com/i/s0a1weof3i3f

2
csanonymus 27 jun. 2019 a las 16:49

1 respuesta

La mejor respuesta

La medición de la volumen de cada frecuencia al tomar el FFT de la señal es la forma más "científica" de hacerlo, pero la imagen de la señal en bruto indica que debería ser posible escapar mucho más fácil que eso.

Si toma una ventana deslizante (al menos tan ancha como 1 período de la frecuencia primaria del sonido (~ 300Hz)) y encuentra el valor máximo dentro de esa ventana, debería ser bastante fácil aplicar un umbral para determinar si el tono es jugando en un intervalo de tiempo dado o no. Aquí está un artículo rápido que encontré en las funciones de la ventana rodante.

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

window_size = sample_rate / primary_freq #minimum size window. could be larger.
rolling_max = np.max(rolling_window(wav_data, window_size),-1)
threshold_max = rolling_max > threshold # maybe about 1000ish based on your graph

Luego, simplemente determine la longitud de las ejecuciones de True en threshold_max. Nuevamente, tiraré de la comunidad desde esta respuesta que muestra una forma concisa de obtener la longitud de ejecución de una matriz (o otro iterable).

def runs_of_ones(bits):
  for bit, group in itertools.groupby(bits):
    if bit: yield sum(group)

run_lengths = list(runs_of_ones(threshold_max))

Los valores en run_lengths ahora deben ser la longitud de cada pulso "en" de sonido en # de muestras. Ahora debería ser relativamente sencillo para que pruebes cada valor si es largo o corto y escribir en un archivo.

1
Aaron 27 jun. 2019 a las 14:40