Intelligence artificielle

isoler les voix de la musique stéréo à l'aide de réseaux de neurones à convolution

isoler les voix de la musique stéréo à l'aide de réseaux de neurones à convolution


De A à Z

Ok, maintenant que j’ai fini de prêcher, parlons de ce que vous êtes venu chercher! Comme pour tous les autres problèmes de données sur lesquels j’ai travaillé au cours de ma carrière, je commencerai par poser la question “À quoi ressemblent les données”?. Jetons un coup d’œil à l’extrait suivant de voix chantée d’un enregistrement original en studio.

Ariana Grande, chanteuse de studio «One Last Time»

Pas trop intéressant non? Eh bien, c'est parce que nous visualisons la forme d'onde ou signal de domaine temporel, où nous n’avons accès qu’aux valeurs d’amplitude du signal dans le temps. Nous pourrions extraire des choses comme les enveloppes, les valeurs RMS, le taux de passage par zéro, etc., mais ces fonctionnalités sont aussi primitif et pas assez discriminant pour nous aider à résoudre le problème. Si nous voulons extraire le contenu vocal d'un mix, nous devrions en quelque sorte exposer la structure de la parole humaine, pour commencer. Heureusement, la transformée de Fourier à court terme (STFT) vient à la rescousse.

Spectre d'amplitude STFT - taille de la fenêtre = 2048, chevauchement = 75%, fréquence logarithmique [Sonic Visualizer]

Bien que j'adore le traitement de la parole et que j'apprécie beaucoup modélisation par filtre source, cepstre, fréquences, LPC, MFCC et cetera, je vais sauter tout ça et me concentrer sur les éléments centraux liés à notre problème, afin que cet article soit digérable par le plus grand nombre de personnes possible et non exclusivement par la communauté Audio Signal Processing / Speech.

Alors, que nous dit la structure de la parole humaine?

Eh bien, il y a 3 éléments principaux que nous pouvons identifier ici:

  • UNE la fréquence fondamentale (f0), déterminé par la fréquence de vibration de nos cordes vocales. Dans ce cas, Ariana chante dans la gamme 300–500 Hz.
  • Un nombre de harmoniques au-dessus de f0, suivant une forme ou un motif similaire. Ces harmoniques se produisent à des multiples entiers de f0.
  • sourd la parole, qui comprend des consonnes comme «T», «p», «k», ‘S’ (qui ne sont pas produits par la vibration de nos cordes vocales), nos respirations, etc. Ils se manifestent par de courtes impulsions dans la région des hautes fréquences.

Un premier coup avec une approche basée sur des règles

Oublions un instant cette chose appelée Apprentissage automatique. Sur la base de notre connaissance des données, pouvons-nous trouver une méthode pour extraire notre voix? Laissez-moi essayer…

Naïve isolement vocal V1.0:

  1. Identifier les sections vocales. Il se passe beaucoup de choses dans un mix. Nous voulons nous concentrer sur les sections contenant du contenu vocal et ignorer le reste.
  2. Faites la distinction entre les sections vocales et non vocales. Comme nous l’avons vu, les discours exprimés sont très différents des discours non prononcés. Ils ont donc probablement besoin d’un traitement différent.
  3. Estimer la fréquence du fondamental dans le temps.
  4. En fonction de la sortie 3, appliquez une sorte de masque pour capturer le contenu harmonique.
  5. Faites autre chose avec les sections non vocalisées…

Si nous faisons un travail décent, le résultat de ce processus devrait être un doux ou binaire masque cela, lorsqu'il est appliqué (multiplication élément par élément) à la magnitude STFT du mixage, nous donne une reconstruction approximative de la magnitude STFT du chant. À partir de là, nous combinons ensuite cette estimation STFT vocale avec les informations de phase du mixage d'origine, calculons une STFT inverse et obtenons le signal temporel des voix reconstituées.

Cela fait déjà beaucoup de travail. Mais pour les besoins de la démonstration, nous allons utiliser une implémentation de l’algorithme pYIN. Même si cela est destiné à la résolution de l’étape 3, avec les bonnes contraintes, il prend en charge les tâches 1 et 2 de manière décente, tout en traquant les fondamentaux vocaux même en présence de musique. L'exemple ci-dessous contient le résultat de cette approche, sans aborder les sections non exprimées.

Bien…? Cela a en quelque sorte fonctionné, mais la qualité de la voix récupérée n’est pas encore au rendez-vous. Peut-être qu'avec du temps, de l'énergie et un budget supplémentaires, nous pourrons améliorer cette méthode et l'améliorer.

Maintenant laissez-moi vous demander…

Qu'est-ce qui se passe quand vous avez plusieurs voix, ce qui est certainement le cas dans au moins 50% des titres produits par des professionnels de nos jours?

Que se passe-t-il lorsque les voix ont été traitées avec réverbération, retards et d'autres effets? Jetons un coup d’œil au dernier choeur de Ariana Grande Une dernière fois.

Vous sentez-vous déjà la douleur…? Je suis.

Très vite, des méthodes ad hoc comme celle décrite ci-dessus deviennent un château de cartes. Le problème est trop complexe. Il y a trop de règles, trop d'exceptions aux règles et trop de conditions variables (effets et paramètres de mixage différents). L'approche en plusieurs étapes implique également que les erreurs d'une étape propagent les problèmes à l'étape suivante. Améliorer chaque étape serait très coûteux, il faudrait un grand nombre d'itérations pour bien faire et, dernier élément, nous aboutirions probablement à un pipeline coûteux en calcul, ce qui en soi peut être un facteur décisif.

C’est le genre de scénarios dans lesquels nous devons commencer à penser à une plus grande de bout en bout approche et laissez ML déterminer - en partie - les processus et opérations sous-jacents nécessaires à la résolution du problème. Cependant, nous ne jetons pas la serviette en matière d’ingénierie des fonctionnalités et vous comprendrez pourquoi.

L'hypothèse: on peut utiliser un CNN comme fonction de transfert qui transforme les mixages en voix

Inspiré par les réalisations de CNN sur les images naturelles, pourquoi ne pas appliquer le même raisonnement ici?

Les CNN ont réussi à des tâches telles que la colorisation, le flou et la super résolution des images.

En fin de journée, nous savons que nous pouvons représenter un signal audio «sous forme d'image»." en utilisant le droit de transformation de Fourier à court terme? Même si ces l'audio images Si vous ne suivez pas la distribution statistique des images naturelles, elles exposent toujours des schémas spatiaux (dans l’espace temps-fréquence) dont nous devrions pouvoir tirer des enseignements.

Mix: vous pouvez voir la grosse caisse et la ligne de base en bas, et certains synthés au milieu se mêlant au chant. A droite, les voix correspondantes uniquement

À l'époque, la validation de cette expérience était une entreprise coûteuse, car obtenir ou générer les données de formation nécessaires représentait déjà un investissement important. L’une des pratiques que j’essaie toujours d’appliquer en recherche appliquée est de commencer par: identifier un problème plus simple qui valide les mêmes principes comme l'original, mais cela ne nécessite pas autant de travail. Cela vous permet de réduire la taille de vos hypothèses, d'effectuer une itération plus rapidement et de pivoter avec un impact minimal lorsque les choses ne fonctionnent pas comme prévu.

Une condition implicite du bon fonctionnement de la solution initiale est la suivante: CNN doit être capable de comprendre la structure de la parole humaine. Un problème plus simple peut alors être: à partir d’un fragment de mixage, voyons si un CNN peut classer ces fragments comme contenant du contenu vocal ou non.. Nous recherchons un détecteur d'activité vocale (VAD) robuste en musique, implémenté comme classificateur binaire.

Concevoir notre espace de fonctionnalités

Nous savons que les signaux audio tels que la musique et la parole humaine intègrent des dépendances temporelles. En termes simples, rien ne se produit de manière isolée à un moment donné. Si je veux savoir si une section audio donnée contient de la parole humaine ou non, je devrais probablement aussi regarder les régions voisines. Cette contexte temporel peut me donner de bonnes informations sur ce qui se passe dans la région d’intérêt. Dans le même temps, nous souhaitons effectuer notre classification par très petites incréments de temps, afin de pouvoir capturer la voix humaine avec la résolution temporelle la plus élevée possible.

Faisons quelques chiffres…

  • Taux d'échantillonnage (fs): 22050 Hz (nous sous-échantillonnons de 44100 à 22050)
  • Conception STFT: taille de la fenêtre = 1024, taille du saut = 256, interpolation de l'échelle Mel pour la pondération perceptuelle. Depuis nos données d'entrée est réal, nous pouvons travailler avec une moitié de la STFT (le pourquoi est hors du champ de cet article…) tout en conservant la composante CC (et non une exigence), ce qui nous donne 513 fréquences.
  • Résolution de classification cible: une seule trame STFT (~ 11,6 millisecondes = 256/22050)
  • Contexte temporel cible: ~ 300 millisecondes = 25 trames STFT.
  • Nombre cible d'exemples de formation: 0,5 million
  • En supposant que nous utilisions une fenêtre glissante avec un pas de temps de 1 STFT pour générer nos données d'entraînement, nous avons besoin d'environ 1,6 heure de son étiqueté pour générer nos 0,5M d'échantillons de données. [if you’d like to know more details about generating the actual dataset, please feel free to ask in the comments]

Avec les exigences ci-dessus, les données d'entrée / sortie de notre classificateur binaire se présentent comme suit:

Le modèle

En utilisant Keras, nous pouvons construire un petit modèle CNN pour valider notre hypothèse.

importer des keras
depuis keras.models import Sequential
de keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
de keras.optimizers importer SGD
depuis keras.layers.advanced_activations importer LeakyReLU
modèle = séquentiel ()
model.add (Conv2D (16, (3,3), padding = 'identique', input_shape = (513, 25, 1)))
model.add (LeakyReLU ())
model.add (Conv2D (16, (3,3), padding = 'same'))
model.add (LeakyReLU ())
model.add (MaxPooling2D (pool_size = (3,3)))
model.add (abandon (0,25))
model.add (Conv2D (16, (3,3), padding = 'same'))
model.add (LeakyReLU ())
model.add (Conv2D (16, (3,3), padding = 'same'))
model.add (LeakyReLU ())
model.add (MaxPooling2D (pool_size = (3,3)))
model.add (abandon (0,25))
model.add (Flatten ())
model.add (Dense (64))
model.add (LeakyReLU ())
model.add (abandon (0.5))
model.add (Dense (1, activation = 'sigmoid'))
sgd = SGD (lr = 0.001, decay = 1e-6, momentum = 0.9, nesterov = True)
model.compile (loss = keras.losses.binary_crossentropy, optimiseur = sgd, métriques =['accuracy'])

Avec une répartition de 80/20 train-test et après environ 50 périodes, nous atteignons ~97% de précision du testCela signifie que notre modèle CNN peut établir une distinction entre les sections de musique contenant un contenu vocal et les sections de musique sans contenu vocal. En inspectant certaines des cartes de caractéristiques issues de notre 4ème couche convolutive, il semble que notre réseau ait optimisé ses noyaux pour effectuer 2 tâches: filtrer la musique et filtrer les voix…

Exemples de cartes de caractéristiques à la sortie de la 4ème conv. couche. Apparemment, la sortie de gauche est le résultat d’une combinaison d’opérations du noyau qui tentent de préserver le contenu vocal tout en ignorant la musique. Les valeurs élevées ressemblent à la structure harmonique de la parole humaine. La carte des fonctionnalités de droite semble résulter de la tâche opposée.

De VAD à la séparation de la source

Maintenant que nous avons validé ce problème de classification plus simple, comment passer de la détection de l’activité vocale à la musique à l’isolation des voix? Eh bien, en récupérant quelques idées de notre naïve méthode décrite au début, nous souhaitons toujours obtenir une estimation du spectrogramme de magnitude de la voix. Cela devient maintenant un problème de régression. Ce que nous voulons faire, c’est, compte tenu du cadre temporel de la table STFT du mixage, estimer le spectre de magnitude du cadre temporel vocal correspondant.

Qu'en est-il de l'ensemble de formation? (vous pourriez vous demander à ce stade)

Oh Seigneur… c'était quelque chose. Je vais en parler à la fin de l’article pour ne pas encore changer de contexte!

Si notre modèle apprend bien, pendant l'inférence, tout ce que nous avons à faire est d'implémenter une simple fenêtre glissante sur la STFT du mélange. Après chaque prédiction, nous déplaçons notre fenêtre vers la droite d'un intervalle de temps, prédisons le prochain cadre vocal et le concaténons avec la prédiction précédente. En ce qui concerne le modèle, nous pouvons commencer par utiliser le même modèle que celui utilisé pour VAD comme base et en effectuant quelques modifications (la forme de la sortie est maintenant (513,1), activation linéaire à la sortie, MSE en tant que fonction de perte), peut commencer notre formation.

Ne réclamez pas encore la victoire…

Bien que la représentation entrée / sortie ci-dessus ait un sens, après avoir formé notre modèle de séparation vocale à plusieurs reprises, avec des paramètres variables et des normalisations de données, les résultats ne sont pas encore là. Il semble que nous en demandions trop…

Nous sommes passés d'un classificateur binaire à essayer de le faire régression sur un vecteur de 513 dimensions. Bien que le réseau apprenne la tâche dans une certaine mesure, après avoir reconstitué le signal du domaine temporel de la voix, il existe des artefacts et des interférences évidents provenant d’autres sources. Même après avoir ajouté plusieurs couches et augmenté le nombre de paramètres du modèle, les résultats ne changent pas beaucoup. La question est alors devenue: pouvons-nous tromper le réseau en en pensant c'est résoudre un problème plus simple et toujours atteindre les résultats souhaités?

Et si au lieu d’essayer d’estimer la magnitude de la voix STFT, nous formions le réseau pour apprendre une masque binaire que, appliqué à la STFT du mélange, nous donne un aperçu simplifié mais perceptuellement acceptable sur reconstruction estimation du spectrogramme de magnitude de la voix?

En expérimentant différentes heuristiques, nous avons mis au point un moyen très simple (et certainement peu orthodoxe du point de vue du traitement du signal…) d'extraire des voix à partir de mixages à l'aide de masques binaires. Sans trop entrer dans les détails, nous allons considérer la sortie comme un binaire image où, la valeur «1» indique présence prédominante de contenu vocal à une fréquence et à un laps de temps donnés, et une valeur de «0» indique une présence prédominante de musique à l’emplacement donné. On peut appeler ça binarisation perceptuelle, juste pour trouver un nom. Pour être honnête, visuellement, cela ne semble pas très attrayant, mais lors de la reconstruction du signal dans le domaine temporel, les résultats sont étonnamment bons.

Notre problème devient maintenant une sorte d'hybride de classification par régression (prenez ceci avec un grain de sel…). Nous demandons au modèle de «classer les pixelsà la sortie, vocale ou non vocale, bien que conceptuellement (et également en ce qui concerne la fonction de perte utilisée -MSE-), la tâche reste une régression.

Bien que la distinction puisse ne pas sembler pertinente pour certains, elle influe considérablement sur la capacité du modèle à apprendre la tâche assignée, la seconde étant beaucoup plus simple et contrainte. En même temps, cela nous permet de garder notre modèle relativement petit en termes de nombre de paramètres, compte tenu de la complexité de la tâche, ce qui est hautement souhaité pour un fonctionnement en temps réel, ce qui était une exigence de conception dans ce cas. Après quelques ajustements mineurs, le modèle final ressemble à ceci.

Comment reconstruisons-nous le signal dans le domaine temporel?

Fondamentalement, comme décrit dans le naïve méthode section. Dans ce cas, à chaque passage d’inférence que nous effectuons, nous prédisons une seule période de temps pour le masque binaire de la voix. Encore une fois, en mettant en place une simple fenêtre glissante avec un pas d'un temps, nous continuons d'estimer et de concaténer des délais consécutifs, qui finissent par constituer l'ensemble du masque binaire vocal.

Création du kit de formation

Comme vous le savez, l’un des problèmes majeurs de l’apprentissage machine supervisé (à part tous les exemples de jouets pour lesquels des jeux de données sont disponibles) est de disposer des données appropriées (quantité et qualité) pour le problème particulier que vous essayez de résoudre. Sur la base des représentations d'entrée / sortie décrites, pour former notre modèle, nous avons tout d'abord besoin d'un nombre important de mixages et de leurs pistes vocales correspondantes parfaitement alignées et normalisées. Il existe plus d’un moyen de construire cet ensemble de données et nous avons utilisé ici une combinaison de stratégies, allant de la création manuelle de paires <> vocales avec des acapellas trouvés en ligne, à la recherche de tiges RockBand, en passant par le web pour supprimer YouTube. Pour vous donner une idée de ce processus fastidieux et fastidieux, notre «projet de jeu de données» a consisté à créer un outil permettant de créer automatiquement des paires <> de voix, comme illustré ci-dessous:

Nous savions qu'il nous fallait une bonne quantité de données pour que le réseau connaisse la fonction de transfert nécessaire pour mapper les mixages en voix. Notre dernier ensemble de données consistait en environ 15 millions d’exemples de fragments de mixages d’environ 300 millisecondes et leurs masques binaires vocaux correspondants.

Architecture de pipeline

Comme vous le savez probablement, la création d’un modèle d’apprentissage automatique pour une tâche donnée n’est qu’une partie de la transaction. Dans le monde réel, nous devons réfléchir à l’architecture logicielle, en particulier lorsque nous traitons avec le temps réel.

Pour ce problème particulier, la reconstruction dans le domaine temporel peut être effectuée en une seule fois après la prédiction d’un masque binaire vocal complet (mode hors connexion) ou, ce qui est plus intéressant, dans le cadre d’un pipeline multithread où l’acquisition, le traitement, la reconstruction et la lecture se font par petits fichiers. segments, ce qui permet une diffusion conviviale et même une capacité de déconstruction en temps réel de la musique enregistrée à la volée, avec une latence minimale. Etant donné qu’il s’agit d’un sujet entier, je vais le laisser pour un autre article consacré à Pipelines ML en temps réel

Je pense que j'en ai assez couvert, alors pourquoi n'écoutons-nous pas quelques exemples de plus!?

Daft Punk - Get Lucky (Studio)

nous pouvons entendre quelques interférences minimes des tambours ici…

Adele - Mettez le feu à la pluie (enregistrement en direct!)

Remarquez comment, au tout début, notre modèle extrait les cris de la foule sous forme de contenu vocal :). Dans ce cas, nous avons des interférences supplémentaires provenant d’autres sources. Étant donné qu’il s’agit d’un enregistrement en direct, il est logique que cette voix extraite ne soit pas d’une aussi grande qualité que les précédentes.

Ok, il y a donc une dernière chose…

Étant donné que cela fonctionne pour la voix, pourquoi ne pas l'appliquer à d'autres instruments…?

Cet article est déjà assez complet, mais vu que vous en êtes arrivé là, je pensais que vous méritiez de voir une dernière démo. Avec le même raisonnement pour extraire le contenu vocal, nous pouvons essayer de scinder une piste stéréo en STEM (batterie, ligne de basse, voix, autres) en apportant quelques modifications à notre modèle et bien sûr, en disposant du kit de formation approprié :). Si les détails techniques de cette extension vous intéressent, laissez-moi quelques commentaires. J’envisagerai d’écrire une «partie 2» pour le cas de déconstruction STEM lorsque le temps le permettra!

Merci de votre lecture et n’hésitez pas à laisser des questions. Je vais continuer à écrire des articles sur Audio AI alors restez à l'écoute! Comme une remarque finale, comme vous pouvez le constater, le modèle CNN que nous avons créé n’est pas si particulier. Le succès de ce travail a été conduit en se concentrant sur la Ingénierie des fonctionnalités et en mettant en place un processus allégé pour la validation des hypothèses, un sujet sur lequel j’écrirai dans un avenir proche!

ps: remerciements à Naveen Rajashekharappa et à Karthiek Reddy Bokka pour leurs contributions à ce travail!

Show More

SupportIvy

SupportIvy.com : Un lieu pour partager le savoir et mieux comprendre le monde. Meilleure plate-forme de support gratuit pour vous, Documentation &Tutoriels par les experts.

Related Articles

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Close
Close