Grabación de varios micrófonos por USB

Cuando empezamos con Podcast Z: Python, Sistemas y Seguridad Pablo y yo grabábamos en persona conectando dos micros USB al ordenador. El siguiente programa Python permite grabar un número arbitrario de micrófonos USB (si usamos un HUB USB pueden ser muchos):

 #!/usr/bin/python

 # (c) 2011 jcea@jcea.es - http://www.jcea.es/
 # Código liberado como Dominio Público.
 # Haz con él lo que quieras.

 import time, sys, Queue, threading, wave, ossaudiodev

 def reader(audio, q) :
   s = ossaudiodev.open(audio, "r")
   # Strict
   s.setparameters(ossaudiodev.AFMT_S16_LE, 2, 16000, True)
   while True :
     samples = s.read(16384)
     q.put(samples)

 def writer(fichero, q) :
   w = wave.open(fichero, "wb")
   w.setnchannels(2)
   w.setsampwidth(2)
   w.setframerate(16000)
   while True :
       samples = q.get()
       w.writeframes(samples)

 ts=time.strftime("%Y%m%d%H%M%S")
 for i,j in enumerate(sys.argv[1:]):
   print "Lanzando hilos para %s" %(j)
   q = Queue.Queue()
   t = threading.Thread(target=reader, args=(j, q))
   t.setDaemon(True)
   t.start()
   t = threading.Thread(target=writer, args=(ts+"-%d.wav" %(i+1), q))
   t.setDaemon(True)
   t.start()

 time.sleep(3600*16)

El programa graba cada micro en un fichero WAV separado para facilitar la edición anterior. Estamos grabando voz así que limito el muestreo a 16Khz. La grabación es estéreo porque algunos micros, como el mío, tienen dos micrófonos internos para facilitar la cancelación del ruido ambiente. En tu caso puede ser suficiente grabar en mono. El fichero medirá la mitad.

Las líneas 27-35 lanzan dos hilos (threads) por micrófono, un hilo para leer el micro y otro hilo para volcar esa información en su fichero WAV correspondiente. Lo hacemos así para evitar en lo posible perder muestras si la grabación es lenta (por ejemplo, grabando en un disco compartido por red). Este enfoque puede parecer un poco overkill, pero lanzar 40 hilos para grabar 20 micrófonos no supone ningún problema.

La rutina en las líneas 9-15 lee el micro que corresponda y vamos metiendo las muestras recibidas en una cola. La rutina en las líneas 17-24 lee de la cola anterior y va almacenando las muestras en un fichero WAV independiente.

La línea 37 simplemente mantiene el programa vivo cuando el hilo principal no está haciendo nada y no queremos que consuma CPU mientras espera a que pulsemos control+c.

Detalles a tener en cuenta

  1. Escribí este programa en febrero de 2011 para la primera grabación de Podcast Z: Python, Sistemas y Seguridad.
  2. El programa usa el sistema de sonido OSS. Algunas distribuciones de Linux ya no soportan OSS, ha pasado de moda. No he probado este programa bajo otros sistemas operativos con soporte OSS moderno.
  3. OSS no permite, al menos en mi versión del sistema operativo, acceso concurrente a los micrófonos. Es decir, si estamos usando un micrófono con otro programa, como en una videoconferencia, no podremos grabarlo al mismo tiempo con este programa.