Cómo convertir un archivo .wav a un espectrogtwig en python3

Estoy intentando crear un espectrogtwig a partir de un archivo .wav en python3.

Quiero que la imagen guardada final se vea similar a esta imagen:

He probado lo siguiente:

Este post de desbordamiento de stack: espectrogtwig de un archivo de onda

Este post funcionó, de alguna manera. Después de ejecutarlo, me dieron

Sin embargo, este gráfico no contiene los colores que necesito. Necesito un espectrogtwig que tenga colores. Intenté juguetear con este código para intentar agregar los colores; sin embargo, después de dedicar un tiempo y un esfuerzo considerables a esto, ¡no pude entenderlo!

Entonces probé este tutorial.

Este código se bloqueó (en la línea 17) cuando intenté ejecutarlo con el error TypeError: el objeto ‘numpy.float64′ no se puede interpretar como un número entero.

línea 17:

samples = np.append(np.zeros(np.floor(frameSize/2.0)), sig) 

Traté de arreglarlo por casting

 samples = int(np.append(np.zeros(np.floor(frameSize/2.0)), sig)) 

y también lo intenté

 samples = np.append(np.zeros(int(np.floor(frameSize/2.0)), sig)) 

Sin embargo, ninguno de estos funcionó al final.

¡Realmente me gustaría saber cómo convertir mis archivos .wav a espectrogtwigs con color para poder analizarlos! ¡¡¡¡¡Cualquier ayuda sería apreciada!!!!!

Dígame si desea que proporcione más información sobre mi versión de python, qué probé o qué quiero lograr.

Utilice scipy.signal.spectrogram .

 import matplotlib.pyplot as plt from scipy import signal from scipy.io import wavfile sample_rate, samples = wavfile.read('path-to-mono-audio-file.wav') frequencies, times, spectrogram = signal.spectrogram(samples, sample_rate) plt.pcolormesh(times, frequencies, spectrogram) plt.imshow(spectrogram) plt.ylabel('Frequency [Hz]') plt.xlabel('Time [sec]') plt.show() 

Edit: poner plt.pcolormesh antes que plt.imshow parece solucionar algunos problemas, como lo señaló @Davidjb.

Asegúrese de que su archivo wav sea mono (un solo canal) y no estéreo (doble canal) antes de intentar hacer esto. Recomiendo leer la documentación de scipy en https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.signal.spectrogram.html .

He arreglado los errores que enfrenta para http://www.frank-zalkow.de/en/code-snippets/create-audio-spectrograms-with-python.html
Esta implementación es mejor porque puede cambiar el binsize (por ejemplo, binsize=2**8 )

 import numpy as np from matplotlib import pyplot as plt import scipy.io.wavfile as wav from numpy.lib import stride_tricks """ short time fourier transform of audio signal """ def stft(sig, frameSize, overlapFac=0.5, window=np.hanning): win = window(frameSize) hopSize = int(frameSize - np.floor(overlapFac * frameSize)) # zeros at beginning (thus center of 1st window should be for sample nr. 0) samples = np.append(np.zeros(int(np.floor(frameSize/2.0))), sig) # cols for windowing cols = np.ceil( (len(samples) - frameSize) / float(hopSize)) + 1 # zeros at end (thus samples can be fully covered by frames) samples = np.append(samples, np.zeros(frameSize)) frames = stride_tricks.as_strided(samples, shape=(int(cols), frameSize), strides=(samples.strides[0]*hopSize, samples.strides[0])).copy() frames *= win return np.fft.rfft(frames) """ scale frequency axis logarithmically """ def logscale_spec(spec, sr=44100, factor=20.): timebins, freqbins = np.shape(spec) scale = np.linspace(0, 1, freqbins) ** factor scale *= (freqbins-1)/max(scale) scale = np.unique(np.round(scale)) # create spectrogram with new freq bins newspec = np.complex128(np.zeros([timebins, len(scale)])) for i in range(0, len(scale)): if i == len(scale)-1: newspec[:,i] = np.sum(spec[:,int(scale[i]):], axis=1) else: newspec[:,i] = np.sum(spec[:,int(scale[i]):int(scale[i+1])], axis=1) # list center freq of bins allfreqs = np.abs(np.fft.fftfreq(freqbins*2, 1./sr)[:freqbins+1]) freqs = [] for i in range(0, len(scale)): if i == len(scale)-1: freqs += [np.mean(allfreqs[int(scale[i]):])] else: freqs += [np.mean(allfreqs[int(scale[i]):int(scale[i+1])])] return newspec, freqs """ plot spectrogram""" def plotstft(audiopath, binsize=2**10, plotpath=None, colormap="jet"): samplerate, samples = wav.read(audiopath) s = stft(samples, binsize) sshow, freq = logscale_spec(s, factor=1.0, sr=samplerate) ims = 20.*np.log10(np.abs(sshow)/10e-6) # amplitude to decibel timebins, freqbins = np.shape(ims) print("timebins: ", timebins) print("freqbins: ", freqbins) plt.figure(figsize=(15, 7.5)) plt.imshow(np.transpose(ims), origin="lower", aspect="auto", cmap=colormap, interpolation="none") plt.colorbar() plt.xlabel("time (s)") plt.ylabel("frequency (hz)") plt.xlim([0, timebins-1]) plt.ylim([0, freqbins]) xlocs = np.float32(np.linspace(0, timebins-1, 5)) plt.xticks(xlocs, ["%.02f" % l for l in ((xlocs*len(samples)/timebins)+(0.5*binsize))/samplerate]) ylocs = np.int16(np.round(np.linspace(0, freqbins-1, 10))) plt.yticks(ylocs, ["%.02f" % freq[i] for i in ylocs]) if plotpath: plt.savefig(plotpath, bbox_inches="tight") else: plt.show() plt.clf() return ims ims = plotstft(filepath) 
 import os import wave import pylab def graph_spectrogram(wav_file): sound_info, frame_rate = get_wav_info(wav_file) pylab.figure(num=None, figsize=(19, 12)) pylab.subplot(111) pylab.title('spectrogram of %r' % wav_file) pylab.specgram(sound_info, Fs=frame_rate) pylab.savefig('spectrogram.png') def get_wav_info(wav_file): wav = wave.open(wav_file, 'r') frames = wav.readframes(-1) sound_info = pylab.fromstring(frames, 'int16') frame_rate = wav.getframerate() wav.close() return sound_info, frame_rate 

por A Capella Science – Bohemian Gravity! esto da:

introduzca la descripción de la imagen aquí

Use graph_spectrogram (path_to_your_wav_file). No recuerdo el blog de donde tomé este fragmento. Agregaré el enlace cada vez que lo vea de nuevo.