32 votes

Remarque l'apparition de détection

Je suis en train d'élaborer un système d'aide aux musiciens de transcription. Le but est de réaliser automatique de la musique de transcription (il n'a pas à être parfait, car l'utilisateur de corriger les bugs / erreurs plus tard) sur un seul instrument monophonique l'enregistrement. Est-ce que quelqu'ont de l'expérience dans la musique automatique la transcription? Ou de traitement du signal numérique en général? L'aide de personne est grandement apprécié, peu importe ce que votre arrière-plan.

Jusqu'à présent j'ai étudié l'utilisation de la transformée de Fourier Rapide pour la détection de hauteur, et un certain nombre de tests dans les deux MATLAB et mon propre Java programmes de test ont montré qu'il était rapide et assez précis pour mes besoins. Un autre élément de la tâche à résoudre, c'est l'affichage des données MIDI dans la musique en feuilles de forme, mais c'est quelque chose que je ne suis pas concerné par la droite maintenant.

En bref, ce que je cherche, c'est une bonne méthode pour noter l'apparition de détection, c'est à dire la position dans le signal où une nouvelle note commence. Que la lenteur de déclenchement peuvent être très difficiles à détecter correctement, je vais d'abord utiliser le système avec des enregistrements au piano. C'est aussi en partie dû au fait que je joue du piano et devrait être dans une meilleure position pour obtenir adapté enregistrements pour les tests. Comme indiqué ci-dessus, les premières versions de ce système sera utilisé pour de simples enregistrements monophoniques, d'envisager d'aller plus tard à la plus complexe de l'entrée en fonction des progrès réalisés dans les semaines à venir.

50voto

MusiGenesis Points 49273

Voici un graphique qui illustre l'approche par seuil de noter l'apparition de détection:

alt text

Cette image montre un fichier WAV classique avec trois discrètes notes jouées dans la succession. La ligne rouge représente un choisi le seuil de signal, et les lignes bleues représentent note positions de départ retourné par un algorithme simple qui marque un début lorsque le niveau du signal franchit le seuil.

Comme le montre l'image, la sélection d'un bon seuil absolu est difficile. Dans ce cas, la première note est ramassé fine, la deuxième remarque est complètement raté, et la troisième note (à peine) est démarré très tard. En général, un seuil bas est une des causes de ramasser phantom notes, tout en relevant qu'il vous fait manquer des notes. Une solution à ce problème est d'utiliser un seuil relatif qui déclenche un début si le signal augmente d'un certain pourcentage d'un certain temps, mais cela a ses propres problèmes.

Une solution plus simple est d'utiliser les un peu contre toute attente intuitive nommé compression (pas de compression MP3 - c'est une tout autre chose) sur le fichier wave en premier. La Compression permet d'aplanir les pointes de vos données audio et l'amplifie tout, de sorte que plus de l'audio est proche du maximum des valeurs. L'effet sur l'exemple ci-dessus devrait ressembler à ceci (qui montre pourquoi le nom de "compression" semble n'avoir aucun sens - sur l'équipement audio, il est habituellement l'étiquette de "loudness"):

alt text

Après la compression, le seuil absolu approche fonctionnera beaucoup mieux (même si c'est facile à comprimer et commencer à ramasser fiction note commence, le même effet que l'abaissement du seuil). Il y a beaucoup de vagues éditeurs qui font un bon travail de compression, et c'est mieux de les laisser gérer cette tâche, vous aurez probablement besoin de faire une bonne quantité de travail de "nettoyage" de vos fichiers wave avant de détecter des notes en eux de toute façon.

Dans le codage des termes, un fichier WAV chargé dans la mémoire est essentiellement juste un tableau de deux octets entiers, où 0 représente l'absence de signal et 32 767 et de -32 768 représentent les sommets. Dans sa forme la plus simple, un seuil de détection de l'algorithme serait juste de commencer à le premier échantillon et de lire à travers le tableau jusqu'à trouver une valeur supérieure au seuil.

short threshold = 10000;
for (int i = 0; i < samples.Length; i++)
{
    if ((short)Math.Abs(samples[i]) > threshold) 
    {
        // here is one note onset point
    }
}

Dans la pratique, cela fonctionne terriblement, depuis audio normale a toutes sortes de transitoire des pointes au-dessus d'un seuil donné. Une solution consiste à utiliser un moyen de la force du signal (c'est à dire ne marque pas commencer jusqu'à ce que la moyenne des n derniers échantillons au-dessus du seuil).

short threshold = 10000;
int window_length = 100;
int running_total = 0;
// tally up the first window_length samples
for (int i = 0; i < window_length; i++)
{
    running_total += samples[i];
}
// calculate moving average
for (int i = window_length; i < samples.Length; i++)
{
    // remove oldest sample and add current
    running_total -= samples[i - window_length];
    running_total += samples[i];
    short moving_average = running_total / window_length;
    if (moving_average > threshold)
    {
        // here is one note onset point 
        int onset_point = i - (window_length / 2);
    }
}

Tout cela demande beaucoup de réglages et de jouer avec les réglages à faire pour trouver les positions de départ d'un fichier WAV avec précision, et généralement ce qui fonctionne pour l'un ne va pas très bien fonctionner sur un autre. C'est très difficile et n'est pas parfaitement résolu le problème de domaine que vous avez choisi, mais je pense que c'est cool que vous êtes en essayant de l'attaquer.

Mise à jour: ce graphique montre un détail de la détection des notes j'ai laissé de côté, à savoir détecter quand la note de fin:

alt text

La ligne jaune représente le hors-seuil. Une fois que l'algorithme a détecté une note de commencer, il suppose que la note se poursuit jusqu'à ce que la moyenne de la force du signal tombe en dessous de cette valeur (illustré ici par les lignes violettes). C'est, bien sûr, une autre source de difficultés, comme c'est le cas où deux ou plusieurs notes se chevauchent (polyphonie).

Une fois que vous avez détecté le départ et les points d'arrêt de chaque note, vous pouvez désormais analyser chaque tranche de WAV fichier de données pour déterminer les emplacements.

Mise à jour 2: je viens de lire la mise à jour de votre question. Hauteur de détection par le biais de l'auto-corrélation est beaucoup plus facile à mettre en œuvre que FFT si vous écrivez votre propre à partir de zéro, mais si vous avez déjà extrait et utilisé un pré-construit FFT bibliothèque, vous feriez mieux de les utiliser pour vous. Une fois que vous avez identifié le démarrer et d'arrêter des positions de chaque note (et inclus quelques rembourrage au début et à la fin de l'manqué d'attaque et de relâchement des parties), vous pouvez maintenant sortir chaque tranche de données audio et de le transmettre à une fonction FFT de déterminer la hauteur.

Un point important ici est de ne pas utiliser une tranche de la compression de données audio, mais plutôt d'utiliser une tranche de l'original, non modifiée de données. Le processus de compression déforme l'audio et peut produire une mauvaise hauteur de lecture.

Un dernier point à propos de la note d'attaque de temps, c'est qu'il est peut-être moins un problème que vous ne le pensez. Souvent dans de la musique d'un instrument avec une attaque lente (comme un synthé virtuel) va commencer une note antérieure à une forte attaque de l'instrument (comme un piano) et deux notes de son comme si ils commencent à la même heure. Si vous jouez des instruments de cette manière, l'algorithme avec les ramasser à la même heure de départ pour les deux types d'instruments, ce qui est bon à partir d'un WAV-MIDI en perspective.

Dernière mise à jour (je l'espère): Oubliez ce que j'ai dit sur le fait d'inclure certains des remplissages des échantillons à partir du début de l'attaque de la part de chaque note - j'ai oublié c'est en fait une mauvaise idée pour la détection de hauteur. L'attaque des portions de nombreux instruments (en particulier de piano et autres percussions-instruments de type) contiennent des transitoires qui ne sont pas multiples de la hauteur fondamentale, et aura tendance à vis de détection de hauteur. Vous voulez commencer chaque tranche un peu après l'attaque pour cette raison.

Oh, et le type de important: le terme "compression" ne désigne pas ici de MP3 style de compression.

Mise à jour: voici une simple fonction qui fait non de la compression dynamique:

public void StaticCompress(short[] samples, float param)
{
    for (int i = 0; i < samples.Length; i++)
    {
        int sign = (samples[i] < 0) ? -1 : 1;
        float norm = ABS(samples[i] / 32768); // NOT short.MaxValue
        norm = 1.0 - POW(1.0 - norm, param);
        samples[i] = 32768 * norm * sign;
    }
}

Lorsque param = 1.0, cette fonction n'a aucun effet sur le son. De plus grandes valeurs de param (2.0 est bonne, ce qui va carré de la différence normalisée entre chaque échantillon et la valeur max valeur de crête) va produire plus de compression et de façon plus générale (mais merde) son. Les valeurs inférieures à 1,0 produire un effet d'expansion.

L'un des autres probablement est évident: vous devez enregistrer de la musique en une de petites, non-échoïque salle puisque les échos sont souvent repris par cet algorithme fantôme notes.

Mise à jour: voici une version de StaticCompress qui va compiler en C# et explicitement jette tout. Renvoie le résultat attendu:

public void StaticCompress(short[] samples, double param)
{
    for (int i = 0; i < samples.Length; i++)
    {
        Compress(ref samples[i], param);
    }
}

public void Compress(ref short orig, double param)
{
    double sign = 1;
    if (orig < 0)
    {
        sign = -1;
    }
    // 32768 is max abs value of a short. best practice is to pre-
    // normalize data or use peak value in place of 32768
    double norm = Math.Abs((double)orig / 32768.0);
    norm = 1.0 - Math.Pow(1.0 - norm, param);
    orig = (short)(32768.0 * norm * sign); // should round before cast,
        // but won't affect note onset detection
}

Désolé, mes connaissances score sur Matlab est de 0. Si vous avez posté une autre question sur les raisons de votre fonction Matlab ne fonctionne pas comme prévu, il aurait répondu (mais pas par moi).

4voto

MusiGenesis Points 49273

Ce que vous voulez faire est souvent appelé WAV vers MIDI (google "wav-midi"). Il y a eu de nombreuses tentatives de ce processus, avec des résultats variables (note apparition est une des difficultés; la polyphonie est beaucoup plus difficile à traiter). Je vous recommande de commencer avec une recherche approfondie de l'off-the-shelf de solutions, et de ne commencer à travailler sur votre propre si il n'y a rien acceptable là-bas.

L'autre partie du processus que vous auriez besoin est quelque chose pour rendre la sortie MIDI traditionnelle partition musicale, mais il y a je ne sais combien de milliards de produits qui ne qui.

Une autre réponse est: oui, j'ai fait beaucoup de traitement numérique du signal (voir le logiciel sur mon site web - c'est une infinité de voix synthétiseur logiciel, écrit en VB et C), et je suis intéressé à vous aider avec ce problème. Le WAV-MIDI n'est pas vraiment difficile sur le plan conceptuel, c'est juste pour le faire fonctionner de manière fiable dans la pratique, c'est dur. Remarque l'apparition est juste de définir un seuil d'erreurs peuvent être facilement ajustés avant ou en arrière dans le temps pour compenser la note d'attaque des différences. Hauteur de détection est beaucoup plus facile à faire sur un enregistrement qu'il est à faire en temps réel, et implique la mise en œuvre d'une auto-corrélation de la routine.

4voto

Jason Sundram Points 3237

Vous devriez regarder MIRToolbox - il est écrit pour Matlab, et dispose d'un détecteur d'attaque construite en, ça fonctionne très bien. Le code source est sous licence GPL, de sorte que vous pouvez mettre en œuvre l'algorithme dans quelque langue que ce soit qui fonctionne pour vous. Quel est le langage de votre code de production va utiliser?

3voto

Adam Points 329

@ALAN Dur les débuts sont facilement détectés dans le domaine temporel à l'aide d'un moyen de mesure de l'énergie.

SOMME de 0 à N (X^2)

le faire avec des morceaux de la totalité du signal. Vous devriez voir des pics lorsque les attaques se produisent. (la taille de la fenêtre est à vous, ma suggestion est de 50 ms ou plus.

Vaste Documents sur l'Apparition de Détection:

Pour Les Ingénieurs

http://www.elec.qmul.ac.uk/people/juan/Documents/Bello-TSAP-2005.pdf

Plus facile pour la personne moyenne pour comprendre

http://bingweb.binghamton.edu/~ahess2/Onset_Detection_Nov302011.pdf

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X