web-dev-qa-db-fra.com

Comment convertir un fichier .wav en spectrogramme en python3

J'essaie de créer un spectrogramme à partir d'un fichier .wav en python3.

Je veux que l'image enregistrée finale ressemble à cette image:

J'ai essayé ce qui suit:

Ce poste de débordement de pile: spectrogramme d’un fichier wave

Ce poste a fonctionné, un peu. Après l'avoir lancé, j'ai eu

Cependant, ce graphique ne contient pas les couleurs dont j'ai besoin. J'ai besoin d'un spectrogramme qui a des couleurs. J'ai essayé de bricoler ce code pour essayer d'ajouter des couleurs, mais après y avoir consacré beaucoup de temps et d'efforts, je ne pouvais pas le comprendre!

J'ai ensuite essayé this tutoriel.

Ce code s'est écrasé (ligne 17) lorsque j'ai essayé de l'exécuter avec l'erreur TypeError: l'objet 'numpy.float64' ne peut pas être interprété comme un entier.

ligne 17:

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

J'ai essayé de le réparer en coulant

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

et j'ai aussi essayé

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

Cependant, ni l'un ni l'autre n'a fonctionné à la fin.

J'aimerais vraiment savoir comment convertir mes fichiers .wav en spectrogrammes en couleur pour pouvoir les analyser! Toute aide serait appréciée!!!!!

Dites-moi si vous souhaitez que je vous fournisse plus d'informations sur ma version de Python, ce que j'ai essayé ou ce que je veux réaliser.

14
Sreehari R

Utilisation 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()

Assurez-vous que votre fichier wav est mono (canal unique) et non stéréo (canal double) avant d'essayer de le faire. Je recommande fortement de lire la documentation de scipy à l’adresse suivante: https://docs.scipy.org/doc/scipy- 0.19.0/reference/généré/scipy.signal.spectrogram.html.

En mettant plt.pcolormesh avant plt.imshow semble résoudre certains problèmes, comme l'a souligné @Davidjb, et si une erreur de déballage se produit, suivez les étapes de @cgnorthcutt ci-dessous.

28
Tom Wyllie

J'ai corrigé les erreurs que vous rencontrez pour http://www.frank-zalkow.de/en/code-snippets/create-audio-spectrograms-with-python.html
Cette implémentation est préférable car vous pouvez modifier le binsize (par exemple, 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)
7
Beginner
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

pour A Capella Science - Bohemian Gravity! cela donne:

enter image description here

Utilisez graph_spectrogram(path_to_your_wav_file). Je ne me souviens pas du blog d'où j'ai pris cet extrait. Je vais ajouter le lien chaque fois que je le revois.

6
Mudit Verma