2011-12-14 61 views
10

esta es mi primera publicación en la pila. Hasta ahora, este sitio ha sido muy útil, pero soy un novato y necesito una explicación clara de mi problema, que está relacionado con el audio de cambio de tono en Python. Tengo instalados los módulos actuales: numpy, scipy, pygame y scikits "samplerate" api.Python: Cambiar el tono del archivo de audio

Mi objetivo es tomar un archivo estéreo y reproducirlo en un tono diferente en tan pocos pasos como sea posible. Actualmente, cargo el archivo en una matriz usando pygame.sndarray, luego aplico una conversión de frecuencia de muestreo usando scikits.samplerate.resample, luego convierto la salida a un objeto de sonido para reproducir usando pygame. El problema es que el audio basura sale de mis altavoces. Seguramente me faltan algunos pasos (además de no saber nada sobre matemáticas y audio).

Gracias.

import time, numpy, pygame.mixer, pygame.sndarray 
from scikits.samplerate import resample 

pygame.mixer.init(44100,-16,2,4096) 

# choose a file and make a sound object 
sound_file = "tone.wav" 
sound = pygame.mixer.Sound(sound_file) 

# load the sound into an array 
snd_array = pygame.sndarray.array(sound) 

# resample. args: (target array, ratio, mode), outputs ratio * target array. 
# this outputs a bunch of garbage and I don't know why. 
snd_resample = resample(snd_array, 1.5, "sinc_fastest") 

# take the resampled array, make it an object and stop playing after 2 seconds. 
snd_out = pygame.sndarray.make_sound(snd_resample) 
snd_out.play() 
time.sleep(2) 

Respuesta

10

Su problema es que pygame trabaja con numpy.int16 matrices, pero la llamada a resample devolver una matriz numpy.float32:

>>> snd_array.dtype 
dtype('int16') 
>>> snd_resample.dtype 
dtype('float32') 

puede convertir resample resultado a numpy.int16 usando astype:

>>> snd_resample = resample(snd_array, 1.5, "sinc_fastest").astype(snd_array.dtype) 

Con esta modificación, la secuencia de comandos de Python reproduce el archivo de tone.wav muy bien, en un tono más bajo y una velocidad más baja.

+0

Oh hombre, no sé cómo agradecerte. No, espera, sí, puedo enviarte dinero de cerveza a través de PayPal si aceptas mi oferta. Tengo innumerables horas buscando una solución. Esto es fantástico. – hilmers

+1

Me alegro de verte como mi respuesta :) No tienes que ofrecerme nada, tu pregunta fue interesante y también he aprendido algunas cosas con ella. – kasyc

+0

¿Sería posible guardar el objeto pygame.micer.Sound modificado como un archivo de sonido en lugar de reproducirlo? –

0

Lo más probable es la scikits.samplerate.resample está "pensando" el audio está en otro formato de 16 bits estéreo. Consulte la documentación en scikits.samplerate sobre dónde seleccionar el formato de audio correcto en su matriz: Si se remuestreó el audio de 16 bits tratándolo como basura de 8 bits, lo que saldrá a la luz.

3

Probablemente su mejor opción sea utilizar python audiere.

Aquí hay un enlace, lo usé para hacer el mismo tipo de cosas, es muy fácil, solo lea toda la documentación.

http://audiere.sourceforge.net/home.php

+0

Gracias, Audiere fue mi primera opción, pero no pude hacerlo _make_ sin errores. No soy demasiado brillante con esto, así que tengo que ir con qué trabajo dadas mis habilidades limitadas. – hilmers

+0

Esto se ve bien, ¿funciona para python 2.7? Parece ser para Python 2.2 –

0

De la documentación scikits.samplerate.resample:

Si la entrada tiene rango 1, que se utilizan todos los datos, y se supone que son de una señal mono. Si rank es 2, se supondrá que el número de columnas es el número de canales.

Así que creo que lo que hay que hacer es algo como esto para pasar los datos estéreo a resample en el formato que espera:

snd_array = snd_array.reshape((-1,2)) 

snd_resample = resample(snd_array, 1.5, "sinc_fastest") 

snd_resample = snd_resample.reshape(-1) # Flatten it out again 
+0

Gracias. Intenté tu sugerencia, pero sale la misma salida. – hilmers

Cuestiones relacionadas