# 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?