How to get the array of envelope in each duration of sound event?

463 Views Asked by At

I am wondering how to get the array of envelopes in every sound duration. Every sound duration means 0.79s in first sound event, 0.21s in second, 0.9s in third and so on.

The current code is extracted from get the array of envelopes:


debussy_file = "1-01-1.wav"
debussy, sr = librosa.load(debussy_file)

FRAME_SIZE = 1024
HOP_LENGTH = 512

def amplitude_envelope(signal, frame_size, hop_length):
    """Calculate the amplitude envelope of a signal with a given frame size nad hop length."""
    amplitude_envelope = []
    
    # calculate amplitude envelope for each frame
    for i in range(0, len(signal), hop_length): 
        amplitude_envelope_current_frame = max(signal[i:i+frame_size]) 
        amplitude_envelope.append(amplitude_envelope_current_frame)
    
    return np.array(amplitude_envelope)    

# number of frames in amplitude envelope
ae_debussy = amplitude_envelope(debussy, FRAME_SIZE, HOP_LENGTH)

#Visualising amplitude envelope
frames = range(len(ae_debussy))
t = librosa.frames_to_time(frames, hop_length=HOP_LENGTH)

ax = plt.subplot(3, 1, 1)
librosa.display.waveplot(debussy, alpha=0.5)
plt.plot(t, ae_debussy, color="r")
plt.title("Debusy")

It shows like this. enter image description here But I want to see the value in every duration of sound event(I already have the duration information), not the whole audio. Perhaps is an easy question, but I don't know how to correct from the code. I appreciate it if someone is willing to help me.!

P.s. If I need to explain more, plz tell me! Thx

1

There are 1 best solutions below

0
Jon Nordby On

In your code you have some code for computing the envelope values, and the timestamps of the envelopes. So this is mostly about using the timestamps in order to cut out the relevant values.

I suggest using pandas.Series to combine the values and timestamps into one object. This makes it very easy to index on timestamps using .loc[start_time:end_time].

Complete code example follows. It will give a plot like this, where we show only the envelope (in red) for the specified times of the event.

enter image description here


import librosa
import pandas
import numpy

from matplotlib import pyplot as plt

def amplitude_envelope(signal, frame_size, hop_length, sr) -> pandas.Series:
    """Calculate the amplitude envelope of a signal

    Returns the envelope values and timestamps
    """
    amplitude_envelope = []
    
    # calculate amplitude envelope for each frame
    for i in range(0, len(signal), hop_length): 
        amplitude_envelope_current_frame = max(signal[i:i+frame_size]) 
        amplitude_envelope.append(amplitude_envelope_current_frame)
    
    values = numpy.array(amplitude_envelope)
    times = librosa.frames_to_time(numpy.arange(1, len(values)+1), hop_length=hop_length, sr=sr)
    series = pandas.Series(values, index=times, name='envelope')
    return  series

# load audio file
path = librosa.example('sweetwaltz')
audio, sr = librosa.load(path, duration=5.0)

# compute envelope
envelope = amplitude_envelope(audio, frame_size=1024, hop_length=512, sr=sr)

# extract only a certain time
event_envelope = envelope.loc[0.37:0.600]

ax = plt.subplot(3, 1, 1)
librosa.display.waveshow(audio, alpha=0.5)
plt.plot(event_envelope.index, event_envelope.values, color="r")
plt.savefig('event-env.png', bbox_inches='tight')