Reconnaissance d'accords à l'aide du chromagramme de la bibliothèque de python librosa

C'est @namaozi. Cet article est eeic Advent Calendar 2016 Article du Jour 9 ** Partie 2 **.

Si vous voulez commencer à regarder à partir de ** Partie 2 ** soudainement, veuillez d'abord lire ** Partie 1 **.

La dernière fois, j'ai réalisé un spectrogramme pour visualiser le signal musical.

Cette fois en utilisant un chromagramme

Cet exemple de source sonore

Contestons la reconnaissance d'accord de.

Ce que vous voulez faire dans cet article

Remarquer

J'utiliserai la bibliothèque.

[Partie 1] Dans (), j'ai implémenté le spectrogramme en utilisant uniquement numpy, mais si j'ai implémenté la reconnaissance d'accords du chromagramme, la précision était trop poubelle, donc je me fie à la bibliothèque. Je vais décider </ font>, c'est une histoire pitoyable ... (´ ・ _ ・ `)

Donc, dans cet article, j'utiliserai la bibliothèque avancée d'analyse de signal vocal python ** librosa ** pour obtenir le chromagramme et reconnaître les accords. Faisons le. Si vous voulez l'essayer, veuillez d'abord installer librosa à partir du lien.

J'utilise python2.7

Je suis vraiment désolé, mais j'utilise python2.7 dans cet exemple ... J'aimerais bientôt prendre en charge la version 3.0.

Problème de langue

Il y a différents termes musicaux, mais je pense qu'il est normal de passer par les bases si vous ne comprenez pas. Si vous êtes intéressé, veuillez vous référer au lien. Pour le moment, ce n'est pas grave si vous savez que ** l'accord est un accord et que l'accord nommé est un accord **.

Qu'est-ce que la reconnaissance d'accords?

** Une tâche qui permet à l'ordinateur de copier la progression du code **.

En fait, la tâche d'estimer les accords est un problème très difficile et la recherche est toujours en cours. Bien que la précision se soit améliorée d'année en année, elle n'a pas encore atteint le stade d'écoute des accords avec autant de souplesse qu'un être humain entraîné.

Si vous voulez en savoir plus, veuillez lire Articles par ici. Le chromagramme à traiter cette fois est également écrit. Pour la dernière méthode, voir ce blog.

En fait, l'implémentation utilisant ** Hidden Markov Model (HMM) est la norme, mais comme elle est difficile à implémenter, je voudrais contester la reconnaissance de code en utilisant uniquement le chromagramme en version simplifiée cette fois.

Qu'est-ce qu'un chromagramme?

Chromagram fournit de l'énergie pour toutes les bandes de fréquences [C, Db, D, Eb, E, F, Gb, G, Ab, A, Bb, B ], C'est une visualisation des composants sonores dans une certaine tranche de temps. Je vais expliquer avec une image du wiki anglais.

chromagram

(a) est une partition dans laquelle les sons des touches blanches de la gamme en do majeur, le soi-disant piano, sont alignés. (b) devient le vecteur de chrominance théorique correspondant à (a), mais si vous créez un chromagramme à partir de (c), qui est la forme d'onde du son réellement joué sur l'échelle de do majeur (do majeur), (d) On dirait. En tant qu'image, est-ce ** le sentiment que tous les signaux musicaux sont poussés dans une octave du piano roll **?

Comme le signal à chaque instant peut être exprimé par la force des 12 composantes sonores, il est également appelé ** vecteur de chrominance **.

Comment faites-vous cela après tout?

Comment reconnaissez-vous le code?

** "La quantité de chromagramme du signal musical est similaire au vecteur de chrominance d'accord souhaité" **

Le code pour chaque fois sera décidé en fonction de. Plus précisément, la procédure est la suivante.

** 1. ** Créez un vecteur de chrominance (vecteur de modèle) pour le code que vous souhaitez reconnaître

** 2. ** Créez un chromagramme de chanson

** 3. ** Calculez la similitude entre le chromagramme et le vecteur modèle à chaque fois, et estimez le code avec la plus grande similitude avec le code à ce moment.

1. Créez un modèle de vecteur

Tout d'abord, créez un vecteur de chrominance idéal pour l'accord (accord) que vous souhaitez reconnaître. Dans ce qui suit, nous désignerons ces vecteurs de chrominance idéaux comme des ** vecteurs modèles **.

Par exemple, Code diatonique est un vecteur modèle qui ressemble à la figure ci-dessous. À propos, un accord diatonique est un accord dans lequel les sons constitutifs d'un certain ton sont accumulés trois fois, c'est-à-dire en sautant un (il y a des accords diatoniques dans chaque majeur et mineur, mais l'image ci-dessous est en majeur).

diatonic_chroma2.png

À propos, la couleur du vecteur de chrominance dans l'image ci-dessus est différente même s'il était noir auparavant, car la somme des puissances de chaque classe de hauteur à un certain moment est alignée sur 1.

La formule au bas de l'image ci-dessus est la formule représentant le vecteur modèle du code majeur en C. 12 types de [Pitch Class] pour chaque dimension (https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%83%E3%83%81%E3%82%AF%E3% Cela correspond à 83% A9% E3% 82% B9), et il monte d'une demi-note dans l'ordre de C.

2.Faites un chromagramme

Faites le chromagramme introduit plus tôt. Fiez-vous à la bibliothèque de la bibliothèque de Dieu. En remarque, j'analyse les composants percussifs séparés. Si vous êtes curieux de savoir ce que vous faites à l'intérieur, allez sur God Document Se il vous plaît se référer.

Le code est sur GitHub, alors essayez-le. https://github.com/namaozi/ChromagramSample

functions.py



def librosa_chroma(file_path="audios/harmony1.wav", sr=44100):
    #importer(Ne peut pas être utilisé sans installation)
    import librosa

    #Lis(sr:Taux d'échantillonnage)
    y, sr = librosa.load(file_path, sr=sr)

    #Diviser en composante musicale et composante percussive
    y_harmonic, y_percussive = librosa.effects.hpss(y)

    #Calculer le chromagramme
    C = librosa.feature.chroma_cens(y=y_harmonic, sr=sr)

    #Terrain
    plt.figure(figsize=(12,4))
    librosa.display.specshow(C, sr=sr, x_axis='time', y_axis='chroma', vmin=0, vmax=1)
    plt.title('Chromagram')
    plt.colorbar()
    plt.tight_layout()
    plt.show()

    return C
###

Vous pouvez calculer le chromagramme en quelques lignes seulement. Ha dieu de la bibliothèque ... Ce qui suit est le chromagramme obtenu. harmony1_chroma.png

Cet exemple de source sonore est BPM120

chord_types.png

L'accord est prolongé de 4 temps, soit 2 secondes. Si vous regardez le chromagramme obtenu, vous pouvez voir que la nuance de couleur change au moment du changement d'accord toutes les 2 secondes et que la composante sonore du signal change. [^ 1]

De plus, par exemple, le troisième, le chromagramme de l'accord de sol majeur entre 4 secondes et 6 secondes, a une couleur plus foncée dans la partie ** D, G, B **, qui est le son constitutif de l'accord ** G majeur. Rencontre **. Il semble que vous puissiez comprendre le code simplement en regardant le chromagramme![^ 2]

[^ 1]: En fait, il est nécessaire de déterminer d'où et vers quelle section se trouve le code, mais dans cet exemple de source sonore, le code change toutes les 2 secondes, alors donnez cette information au programme. Je vais finir.

[^ 2]: Si vous êtes intéressé, quelques exemples de sources sonores sont placés dans le dossier audios, il peut donc être intéressant de les écouter et de faire un chromagramme. Alors que l'harmonie1.wav n'était que des accords d'orgue et de batterie, Harmony2.wav ajoutait des basses et Harmony3.wav devenait une source sonore avec une mélodie supplémentaire. Lorsque vous regardez réellement le chromagramme, la partie correspondant à la mélodie ou au son de basse devrait apparaître plus sombre.

3. Estimation du code

Tout ce que vous avez à faire est d'estimer le code le long de l'axe du temps.

chordestimation.py


#coding:utf-8
from collections import OrderedDict
import numpy as np
import matplotlib.pyplot as plt
import librosa #Se il vous plaît installer!

import soundanalysis as sa

file_path = "audios/"
file_name = "harmony1.wav"

#Demandez un chromagramme
chroma = sa.librosa_chroma(file_path + file_name)

TONES = 12 #Classe de pitch,Nombre de types de sons
sampling_rate = 44100 #Dépend de la source sonore

# "Avec ce paramètre",Il vous sera demandé de définir l'axe du temps comme ceci
# (Veuillez lire la documentation pour plus de détails)
time_unit = 512.0 / 44100 #1 longueur de chromagramme de cadre
# stop = time_unit * (chroma.shape[1] - 1)
stop = time_unit * (chroma.shape[1])
time_ruler = np.arange(0, stop, time_unit)

###Vecteur de modèle de code
#Ne considérez que les majors et les mineurs
#Code du muscle cérébral,Je n'ai pas eu le temps ...
#J'utilise Ordered Dict car je souhaite conserver la commande
one_third = 1.0/3
chord_dic = OrderedDict()
chord_dic["C"] = [one_third, 0,0,0, one_third, 0,0, one_third, 0,0,0,0]
chord_dic["Db"] = [0, one_third, 0,0,0, one_third, 0,0, one_third, 0,0,0]
chord_dic["D"] = [0,0, one_third, 0,0,0, one_third, 0,0, one_third, 0,0]
chord_dic["Eb"] = [0,0,0, one_third, 0,0,0, one_third, 0,0, one_third, 0]
chord_dic["E"] = [0,0,0,0, one_third, 0,0,0, one_third, 0,0, one_third]
chord_dic["F"] = [one_third, 0,0,0,0, one_third, 0,0,0, one_third, 0,0]
chord_dic["Gb"] = [0, one_third, 0,0,0,0, one_third, 0,0,0, one_third, 0]
chord_dic["G"] = [0,0, one_third, 0,0,0,0, one_third, 0,0,0, one_third]
chord_dic["Ab"] = [one_third, 0,0, one_third, 0,0,0,0, one_third, 0,0,0]
chord_dic["A"] = [0, one_third, 0,0, one_third, 0,0,0,0, one_third, 0,0]
chord_dic["Bb"] = [0,0, one_third, 0,0, one_third, 0,0,0,0, one_third, 0]
chord_dic["B"] = [0,0,0, one_third, 0,0, one_third, 0,0,0,0, one_third]
chord_dic["Cm"] = [one_third, 0,0, one_third, 0,0,0, one_third, 0,0,0,0]
chord_dic["Dbm"] = [0, one_third, 0,0, one_third, 0,0,0, one_third, 0,0,0]
chord_dic["Dm"] = [0,0, one_third, 0,0, one_third, 0,0,0, one_third, 0,0]
chord_dic["Ebm"] = [0,0,0, one_third, 0,0, one_third, 0,0,0, one_third, 0]
chord_dic["Em"] = [0,0,0,0, one_third, 0,0, one_third, 0,0,0, one_third]
chord_dic["Fm"] = [one_third, 0,0,0,0, one_third, 0,0, one_third, 0,0,0]
chord_dic["Gbm"] = [0, one_third, 0,0,0,0, one_third, 0,0, one_third, 0,0]
chord_dic["Gm"] = [0,0, one_third, 0,0,0,0, one_third, 0,0, one_third, 0]
chord_dic["Abm"] = [0,0,0, one_third, 0,0,0,0, one_third, 0,0, one_third]
chord_dic["Am"] = [one_third, 0,0,0, one_third, 0,0,0,0, one_third, 0,0]
chord_dic["Bbm"] = [0, one_third, 0,0,0, one_third, 0,0,0,0, one_third, 0]
chord_dic["Bm"] = [0,0, one_third, 0,0,0, one_third, 0,0,0,0, one_third]

prev_chord = 0
sum_chroma = np.zeros(TONES)
estimate_chords = []

result = np.zeros((TONES * 2, 8))

for time_index, time in enumerate(time_ruler):
    #Quel nombre de code analysez-vous maintenant?
    #Il change toutes les 2 secondes, donc divisez par 2 pour le trouver.
    nth_chord = int(time) / 2

    #Lors du passage aux 2 secondes suivantes,Estimer le code des 2 secondes précédentes
    if nth_chord != prev_chord:
        maximum = -100000
        this_chord = ""
        #Examiner le code qui maximise la similitude cosinus
        for chord_index, (name, vector) in enumerate(chord_dic.iteritems()):
            similarity = sa.cos_sim(sum_chroma, vector)
            result[chord_index][nth_chord - 1] = similarity
            if similarity > maximum:
                maximum = similarity
                this_chord = name
        #Stocke le code initialisé et estimé
        sum_chroma = np.zeros(TONES)
        estimate_chords.append(this_chord)

    else:
        #J'ajouterai en faisant attention à la forme de la chrominance
        for i in range(TONES):
            sum_chroma[i] += chroma[i][time_index]

    #mise à jour
    prev_chord = nth_chord
###

#Le résultat final
print estimate_chords


###Bonne chance
axis_x = np.arange(0, 16, 2)
bar_width = 0.07
colors = ["#ff9999", "#ffaf95","#fabb92","#ffd698","#fae991","#c1fc97","#97fac8","#96f9f5","#98e1fb","#9cb2ff","#b79bfe","#fa96f9", "#b36a6a", "#ab7361","#aa7d61","#ad9165","#b4a765","#8ab66b","#6ab48f","#68b0ad","#689fb3","#6979b0","#7462a3","#aa62a9"]
for i, (name, vector) in enumerate(chord_dic.iteritems()):
    plt.bar(axis_x - ((axis_x[1] - axis_x[0]) * 0.45) + bar_width * i, result[i], color=colors[i], width = bar_width, label = name, align = "center")

plt.legend()
plt.xticks(axis_x + bar_width / 24)
plt.show()

Le résultat de l'exécution du code ci-dessus! !! !! chord_result.png

J'ai la chaîne de code! !! Le code pour Chanson entrée est chord_types.png

Cependant, cette fois, seuls les codes majeurs et mineurs peuvent être reconnus, de sorte que le second ** Dm7 ** (Ré mineur sept) ne peut pas produire la bonne réponse en premier lieu. Considérant que les sons constitutifs de Dm7 sont [D, F, A, C], s'il s'agit de D mineur ou de Fa majeur, il peut être reconnu tel quel. Dans la sortie, ** F majeur ** est obtenu, donc c'est presque correct. Le 7ème accord ** Am / E ** a également le même son constitutif que Am, donc la sortie Am est la bonne réponse.

De cette façon, la source sonore de l'échantillon "harmonie1.wav" a pu produire presque la bonne réponse pour tous les codes en utilisant le chromagramme et le vecteur modèle! </ font> Félicitations. [^ 3]

[^ 3]: Malheureusement, il est peu probable qu'une chanson dans le monde réel puisse être si bien copiée à partir d'un simple chromagramme. Harmony1.wav avait une composition très simple d'accords + batterie uniquement, mais de nombreuses chansons du monde réel sont des chansons compliquées utilisant un nombre infini de pistes. Il est encore plus difficile d'estimer les accords car il est fortement affecté par la mélodie de la voix chantée. Comme mentionné dans la note de bas de page 1, il est également difficile d'estimer «quel intervalle est l'accord», ce qui rend la tâche d'analyse d'accord encore plus difficile.

La figure ci-dessous trace la similitude avec tous les codes de chaque section (vous pouvez l'obtenir en exécutant le programme ci-dessus), ce qui n'est pas une visualisation très propre, mais ... similarity_distribution.png

En regardant ce chiffre (faites de votre mieux), par exemple, dans la première section de 0 à 2 secondes, la similitude de ** C ** est la plus élevée, mais en plus de cela, ** Cm ** du même accord principal. Vous pouvez voir que la similitude est également élevée dans les accords principaux parallèles ** Am ** et les accords principaux du genre (IIIm) ** Em **.

Vous pouvez voir que les similitudes des accords principaux du ton relationnel sont similaires de cette manière </ font>. Il peut être intéressant de reconsidérer la théorie musicale à partir d'une telle interprétation mathématique.

Résumé

--python est bon --librosa le plus fort

  • Voyons si la bibliothèque peut le faire avant de l'implémenter vous-même
  • La reconnaissance de code est assez difficile même avec la bibliothèque la plus puissante

Recommended Posts