audioop — Manipula datos de audio sin procesar


El módulo audioop contiene algunas operaciones útiles sobre fragmentos de sonido. Opera en fragmentos de sonido que consisten en muestras de enteros de 8, 16, 24, o 32 bits, guardados en objetos parecidos a bytes. Todos los elementos escalares son enteros, a menos que se especifique lo contrario.

Distinto en la versión 3.4: La compatibilidad para muestras de 24-bit fue añadida. Todas las funciones ahora aceptan cualquier bytes-like object. La entrada de cadenas de caracteres ahora resulta en un error inmediato.

Este módulo proporciona compatibilidad con las codificaciones a-LAW, u-LAW e Intel/DVI ADPCM.

Algunas de las operaciones más complicadas sólo toman muestras de 16-bit, si no, el tamaño de la entrada (en bytes) siempre es un parámetro de la operación.

El módulo define las siguientes variables y funciones:

exception audioop.error

Esta excepción es lanzada en todos los errores, tal como números desconocidos de bytes por entrada, etc.

audioop.add(fragment1, fragment2, width)

Retorna un fragmento que es la adición de dos entradas pasadas como parámetros. width es la longitud de la muestra en bytes, o 1, 2, 3, o 4. Ambos fragmentos deben tener la misma longitud. Las muestras son truncadas en caso de desbordamiento.

audioop.adpcm2lin(adpcmfragment, width, state)

Decodifica un fragmento codificado con Intel/DVI ADPCM en un fragmento lineal. Véase la descripción de lin2adpcm() por detalles sobre la codificación ADPCM. Retorna una tupla (sample, newstate) donde la entrada tiene la longitud especificada en width.

audioop.alaw2lin(fragment, width)

Convierte los fragmentos de sonido codificados con a-LAW en fragmentos de sonido linealmente codificados. La codificación a-LAW siempre usa muestras de 8 bits, por lo que width hace referencia sólo a la longitud de la entrada del fragmento de salida aquí.

audioop.avg(fragment, width)

Retorna el promedio de todas las muestras en el fragmento.

audioop.avgpp(fragment, width)

Retorna el promedio del valor de pico a pico de todas las muestras en el fragmento. No se hace ningún filtrado, por lo que la utilidad de esta rutina es cuestionable.

audioop.bias(fragment, width, bias)

Retorna un fragmento que es el fragmento original con un bias añadido a cada muestra. Las muestras se envuelven en caso de desbordamiento.

audioop.byteswap(fragment, width)

Intercambia los bytes («Byteswap») de todas las muestras en un fragmento y retorna el fragmento modificado. Convierte muestras big-endian en little-endian y viceversa.

Nuevo en la versión 3.4.

audioop.cross(fragment, width)

Retorna el número de cruces por 0 en el fragmento pasado como un argumento.

audioop.findfactor(fragment, reference)

Retorna un factor F tal que rms(add(fragment, mul(reference, -F))) sea mínimo, i.e., retorna el factor con el cual debes multiplicar la reference para hacerlo coincidir tanto como sea posible a fragment. Los fragmentos deben contener muestras de 2-byte.

El tiempo tomado por esta rutina es proporcional a len(fragment.

audioop.findfit(fragment, reference)

Intenta hacer coincidir reference tanto bien como sea posible a un fragment (que debe ser el fragmento más largo). Esto es (conceptualmente) hecho al tomar segmentos de fragment, usando findfactor() para computar la mejor coincidencia, y minimizando el resultado. Los fragmentos deben contener muestras de 2-byte. Retorna una tupla (offset, factor) donde offset (entero) es el offset en fragment donde la coincidencia más óptima empezó y factor es el (número flotante) factor según findfactor().

audioop.findmax(fragment, length)

Inspecciona fragment por un segmento de longitud length muestras (¡no bytes!) con la energía máxima, i.e., retorna i por el cual rms(fragment[i*2:(i+length)*2]) es máximo. Los fragmentos deben contener muestras de 2 bytes.

La rutina tarda proporcionalmente a len(fragment).

audioop.getsample(fragment, width, index)

Retorna el valor de la muestra index del fragmento.

audioop.lin2adpcm(fragment, width, state)

Convierte las muestras en codificaciones Intel/DVI ADPCM de 4 bits. La codificación ADPCM es un esquema de codificación adaptativo a través del cual cada número de 4 bits es la diferencia entre una muestra y la siguiente, dividido por un paso (inconsistente). El algoritmo de Intel/DVI ADPCM ha sido seleccionado para su uso por el IMA, por lo que bien puede convertirse en un estándar.

state es una tupla que contiene el estado del codificador. El codificador retorna una tupla (adpcmfrag, newstate), y el newstate debe pasarse a la siguiente llamada de lin2adpcm(). En la llamada inicial, se puede pasar None como estado. adpcmfrag es el fragmento codificado ADPCM empaquetado 2 valores de 4 bits por byte.

audioop.lin2alaw(fragment, width)

Convierte las muestras en el fragmento de audio en una codificación a-LAW y los retorna como un objeto de bytes. a-LAW es un formato de codificación de audio a través del cual obtienes un rango dinámico de cerca de 13 bits usando sólo muestras de 8 bits. Es usado por el hardware de audio Sun, entre otros.

audioop.lin2lin(fragment, width, newwidth)

Convierte muestras entre formatos de 1, 2, 3, y 4 bytes.

Nota

En algunos formatos de audio, como archivos .WAV, las entradas de 16, 24, y 32 bits tienen signo, pero las entradas de 8 bits no tienen signo. Por lo que cuando se convierta en entradas de 8 bits para estas entradas, también necesitas añadir 128 al resultado:

new_frames = audioop.lin2lin(frames, old_width, 1)
new_frames = audioop.bias(new_frames, 1, 128)

Lo mismo, al revés, tiene que ser aplicado cuando se convierta muestras de 8 bits en muestras de 16, 24, o 32 bits.

audioop.lin2ulaw(fragment, width)

Convierte muestras en el fragmento de audio en codificaciones u-LAW y lo retorna como un objeto de bytes. u-LAW es un formato de codificación de audio a través del cual obtienes un rango dinámico de cerca de 14 bits usando sólo muestras de 8 bits. Es usado por el hardware de audio Sun, entre otros.

audioop.max(fragment, width)

Retorna el máximo de los valores absolutos de las entradas en un fragmento.

audioop.maxpp(fragment, width)

Retorna el valor de pico a pico máximo en el fragmento de sonido.

audioop.minmax(fragment, width)

Retorna una tupla que consiste de los valores mínimos y máximos de todas las entradas en el fragmento de sonido.

audioop.mul(fragment, width, factor)

Retorna un fragmento que tiene todas las entradas en el fragmento original multiplicado por el valor de punto flotante factor. Las muestras son truncadas en caso de desbordamiento.

audioop.ratecv(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])

Convierte el ratio de fotogramas del fragmento de entrada.

state es una tupla que contiene el estado del convertidor. El convertidor retorna una tupla (newfragment, newstate), y newstate debe ser pasado a la siguiente llamada de ratecv(). La llamada inicial debe pasar None como el estado.

Los argumentos weightA y weightB son parámetros para un filtro digital simple y sus valores por defecto son 1 y 0 respectivamente.

audioop.reverse(fragment, width)

Invierte las entradas en un fragmento y retorna el fragmento modificado.

audioop.rms(fragment, width)

Retorna la media cuadrática del fragmento, i.e. sqrt(sum(S_i^2)/n).

Este es una medida del poder en una señal de audio.

audioop.tomono(fragment, width, lfactor, rfactor)

Convierte un fragmento estéreo en una fragmento mono. El canal izquierdo es multiplicado por Ifactor y el derecho por rfactor antes de añadir los dos canales para dar una señal mono.

audioop.tostereo(fragment, width, lfactor, rfactor)

Genera un fragmento estéreo de un fragmento mono. Cada par de muestras en el fragmento estéreo son computados de la entrada mono, a través del cual las muestras del canal izquierdo son multiplicadas por Ifactor y del canal derecho por rfactor.

audioop.ulaw2lin(fragment, width)

Convierte los fragmentos de sonido en codificaciones u-LAW en fragmentos de sonidos linealmente codificados. Las codificaciones u-LAW siempre usan muestras de 8 bits, por lo que width hace referencia a la longitud de la muestra del fragmento de salida aquí.

Note que operaciones tales como mul() o max() no hacen distinción entre fragmentos mono y estéreo, i.e. todas las muestras son tratadas iguales. Si este es un problema, el fragmento estéreo debe ser dividido en dos fragmentos mono primero y recombinado después. Aquí hay un ejemplo de como hacerlo:

def mul_stereo(sample, width, lfactor, rfactor):
    lsample = audioop.tomono(sample, width, 1, 0)
    rsample = audioop.tomono(sample, width, 0, 1)
    lsample = audioop.mul(lsample, width, lfactor)
    rsample = audioop.mul(rsample, width, rfactor)
    lsample = audioop.tostereo(lsample, width, 1, 0)
    rsample = audioop.tostereo(rsample, width, 0, 1)
    return audioop.add(lsample, rsample, width)

Si usas el codificador ADPCM para construir paquetes de redes y quieres que tu protocolo no tenga estado (stateless) (i.e. para ser capaz de tolerar pérdida de paquetes) no sólo debes transmitir los datos pero también el estado. Note que debes enviar el estado inicial (initial) (el que pasas a lin2adpcm()) junto con el decodificador, no el estado final (como es retornado por el codificador). Si quieres usar un struct.Struct para almacenar el estado en binario puedes codificar el primer elemento (el valor predicho) en 16 bits y el segundo (el índice delta) en 8.

Los codificadores ADPCM nunca se han probado en contra de otros codificadores ADPCM, sólo contra ellos mismos. Bien puede ser que malinterpreté los estándares en cuyo caso ellos no serán interoperables con los estándares respectivos.

La rutinas find*() pueden parecer un poco raras a primera vista. Sirven principalmente para hacer echo de la cancelación. Una manera razonablemente rápida para hacerlo es coger la pieza más energética de la muestra de la salida, localizarla en la muestra de la entrada y substraer la muestra de la salida completa de la muestra de entrada:

def echocancel(outputdata, inputdata):
    pos = audioop.findmax(outputdata, 800)    # one tenth second
    out_test = outputdata[pos*2:]
    in_test = inputdata[pos*2:]
    ipos, factor = audioop.findfit(in_test, out_test)
    # Optional (for better cancellation):
    # factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
    #              out_test)
    prefill = '\0'*(pos+ipos)*2
    postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
    outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
    return audioop.add(inputdata, outputdata, 2)