The plot from librosa doesn't appear together

# Library
import dash
from dash import Dash
from dash import dcc
from dash import html, dash_table
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
from dash import callback, ctx, State
from dash import register_page


import plotly.express as px 


import librosa
import librosa.display


import matplotlib
import matplotlib.axes
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import os

import io
import base64

# Register
dash.register_page(__name__)

# Style
hstyle = {"background": "#2D847A", "color": "white", "font-size": "30px",'width': '100%'}
hstyle1 = {"background": "#96B1AC", "color": "white", "font-size": "20px",'width': '100%'}

# Layout
layout = dbc.Col([
            html.Div([
                html.H1("Upload The Audio WAV File", style=hstyle),
                dbc.Row(
                    html.Div([
                        dcc.Upload(
                            id='upload-audio',
                            children=html.Div([
                                'Drag and Drop or ',
                                html.A('Select Files')
                            ]),
                            style={
                                'width': '99%',
                                'height': '60px',
                                'lineHeight': '60px',
                                'borderWidth': '1px',
                                'borderStyle': 'dashed',
                                'borderRadius': '5px',
                                'textAlign': 'center',
                                'margin': '10px'
                            },
                            multiple=False
                        )
                    ])
                ),
                dbc.Row([
                        html.Div(id='output'),
                        html.Div(id='output2')]), html.Br(),
                dbc.Row([                        
                        html.Div(id='output3'),
                        html.Div(id='output4'),
                        html.Div(id='output5'),
                        html.Div(id='output6')
                ])
            ])
])




## Audio Analysis Output1 - WAVEFORM

@callback(Output('output', 'children'),
              [Input('upload-audio', 'contents')])

def update_output(contents):
    if contents is not None:
        audio_string = contents.split(',')[1]
        audio_bytes = base64.b64decode(audio_string)
        file_path = 'uploaded_audio.wav'

        with open(file_path, 'wb') as f:
            f.write(audio_bytes)

        signal, sample_rate = librosa.load(file_path, sr=16000)
        fig, ax = plt.subplots(figsize=(12, 4))
        librosa.display.waveshow(signal, sr=sample_rate, alpha=0.4, ax=ax)
        ax.set_xlabel("Time (s)")
        ax.set_ylabel("Amplitude")
        ax.set_yticks(np.arange(-1, 1.25, 0.5))
        ax.set_title("Waveform")

        plt.tight_layout()

        buf = io.BytesIO()
        plt.savefig(buf, format='png')
        buf.seek(0)
        buffer_image = base64.b64encode(buf.getvalue()).decode('utf-8')

        return html.Div([
            html.Br(),
            html.H3('Uploaded WAV file:',style=hstyle1),
            html.Br(),
            html.Audio(src=contents, controls=True),
            html.Img(src='data:image/png;base64,' + buffer_image)
        ])
    else:
        return html.Div()
    
    
## Audio Analysis Output2 - Energy
@callback(Output('output2', 'children'),
              [Input('upload-audio', 'contents')])
def update_output2(contents):
    if contents is not None:
        audio_string2 = contents.split(',')[1]
        audio_bytes2 = base64.b64decode(audio_string2)
        file_path2 = 'uploaded_audio.wav'

        with open(file_path2, 'wb') as f:
            f.write(audio_bytes2)
        
        # load audio file with Librosa
        y, sample_rate = librosa.load(file_path2, sr=16000)
            
        # Display RMS Energy
        S, phase = librosa.magphase(librosa.stft(y))
        rms = librosa.feature.rms(S=S)

        fig, ax = plt.subplots(figsize=(15, 5), nrows=2, sharex=True)
        times = librosa.times_like(rms)
        ax[0].semilogy(times, rms[0], label='RMS Energy')
        ax[0].set(xticks=[])
        ax[0].legend()
        ax[0].label_outer()
        librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
                                y_axis='log', x_axis='time', ax=ax[1])
        ax[1].set_title("log Power spectrogram of")
        plt.tight_layout()
            
        buf2 = io.BytesIO()
        plt.savefig(buf2, format='png')
        buf2.seek(0)
        buffer_image2 = base64.b64encode(buf2.getvalue()).decode('utf-8')

        return html.Div([
            html.Br(),
            html.H3("Feature Extraction",className="fw-bold fst-italic",style=hstyle1),
            html.Br(),
            html.H5('Audio Energy:'),
            html.Br(),
            html.Img(src='data:image2/png;base64,' + buffer_image2),html.Br(),
            ])
    else:
        return html.Div()
    
    
    
## Audio Analysis Output3 - PITCH
@callback(Output('output3', 'children'),
              [Input('upload-audio', 'contents')])
def update_output3(contents):
    if contents is not None:
        audio_string3 = contents.split(',')[1]
        audio_bytes3 = base64.b64decode(audio_string3)
        file_path3 = 'uploaded_audio.wav'

        with open(file_path3, 'wb') as f:
            f.write(audio_bytes3)
           
        # Load audio file and extract pitch features
        y, sr = librosa.load(file_path3, sr=16000)
        
        S = np.abs(librosa.stft(y, n_fft=4096))**2
        chroma = librosa.feature.chroma_stft(S=S, sr=sr)
        
        # display pitch
        fig, ax = plt.subplots(figsize=(15, 6),nrows=2, sharex=True)
        img2 = librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
                                    y_axis='log', x_axis='time', ax=ax[0])
        fig.colorbar(img2, ax=[ax[0]], location = 'right')
        ax[0].label_outer()
        img2 = librosa.display.specshow(chroma, y_axis='chroma', x_axis='time', ax=ax[1])
        fig.colorbar(img2, ax=[ax[1]], location = 'right') #ax.colorbar()

        ax[1].set_xlabel("Time (s)")
        ax[0].set_ylabel("Hz")
        ax[1].set_ylabel("Pitch Class")
        ax[0].set_title("STFT Amplitude to dB")  
        ax[1].set_title("Pitch")                     
        plt.tight_layout()
           
        buf3 = io.BytesIO()
        plt.savefig(buf3, format='png')
        buf3.seek(0)
        buffer_image3 = base64.b64encode(buf3.getvalue()).decode('utf-8')

        return html.Div([
            html.Br(),
            html.Img(src='data:image3/png;base64,' + buffer_image3),
            ])
    else:
        return html.Div()


## Audio Analysis Output5 - MFCC
@callback(Output('output5', 'children'),
              [Input('upload-audio', 'contents')])
def update_output5(contents):
    if contents is not None:
        audio_string = contents.split(',')[1]
        audio_bytes = base64.b64decode(audio_string)
        file_path = 'uploaded_audio.wav'

        with open(file_path, 'wb') as f:
            f.write(audio_bytes)
            
        # Load audio file and extract pitch features
        x, sr = librosa.load(file_path, sr=16000)
        mfccs = librosa.feature.mfcc(y=x, sr=sr)
    
        # Display the MFCCs with the file name as the plot title
        fig, ax5 = plt.subplots(figsize=(15, 3))
        img5 = librosa.display.specshow(mfccs, sr=sr, x_axis='time',ax=ax5)
        fig.colorbar(img5, ax=ax5)
        ax5.set_title("MFCC") 
        ax5.set_ylabel("MFCC Coefficient")
        
        plt.tight_layout()
            
        buf = io.BytesIO()
        plt.savefig(buf, format='png')
        buf.seek(0)
        buffer_image5 = base64.b64encode(buf.getvalue()).decode('utf-8')

        return html.Div([
            html.Br(),
            html.H3("Feature Extraction",className="fw-bold fst-italic"), 
            html.Img(src='data:image/png;base64,' + buffer_image5),
            ])
    else:
        return html.Div()   

Hi guys, I have a problem that the plot generated from Librosa doesn’t appear simultaneously / together, only appears when called one by one. And some times the plot and plotbar are messy. Currently, my project is related to audio data. Do you have any solutions?



@adamschroeder and @AIMPED , if you have any solutions please let me know :slight_smile:

Hey @ELITSZORD what exactly are you referring to with this?

My code generates some plots (wave, energy, pitch, mfcc) but when I run the program all the plots don’t appear or sometimes only some appear.

@ELITSZORD are you running your app in debug mode? Do you get any errors?

There is no error… @AIMPED

hi @ELITSZORD
Were you able to fix the error? if yes, can you share the solution with us please.

not yet sir @adamschroeder

@ELITSZORD could you try breaking down your problem into a smaller example which we can reproduce on our computers?

You @AIMPED @adamschroeder can see my dashboard video problem and my files (appp.py and pages folder) with this link https://drive.google.com/drive/folders/1tYKC3bb4zx63XQ5-S9BY1wUdxvL4HQJE?usp=sharing

The problems are as follows:

  1. When going to the audio analysis page and uploading a WAV file, if we only operate the code to plot waveform and energy, then the waveform and energy plots will appear on the audio analysis page. If the code is added to display pitch and MFCC plots, which are four plots in total, all four plots do not appear or sometimes appear distorted.
  2. When the “Overview Result” navbar is clicked and then returned to the home page, the content of the overview result page appears on the home page, whereas the overview result page should not be included.
  3. The navbar size does not fit the screen size.

Hey @ELITSZORD I would try chaining the callbacks so that the first callback is triggered by the upload, the second callback is triggered once the first callback finishes instead of triggering all callbacks with the upload-audio

You can upload your data into a dcc.Store() and use the State()of it for the callbacks.

1 Like