<jupyter_start><jupyter_text>Hidden Markov Models as timbre-based rhythm models<jupyter_code>audio_files = ('../audio/base.wav', '../audio/var1.wav', '../audio/var2.wav')
sounds = [load_audio(file) for file in audio_files]<jupyter_output><empty_output><jupyter_text>1. Preprocessing<jupyter_code>fps = 44100           # audio frames per second
window = 'hamming'    # window function to apply to segments
n_perseg = 1024       # length of each segment in samples
n_overlap = 512       # number of overlapping samples<jupyter_output><empty_output><jupyter_text>1.1 Onset detection<jupyter_code>onsets = []
for snd in sounds:
    fod = FluxOnsetDetector(fps, window, n_perseg, n_overlap)
    fod.detect(snd.data.ravel())
    onsets.append(fod.onsets)
fig, axs = plt.subplots(3, 1, figsize=(10, 5), sharex=True, sharey=True)
for i, (ax, snd, ons) in enumerate(zip(axs, sounds, onsets)): 
    ax.set_ylabel(f'Sound {i+1}')
    ax.plot(snd.data.ravel(), zorder=-1)
    ax.vlines(ons.frame, -0.5, 0.5, 'r', 'dashed', zorder=1)
fig.tight_layout()<jupyter_output><empty_output><jupyter_text>1.2 Feature extraction<jupyter_code>dft = Dft(fps, window)
centroids = []
for snd, ons in zip(sounds, onsets):
    segs = segment.by_onsets(snd.data.ravel(), 1024, ons.frame)
    spctr = dft.transform(segs.T)
    cn = spectral_centroid(spctr.frqs, spctr.power).ravel()
    centroids.append(cn)
fig, axs = plt.subplots(3, 1, figsize=(10, 5), sharex=True, sharey=True)
for i, (ax, cnt) in enumerate(zip(axs, centroids)): 
    ax.set_ylabel(f'CNT {i+1}')
    ax.set_ylim([0, 10000])
    ax.plot(cnt)
fig.tight_layout()<jupyter_output><empty_output><jupyter_text>1.3 Prepare features for HMM This particular HMM uses Poisson distributions as components. These are discrete distributions. Hence, the feature values must be discretized.In this case, the spectral centroid frequencies are rounded to the next integer. Additionally, features must be rescaled to support numerical stabilityof the algorithm<jupyter_code>scaler = MinMaxScaler((1, 500))

scaled_features = []
for cnt in centroids:
    scaled_features.append(scaler.fit_transform(cnt.reshape(-1, 1)).ravel().round().astype(int))<jupyter_output><empty_output><jupyter_text>2. Estimate HMM parameters<jupyter_code>m = 4    # number HMM states a.k.a. number of component distributions
hmms = []
for feat in scaled_features:
    mod = PoissonHmm(feat, m)
    mod.fit(feat)
    hmms.append(mod)
a = hmms[0]
hmms[0].params
hmms[1].params
hmms[2].params<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13365155131264916, 'fraction_numerical': 0.02426412092283214, 'mean_word_length': 5.134146341463414, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '641078', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 972, 'n_tokens_neox': 920, 'n_words': 209, 'path': 'notebooks/timbre_based_rhythm_feature.ipynb', 'repo_name': 'Teagum/cpa', 'size': '2514'}