8.5 Archivos.wav de audio con Python – Abrir, extraer una porción
Los conceptos de arreglos como vectores y matrices son suficientes para manejar archivos.wav. con la librería Scipy-Python.
1. Leer o Abrir archivo.wav de audio
Para procesar un archivo de audio en formato .wav, la instrucción waves.read(archivo)
usa el archivo con ‘nombre.wav’ y obtiene dos variables que representan:
– muestreo: frecuencia de muestreo del sonido en PCM y
– sonido: que es un arreglo con las muestras del sonido.
El archivo de audio debe encontrarse en el mismo directorio que el archivo.py de instrucciones, por ejemplo, dado el archivo ‘Alarm01.wav’ , se puede procesar con las instrucciones mostradas:
# Abrir un archivo de audio .wav import numpy as np import matplotlib.pyplot as plt import scipy.io.wavfile as waves # INGRESO archivo = 'Alarm01.wav' muestreo, sonido = waves.read(archivo)
con lo que se obtiene:
>>> muestreo 22050 >>> sonido array([[0, 0], [0, 0], [0, 0], ..., [0, 0], [0, 0], [0, 0]], dtype=int16) >>> np.shape(sonido) (122868, 2)
En el ejemplo, la frecuencia de muestreo es de 22050 Hz. El sonido es estéreo al tener dos columnas que corresponden a los canales izquierdo y derecho.
Para usar un solo canal, se copian los datos a un nuevo arreglo. Para separar el canal izquierdo por ejemplo, se usan las instrucciones:
>>> izquierdo=sonido[:,0].copy() >>> izquierdo array([0, 0, 0, ..., 0, 0, 0], dtype=int16
Con lo que se tienen los datos listos para ser procesados.
1.1 Otro ejemplo de archivo.wav de audio
Con los datos se pueden graficar las ondas de sonido como la mostrada en la imagen.
El formato .wav es el más simple de manejar pues contiene directamente los datos de las muestras de sonido similar a la mostrada en la figura.
El primer parámetro a obtener es la frecuencia de muestreo en Hz, o cuántas muestras por segundo se realizan, y luego los datos del sonido.
# Abrir un archivo de audio .wav import numpy as np import matplotlib.pyplot as plt import scipy.io.wavfile as waves # INGRESO # archivo = input('archivo de sonido:' ) archivo = 'muestra_Invernal01.wav' muestreo, sonido = waves.read(archivo) # PROCEDIMIENTO tamano=np.shape(sonido) canales=len(tamano) tipo = 'estéreo' if (canales<2): tipo = 'monofónico' duracion = len(sonido) /muestreo # SALIDA print('muestreo (Hz) : ',muestreo) print('canales: ' + str(canales) + ' tipo ' + tipo ) print('duración (s): ',duracion) print('tamaño de matriz: ', tamano) print(sonido) plt.plot(sonido) plt.show()
Con lo que obtiene la gráfica mostrada al inicio y los siguientes resultados:
muestreo (Hz) : 44100 canales: 2 tipo estéreo duración (s): 15.0 tamaño de matriz: (661500, 2) [[-4355 -4561] [-4353 -4572] [-4347 -4578] ..., [ 120 1008] [ 124 993] [ 100 935]]
Referencias:
https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.io.wavfile.read.html
1.2 Librerías para tratamiento de audio
la librería de funciones scipy (scientific python), dispone de funciones para el tratamiento de señales, estadísticas, audio, entre otras.
El orden de las instrucciones es el que aparece en los post del blog.
import scipy.io.wavfile as waves | librerias de audio en formato wav para lectura y escritura de archivos. |
muestreo, sonido = waves.read(archivo) | lectura de datos de un archivo de audio en formato wav. Se obtiene la frecuencia de muestreo y los datos en sonido |
import scipy.integrate as integrate | importar metodos de integración de scipy |
integrate.simps(valrores, ejex) | integral de muestras de señal usando el método de Simpson. |
. | . |
. | . |
2. Extraer una Porción del audio y guardar archivo.wav
Para extraer una porción de un archivo de audio se requiere: abrir el archivo, seleccionar la porción de interés y guardar el resultado un archivo de salida.
archivo origen: muestra_Invernal01.wav
archivo resultado: muestra_Invernal02.wav
La porción puede ser indicada en unidades de tiempo que luego deben ser convertidas a índices de muestras para extraer la porción requerida.
El procesamiento del archivo simplificado en Python es:
# Extrae porción de un archivo de audio .wav import numpy as np import matplotlib.pyplot as plt import scipy.io.wavfile as waves # INGRESO # archivo = input('archivo de sonido:' ) archivo = 'muestra_Invernal01.wav' archivosalida = 'muestra_Invernal02.wav' # tiempo en segundos desde = 7.5 hasta = 10.2 muestreo, sonido = waves.read(archivo) # PROCEDIMIENTO # indices de muestras idesde = int(desde*muestreo) ihasta = int(hasta*muestreo) porcion = sonido[idesde:ihasta,:] duracion = len(porcion)/muestreo # SALIDA waves.write(archivosalida, muestreo, porcion) print('archivo creado: ', archivosalida)
2.1 Guardar un archivo de audio .wav
Luego de procesar los datos de audio, y guardar el resultado en un archivo con ‘nombre.wav’ se usa la instruccion waves.write()
de la libreria scipy, que requiere:
– archivo: el nombre del archivo resultante, con extension.wav
– fsonido: la frecuencia de muestreo del sonido (entero)
– sonido: el arreglo de la señal de audio como entero de 16 bits (dtype=’int16′).
Recuerde haber realizado el llamado a las librerias numpy y scipy que se presentan como referencia en el script.
# PROCEDIMIENTO # Arreglos para datos con k muestras sonidofinal = np.zeros(k, dtype='int16') # SALIDA archivo = 'audiofinal.wav' waves.write(archivo, int(fsonido),sonidofinal)
El archivo de audio resultante se escucharà usando un programa como «windows media player»
Notas:
Se puede añadir al nombre la ruta de ubicación del archivo en el disco duro. Ejemplo para windows: ‘C:\Users\mis documentos\archivo.wav‘
3. Gráfica de un canal de audio
Para mostrar en un gráfico un canal de audio se usa la libreria matplotlib. Para muestra, usando los datos del ejemplo anterior:
izquierdo = sonido[:,0].copy()
# SALIDA grafica
plt.plot(izquierdo)
plt.show()
con lo que se obtiene la siguiente gráfica:
Con lo que se puede revisar la forma de la señal de audio
Ejercicio
Si el archivo de origen es estéreo, extraer un solo canal y convertirlo a monofónico.
El manejo de archivo de audio en formato wav permite analizar varios conceptos como , en los cursos de Señales y Sistemas y Procesos estocásticos:
Señales Analógicas y Digitales
Referencia: https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.io.wavfile.write.html
8.4 Archivos.json con Pandas-Python
Algunas estructuras de datos que se encuentran en formato tipo «diccionario» se pueden guardar y leer usando librerias Pandas.
Para el ejemplo se usa el diccionario:
tabla = {'Maria': {'primera': 55, 'segunda': 70, 'tercera': 0, 'final': '62,5'}, 'Pedro': {'primera': 30, 'segunda': 60, 'tercera': 70, 'final': '65'}, 'Juan': {'primera': 80, 'segunda': 65, 'tercera': 65, 'final': '72,5'} }
Para almacenar estos datos se realiza la conversión del diccionario a DataFrame con el objetivo de usar la instrucción de Pandas para guardar archivos.json.
tabla.to_json(unarchivo)
Instrucciones en Python
import pandas as pd # INGRESO #archivos de salida T: Transpuesta unarchivo = 'ejemplonotas01.json' unarchivoT = 'ejemplonotasT01.json' # datos como diccionario de datos tabla = {'Maria': {'primera': 55, 'segunda': 70, 'tercera': 0, 'final': '62,5'}, 'Pedro': {'primera': 30, 'segunda': 60, 'tercera': 70, 'final': '65'}, 'Juan': {'primera': 80, 'segunda': 65, 'tercera': 65, 'final': '72,5'} } # PROCEDIMIENTO # conversión a DataFrame de pandas tabla = pd.DataFrame(tabla) tablaT = tabla.transpose() # SALIDA print(tabla) print('transponer: ') print(tablaT) # almacena en archivo.json tabla.to_json(unarchivo) tablaT.to_json(unarchivoT)
los archivos resultantes son:
Referencia:
https://pandas.pydata.org/docs/reference/api/pandas.io.json.read_json.html
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_json.html
8.3.1 Archivos.csv con Python – Ejercicio con gráfica de temperatura y Humedad
Ejercicio. De una estación meteorológica se obtiene un archivo.csv con los datos de los sensores disponibles durante una semana.
1. Lectura de archivo.csv y gráfica de datos
a. Realice la lectura de los datos desde el archivo.csv
en una tabla de Pandas, muestre los nombres de las columnas
b. Añada una columna de fecha-hora con tipo de dato datetime
unificando las columnas «Date
» y «Time
»
c. Realice la gráfica de los datos obtenidos para la variable temperatura «TEMP
» vs «fecha
«.
Referencia: Basic Time Series Plotting. Unidata. https://unidata.github.io/python-training/workshop/Time_Series/basic-time-series-plotting/
1.1 Solución propuesta
literal a
Para leer o cargar el archivo.csv con pandas y realizar la gráfica se usarán las librerías «pandas» y «matplotlib». La lectura del archivo usa los parámetros de separador de datos ';'
y separador decimal ','
. El nombre del archivo es parte del bloque de ingreso.
tabla = pd.read_csv(narchivo, sep=';',decimal=',')
literal b
Para manejar las fechas, se concatenan los valores de las columnas 'Date'
y 'Time'
conformando una cadena de caracteres en cada casilla de la columna 'fecha'
.
Para manejar los datos y operaciones con fechas se usan el tipo de datos datetime
. El formato de lectura se indica como"%d/%m/%Y %H:%M:%S"
dado por una cadena de caracteres
fechaformato = "%d/%m/%Y %H:%M:%S" tabla['fecha'] = pd.to_datetime(tabla['fecha'], format=fechaformato)
literal c
La gráfica se realiza usando los datos de las columnas de fecha y temperatura.
Instrucciones Python
# lecturas archivo.csv de estación meteorológica import pandas as pd import matplotlib.pyplot as plt # INGRESO narchivo = "2021_10_EstMeteorologica.csv" # PROCEDIMIENTO tabla = pd.read_csv(narchivo, sep=';',decimal=',') n = len(tabla) # fechas concatenando columnas de texto tabla['fecha'] = tabla['Date']+' '+tabla['Time'] # convierte a datetime fechaformato = "%d/%m/%Y %H:%M:%S" tabla['fecha'] = pd.to_datetime(tabla['fecha'], format=fechaformato) # SALIDA print('columnas: ', list(tabla.keys())) # grafica x_horas = tabla['fecha'] y_temp = tabla['TEMP'] plt.plot(x_horas,y_temp,'*') plt.title('Temperatura') plt.grid() plt.show()
2. Separar datos por días y graficar
d. Para realizar un análisis por día y comparar entre varios días, se requiere encontrar los intervalos de inicio y fin de día.
e. Realizar la gráfica comparativa de los días.
2.1 Solución propuesta
literal d
Los intervalos se pueden entregar como una lista de los índices de las filas donde cambia el día.
literal d
Para que las gráficas se superpongan en las mismas horas, sin cambiar de día, se realiza una operación de desplazamiento pd.Timedelta(days=j)
a las fechas antes de hacer cada línea de gráfica.
Las etiquetas en el eje x se cambia al formato '%H:%M'
mediante la librería matplotlib.dates
y la instrucción DateFormatter
.
La gráfica para 7 días se presenta muchos datos, por lo que para análisis es preferible algo más simplificado, como comparar dos días para simplificar visualmente.
Instrucciones Python
# lecturas archivo.csv de estación meteorológica import pandas as pd import matplotlib.pyplot as plt from matplotlib.dates import DateFormatter, DayLocator # INGRESO narchivo = "2021OctubreEstMetorologica.csv" # PROCEDIMIENTO tabla = pd.read_csv(narchivo, sep=';',decimal=',') n = len(tabla) # fechas concatenando columnas de texto tabla['fecha'] = tabla['Date']+' '+tabla['Time'] # convierte a datetime fechaformato = "%d/%m/%Y %H:%M:%S" tabla['fecha'] = pd.to_datetime(tabla['fecha'], format=fechaformato) # serie por días diaIndice = [0] # indice inicial for i in range(1,n-1,1): i0_fecha = tabla['fecha'][i-1] i1_fecha = tabla['fecha'][i] if i0_fecha.day != i1_fecha.day: diaIndice.append(i) diaIndice.append(len(tabla)-1) # indice final m = len(diaIndice) # SALIDA print('columnas: ', list(tabla.keys())) print('SerieDia: ',diaIndice) print('días en serie: ', len(diaIndice)) # grafica figura, grafica = plt.subplots() marcador = ['.','o','v','^','<','>','1'] for j in range(0,7,1): i0 = diaIndice[j] i1 = diaIndice[j+1] x_horas = tabla['fecha'][i0:i1]-pd.Timedelta(days=j) y_temp = tabla['TEMP'][i0:i1] etiqueta = str(tabla['fecha'][i0].month)+'-' etiqueta = etiqueta + str(tabla['fecha'][i0].day) grafica.scatter(x_horas,y_temp, marker = marcador[j%7], label=etiqueta) # formato de eje grafica.xaxis.set_major_formatter(DateFormatter('%H:%M')) plt.legend() plt.title('Temperatura') plt.grid() plt.show()
Otros temas de desarrollo
Regresión polinomial de grado m – Ejercicio Temperatura para un día
8.3 Archivos.csv con Pandas-Python
Algunas tablas de datos se pueden recibir como archivos.csv, que son datos separados por ';'
, debiendo indicar el separador de decimales ','
.
Ejemplo de archivo: ejemplonotas01.csv
nombre;primera;segunda;tercera;final Maria;55;70;0;62,5 Pedro;30;60;70;65 Juan;80;65;65;72,5
puede ser leido y procesado usando la libreria pandas
import pandas as pd # INGRESO # archivo de entrada unarchivo = 'ejemplonotas01.csv' # PROCEDIMIENTO tabla = pd.read_csv(unarchivo, sep=';', na_values=',') # SALIDA print(tabla)
con lo que se obtiene:
nombre primera segunda tercera final 0 Maria 55 70 0 62,5 1 Pedro 30 60 70 65 2 Juan 80 65 65 72,5 >>>
Tamaño de la tabla:
>>> tabla.shape (3, 5) >>> tabla.columns Index(['nombre', 'primera', 'segunda', 'tercera', 'final'], dtype='object') >>> tabla['nombre'] 0 Maria 1 Pedro 2 Juan Name: nombre, dtype: object
Seleccionando solo un grupo de datos:
>>> soloprimera = tabla['primera'] >>> soloprimera 0 55 1 30 2 80 Name: primera, dtype: int64 >>> media = soloprimera.mean() >>> media 55.0
Referencia:
https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html
8.2 Gráficas de funciones matemáticas
Las gráficas básicas para funciones matemáticas, datos, en 2D y 3D usan la librería matplotlib.pyplot con el alias plt.
import matplotlib.pyplot as plt
En caso de necesitar instalar: Matplotlib – Gráficas. Instalación simple con pip
Ejemplos de gráficas en 2D
Las gráficas son un recurso muy versatil en el área de la matemática e ingeniería.
En el curso de Métodos Numéricos se presenta una introducción de gráficas en 2D y se usan y desarrollan en todas las unidades como parte del análisis de los problemas.
Graficas 3D puntos dispersos-scatter
En el curso de Señales y Sistemas, se las usa ampliamente desde la unidad 1 Señales, para mostrar los diferentes tipos y formas, y luego en el análisis de las respuestas de los sistemas ante las señales. Como tema de instroducción, revise algúnas de las definiciones básicas de señales para observar la aplicación de gráficas.
3. Señales Analógicas y Digitales
4. Señales Periódicas y No periódicas
5. Señales de Energía y Potencia
9. Señales Exponencial compleja
10. Señales operaciones en tiempo
También se usan para el análisis de resultados e algun experimento, como los que se pueden observar en el grupo de investigación GIRNI
Rssi vs Distancia. Linealiza POR intervalos
Se pueden usar algunos tipos de gráficas, como de línea, dispersión, flechas, usando las coordenadas en vectores x, y
plt.plot(x,y) plt.scatter(x,y) plt.arrow(xinicio, yinicio, deltax,deltay) plt.quiver(xinicio, yinicio, componentex, componentey)
Las instrucciones para las gráficas se realizan en el bloque de salida usando un solo bloque de instrucciones, para finalmente mostrar el resultado plt.show().
8.1.1 Menú en Python – Ejercicios resueltos y Tarea
Ejercicios resueltos de menú con Python
3Eva_IIT2009_T2 Registrar alquiler de casilleros
Solución propuesta: s3Eva_IIT2009_T2 Registrar alquiler de casilleros
2Eva_IIT2009_T3 Controlar saldos prepago
Solución propuesta: s2Eva_IIT2009_T3 Controlar saldos prepago
2Eva_IIT2015_T4 biciespol, prestamos de bicicletas
Solución propuesta: s2Eva_IIT2015_T4 biciespol, prestamos de bicicletas
2Eva_IT2006_T1 Donaciones defensa civil
Solución propuesta: s2Eva_IT2006_T1 Donaciones defensa civil
3Eva_IIT2015_T1 Mensajes en redes sociales y etiquetas
Solución propuesta: s3Eva_IIT2015_T1 Mensajes en redes sociales y etiquetas
3Eva_IIT2015_T2 Gestionar mensajes con etiquetas
Solución propuesta: s3Eva_IIT2015_T2 Gestionar mensajes con etiquetas
1Eva_IIT2002_T1a Crea tablas de multiplicar con strings del 1 a n
Solución propuesta: s1Eva_IIT2002_T1a Crea tablas de multiplicar con strings del 1 a n
Ejercicios por desarrollar
3Eva_IIT2013_T4 Gestionar asientos en cine
8.1 Menú en Python – Condicionales «elif» semejante a «case»
¿Cómo hacer un menú en Python? como una estructura simplificada y semejante a un menú de un restaurante donde cada opción
puede pedirse una o varias veces. Cada opción
se identifica y selecciona usando un caracter
de un número entero, luego se revisa entre cada opción
disponible mediante bucle while
, para continuar recibiendo peticiones de opción
.
Para crear un menú en Python, los pasos a seguir se describen como:
- Iniciar la
opción
seleccionada en «0» o un valor diferente a laopción
de «salida» del lazo/bucle. - repetir el bloque menú en un lazo/bucle mientras la opción seleccionada no sea la
opción
de «salida» del menú, - Mostrar en pantalla las
opción
es del menú, y los valores que las seleccionan. - Preguntar o pedir una
opción
, entre las mostradas en pantalla. - Revisar la
opción
seleccionada entre lasopción
es disponibles. Use un condicional por cadaopción
disponible (caso) y se realice los pasos que se requieran. En este caso también se puede llamar a una función o un procedimiento. - Para la
opción
de salida, se puede añadir un condicional y se muestran los mensajes de cierre de programa.
Instrucción «elif» semejante a la instrucción «case»
Para cada caso luego del primer condicional se usa «elif
«, que es la simplificación de condicionales anidados, es decir lo que sigue después del primer condicional es «else
» y luego «if
«, al simplificar es «elif
«.
if (opcion=='1'): print(' **** menu opcion 01 ****') else: if (opcion=='2'): print(' **** menu opcion 02 ****') else: print('No existe la opcion')
Se adjunta un video tutorial con un ejemplo para administrar el alquiler de un bloque de casilleros de 6 filas y 10 columnas.
Ejercicio: 3Eva_IIT2009_T2 Registrar alquiler de casilleros
Solución Propuesta: s3Eva_IIT2009_T2 Registrar alquiler de casilleros
Estructura básica de instrucciones en Python
Note que los valores de opción de selección son tipo caracteres, por lo que también se puede usar letras para cada caso.
# Ejemplo de un menu # las opciones se proponen por caracteres # propuesta: edelros@espol.edu.ec # menu opcion = '0' while not(opcion=='9'): print(' 1. menu opcion 01') print(' 2. menu opcion 02') print(' 3. menu opcion 03') print(' 4. menu opcion 04') print(' 5. menu opcion 05') print(' 9. Salir') opcion=input(' --- ¿Cuál opcion?: ') if (opcion=='1'): print(' **** menu opcion 01 ****') elif (opcion=='2'): print(' **** menu opcion 02 ****') elif (opcion=='3'): print(' **** menu opcion 03 ****') elif (opcion=='4'): print(' **** menu opcion 04 ****') elif (opcion=='5'): print(' **** menu opcion 05 ****') elif (opcion=='9'): print(' **** Saliendo del menu ****') print(' **** Ejemplo de un menu ****') else: print('No existe la opcion en el menu')
Al final, se añade un «else», en el que se añaden instrucciones para el caso que ninguno de los casos anteriores se cumplió. Se muestra un mensaje como ‘No existe la opción en el menú’ y el lazo vuelve a iniciar.
Ejemplos de ejercicios desarrollados y otros ejercicios se presentan en la siguiente sección.