Reconnaissance de hauteur des notes de musique sur un téléphone intelligent
Avec des ressources limitées telles que des processeurs plus lents, la taille du code et la RAM, comment mieux détecter la hauteur d'une note musicale, semblable à ce qu'un tuner électronique ou logiciel ferait?
Dois-je utiliser:
- baiser FFT
- FFTW
- Transformée En Ondelettes Discrètes
- autocorrélation
- analyse du passage à zéro
- filtres espacés d'octave
Autres?
En un mot, ce que j'essaie de faire est de reconnaître une seule note de musique, deux octaves au-dessous du Do moyen à deux octaves au-dessus, joué sur n'importe quel instrument (raisonnable). Je voudrais être à moins de 20% du demi-ton - en d'autres termes, si l'utilisateur joue trop plat ou trop net, je dois le distinguer. Cependant, je n'aurai pas besoin de la précision requise pour le réglage.
5 réponses
Si vous n'avez pas besoin de beaucoup de précision, un FFT pourrait être suffisant. fenêtre le morceau d'audio d'abord afin que vous obteniez des pics bien définis, puis trouver le premier pic significatif.
Bin width = taux d'échantillonnage / taille FFT:
Les fondamentaux vont de 20 Hz à 7 kHz, donc un taux d'échantillonnage de 14 kHz serait suffisant. Le prochain taux d'échantillonnage" standard " est de 22050 Hz.
La taille de FFT est alors déterminée par la précision que vous voulez. FFT sortie est linéaire dans fréquence, tandis que les tonalités musicales sont logarithmiques en fréquence, de sorte que la précision du pire des cas sera aux basses fréquences. Pour 20% d'un demi-ton à 20 Hz, vous avez besoin d'une largeur de 1.2 Hz, ce qui signifie une FFT longueur de 18545. La puissance de deux est 215 = 32768. C'est 1.5 secondes de données, et prend le processeur de mon ordinateur portable 3 ms pour calculer.
Cela ne fonctionnera pas avec les signaux qui ont un " fondamental manquant ", et trouver le "premier pic significatif" est un peu difficile (puisque les harmoniques sont souvent plus élevés que les fondamentaux), mais vous pouvez trouver un moyen qui convient à votre situation.
L'autocorrélation et le spectre de produit harmonique {[2] } sont meilleurs pour trouver le vrai fondamental pour une vague au lieu de l'une des harmoniques, mais je ne pense pas qu'ils traitent aussi bien avec inharmonicité , et la plupart des instruments comme le piano ou la guitare sont inharmoniques (les harmoniques sont légèrement nettes de ce qu'elles devraient être). - Il vraiment dépend de votre situation, si.
En outre, vous pouvez économiser encore plus de cycles de processeur en calculant uniquement dans une bande de fréquence spécifique d'intérêt, en utilisant la transformation Chirp-Z .
J'ai écrit quelques méthodes différentes en Python à des fins de comparaison.
Si vous voulez faire la reconnaissance de hauteur en temps réel (et précis à moins de 1/100 d'un demi-ton), votre seul espoir réel est l'approche de passage à zéro. Et c'est un faible espoir, désolé de le dire. Le passage par zéro peut estimer la hauteur à partir de quelques longueurs d'onde de données, et cela peut être fait avec la puissance de traitement d'un smartphone, mais ce n'est pas particulièrement précis, car de petites erreurs dans la mesure des longueurs d'onde entraînent de grandes erreurs dans la fréquence estimée. Des appareils comme les synthétiseurs de guitare (qui déduire la hauteur d'une corde de guitare avec seulement quelques longueurs d'onde) travailler en quantifiant les mesures aux notes de l'échelle. Cela peut fonctionner pour vos besoins, mais sachez que le passage par zéro fonctionne très bien avec des formes d'onde simples, mais a tendance à fonctionner de moins en moins bien avec des sons d'instruments plus complexes.
Dans mon application (un synthétiseur logiciel qui fonctionne sur smartphones), j'utilise des enregistrements de notes d'instrument unique comme matière première pour la synthèse de table d'ondes, et afin de produire notes à une hauteur particulière, j'ai besoin de connaître la hauteur fondamentale d'un enregistrement, précise à moins de 1/1000 d'un demi-ton (je n'ai vraiment besoin que d'une précision de 1/100, mais je suis TOC à ce sujet). L'approche de passage par Zéro est Beaucoup {[4] } trop inexacte pour cela, et les approches basées sur la FFT sont soit trop inexactes, soit trop lentes (ou parfois les deux).
La meilleure approche que j'ai trouvée dans ce cas est d'utiliser l'autocorrélation. Avec l'autocorrélation vous devinez essentiellement le terrain puis mesurez l'autocorrélation de votre échantillon à cette longueur d'onde correspondante. En parcourant la gamme des hauteurs plausibles (par exemple A = 55 Hz à travers A = 880 Hz) par des demi-tons, Je localise la hauteur la plus corrélée, puis je fais un balayage plus fin dans le voisinage de cette hauteur pour obtenir une valeur plus précise.
L'approche qui vous convient le mieux dépend entièrement de ce que vous essayez d'utiliser.
Je ne suis pas familier avec toutes les méthodes que vous mentionnez, mais ce que vous choisissez devrait dépendre principalement de la nature de vos données d'entrée. Analysez-vous des tons purs, ou votre source d'entrée a-t-elle plusieurs notes? La parole est-elle une caractéristique de votre contribution? Y a-t-il des limites sur la durée pendant laquelle vous devez échantillonner l'entrée? Êtes-vous en mesure d'échanger une certaine précision pour la vitesse?
, dans une certaine mesure ce que vous choisissez dépend aussi si vous souhaitez effectuer vos calculs dans temps ou l'espace des fréquences. Convertir une série temporelle en une représentation de fréquence prend du temps, mais dans mon expérience tend à donner de meilleurs résultats.
L'Autocorrélation compare deux signaux dans le domaine temporel. Une implémentation naïve est simple mais relativement coûteuse à calculer, car elle nécessite une différenciation par paire entre tous les points des signaux d'origine et décalés dans le temps, suivie d'une différenciation pour identifier les points de retournement dans le fonction d'autocorrélation, puis sélection du minimum correspondant à la fréquence fondamentale. Il existe des méthodes alternatives. Par exemple, La Différence de Magnitude moyenne est une forme d'autocorrélation très bon marché, mais la précision en souffre. Toutes les techniques d'autocorrélation courent le risque d'erreurs d'octave, car des pics autres que le fondamental existent dans la fonction.
Mesurer les points de passage par zéro est simple et direct, mais rencontrera des problèmes si vous plusieurs formes d'onde présentes dans le signal.
Dans l'espace de fréquence, les techniques basées sur FFT {[4] } peuvent être assez efficaces pour vos besoins. Un exemple est la technique du spectre de produit harmonique, qui compare le spectre de puissance du signal avec des versions sous-échantillonnées à chaque harmonique, et identifie la hauteur en multipliant les spectres ensemble pour produire un pic clair.
Comme toujours, il n'y a pas de substitut pour tester et profiler plusieurs techniques, à empiriquement déterminez ce qui fonctionnera le mieux pour votre problème et vos contraintes.
Une réponse comme celle-ci ne peut que rayer la surface de ce sujet. En plus des liens précédents, voici quelques références pertinentes pour une lecture plus approfondie.
- résumé des algorithmes de détection de hauteur (Wikipedia)
- avantages et inconvénients de autocorrélation vs spectre de produit harmonique
- Un aperçu de haut niveau des méthodes de détection de hauteur
Dans mon projet danstuner, j'ai pris le code de Audacity. Il a essentiellement pris une FFT, puis a trouvé la puissance de crête en mettant une courbe cubique sur la FFT et en trouvant le pic de cette courbe. Fonctionne assez bien, même si je devais me prémunir contre le saut d'octave.
Voir Spectre.rpc.
Le passage par zéro ne fonctionnera pas car un son typique a des harmoniques et des passages par zéro beaucoup plus que la fréquence de base.
Quelque chose que j'ai expérimenté (en tant que projet côté maison) était ceci:
- échantillonnez le son avec ADC à la fréquence d'échantillonnage dont vous avez besoin.
- détecter les niveaux des pics positifs et négatifs à court terme de la forme d'onde (fenêtre coulissante ou similaire). I. e. un détecteur d'enveloppe.
- Faire une onde carrée qui va haut lorsque la forme d'onde va à l'intérieur 90% (ou plus) de l'enveloppe positive, et va bas quand la forme d'onde va dans 90% de l'enveloppe négative. C'est-à-dire une onde carrée de suivi avec hystérésis.
- mesurez la fréquence de cette onde carrée avec des calculs de comptage/temps simples, en utilisant autant d'échantillons que nécessaire pour obtenir la précision requise.
Cependant, j'ai trouvé qu'avec les entrées de mon clavier électronique, pour certains sons d'instrument, il a réussi à ramasser 2× la fréquence de base (octave suivante). C'était un side project et je n'ai jamais eu le temps de mettre en œuvre une solution avant de passer à d'autres choses. Mais je pensais qu'il avait la promesse d'être beaucoup moins de charge CPU que FFT.