music-analysis / pages /6-Timbre_Analysis.py
Keycatowo
init trans commit
bb5feba
#%%
import streamlit as st
import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
import numpy as np
import librosa
import pandas as pd
from src.st_helper import convert_df, show_readme, get_shift
from src.timbre_analysis import (
spectral_centroid_analysis,
rolloff_frequency_analysis,
spectral_bandwidth_analysis,
harmonic_percussive_source_separation
)
st.title("Timbre Analysis")
#%% 頁面說明
# show_readme("docs/6-Timbre Analysis.md")
#%% 上傳檔案區塊
with st.expander("上傳檔案(Upload Files)"):
file = st.file_uploader("Upload your music library", type=["mp3", "wav", "ogg"])
if file is not None:
st.audio(file, format="audio/ogg")
st.subheader("File information")
st.write(f"File name: `{file.name}`", )
st.write(f"File type: `{file.type}`")
st.write(f"File size: `{file.size}`")
# 載入音檔
y, sr = librosa.load(file, sr=44100)
st.write(f"Sample rate: `{sr}`")
duration = float(np.round(len(y)/sr-0.005, 2)) # 時間長度,取小數點後2位,向下取整避免超過音檔長度
st.write(f"Duration(s): `{duration}`")
y_all = y
#%%
if file is not None:
### Start of 選擇聲音片段 ###
with st.expander("選擇聲音片段(Select a segment of the audio)"):
# 建立一個滑桿,可以選擇聲音片段,使用時間長度為單位
start_time, end_time = st.slider("Select a segment of the audio",
0.0, duration,
(st.session_state.start_time, duration),
0.01
)
st.session_state.start_time = start_time
st.write(f"Selected segment: `{start_time}` ~ `{end_time}`, duration: `{end_time-start_time}`")
# 根據選擇的聲音片段,取出聲音資料
start_index = int(start_time*sr)
end_index = int(end_time*sr)
y_sub = y_all[start_index:end_index]
# 建立一個y_sub的播放器
st.audio(y_sub, format="audio/ogg", sample_rate=sr)
# 計算y_sub所對應時間的x軸
x_sub = np.arange(len(y_sub))/sr
### End of 選擇聲音片段 ###
tab1, tab2, tab3, tab4 = st.tabs(["Spectral Centroid", "Rolloff Frequency", "Spectral Bandwidth", "Harmonic Percussive Source Separation"])
shift_time, shift_array = get_shift(start_time, end_time) # shift_array為y_sub的時間刻度
# spectral_centroid_analysis
with tab1:
st.subheader("Spectral Centroid Analysis")
fig6_1, ax6_1, centroid_value = spectral_centroid_analysis(y_sub, sr, shift_array)
st.pyplot(fig6_1)
df_centroid = pd.DataFrame(centroid_value.T, columns=["Time(s)", "Centroid"])
df_centroid["Time(s)"] = df_centroid["Time(s)"] + shift_time
st.dataframe(df_centroid, use_container_width=True)
st.download_button(
label="Download spectral centroid data",
data=convert_df(df_centroid),
file_name="centroid.csv",
mime="text/csv",
)
# rolloff_frequency_analysis
with tab2:
st.subheader("Rolloff Frequency Analysis")
roll_percent = st.selectbox("Select rolloff frequency", [0.90, 0.95, 0.99])
fig6_2, ax6_2, rolloff_value = rolloff_frequency_analysis(y_sub, sr, roll_percent=roll_percent, shift_array=shift_array)
st.pyplot(fig6_2)
df_rolloff = pd.DataFrame(rolloff_value.T, columns=["Time(s)", "Rolloff", "Rolloff_min"])
df_rolloff["Time(s)"] = df_rolloff["Time(s)"] + shift_time
st.dataframe(df_rolloff, use_container_width=True)
st.download_button(
label="Download rolloff frequency data",
data=convert_df(df_rolloff),
file_name="rolloff.csv",
mime="text/csv",
)
# spectral_bandwidth_analysis
with tab3:
st.subheader("Spectral Bandwidth Analysis")
fig6_3, ax6_3, bandwidth_value = spectral_bandwidth_analysis(y_sub, sr, shift_array)
st.pyplot(fig6_3)
df_bandwidth = pd.DataFrame(bandwidth_value.T, columns=["Time(s)", "Bandwidth"])
df_bandwidth["Time(s)"] = df_bandwidth["Time(s)"] + shift_time
st.dataframe(df_bandwidth, use_container_width=True)
st.download_button(
label="Download spectral bandwidth data",
data=convert_df(df_bandwidth),
file_name="bandwidth.csv",
mime="text/csv",
)
# harmonic_percussive_source_separation
with tab4:
st.subheader("Harmonic Percussive Source Separation")
fig6_4, ax6_4, (Harmonic_data) = harmonic_percussive_source_separation(y_sub, sr, shift_array)
D, H, P, t = Harmonic_data
st.pyplot(fig6_4)
st.download_button(
label="Download Full power spectrogram data",
data=convert_df(pd.DataFrame(D)),
file_name="Full_power_spectrogram.csv",
use_container_width=True,
)
st.download_button(
label="Download Harmonic power spectrogram data",
data=convert_df(pd.DataFrame(H)),
file_name="Harmonic_power_spectrogram.csv",
use_container_width=True,
)
st.download_button(
label="Download Percussive power spectrogram data",
data=convert_df(pd.DataFrame(P)),
file_name="Percussive_power_spectrogram.csv",
use_container_width=True,
)
st.download_button(
label="Download Time data",
data=convert_df(pd.DataFrame(t+shift_time, columns=["Time(s)"])),
file_name="Time_scale.csv",
use_container_width=True,
)