![]() |
Bienvenue invité ( Connexion | Inscription )
![]() |
![]()
Message
#1
|
|
Macbidouilleur d'argent ! ![]() ![]() ![]() Groupe : Membres Messages : 659 Inscrit : 7 May 2015 Membre no 195 224 ![]() |
Bonjour,
Je travaille sur un µC qui doit lire du MIDI en temps réel. Il est programmé en C et je débute un peu dans ce language. Lors de changements de tempo, j'ai besoin de faire des calculs mathématiques qui prennent beaucoup de temps au processeur (je pense que je m'y prend mal, j'ai l'impression que certaines instructions seraient à éviter). Le fichier est écrit ainsi :
Mon programme actuel fonctionne comme ça : Le microcontrôleur dispose d'un timer interne. Il s'incrément automatiquement tous les 64 coups d'horloge et il déclenche une action quand il atteint une limite configurable entre 1 et 255. J'essaie donc de le calculer de telle manière à ce qu'il corresponde au plus près de la durée d'un "tick" et quand je recois un nombre de ticks à attendre, j'attends qu'il se déclenche autant de fois avant de lire la suite. Mon calcul fonctionne, mais si le tempo change par exemple de manière progressive dans un morceau (en gros, il y a un changement de tempo avant chaque note), la lecture s'en trouve très ralentie. C'est embêtant. Voici ce que j'utilise en cas de changement de tempo : Code // variable globale unsigned int baseDelay; float baseFreq; // variables locales long Finstruction; float base, limite, calcul; // A l'ouverture du fichier, je déduis du nombre de "ticks" par noire (une seule fois) la fréquence du timer dont j'ai besoin Finstruction = _XTAL_FREQ / 4000000; //MHz baseFreq = 256 * (long)DivisionTps; // 256 = limite max d'explosion du timer baseFreq = Finstruction / baseFreq; // = FmaxTimer / DivisionTps baseFreq /= 16; // multiplicateur interne du timer // Configuration lors d'un changement de Tempo // souvent la limite de 256 du timer ne suffira pas, donc j'utilise un multiplicateur supplémentaire base = ceil(Tempo * baseFreq); // calcul de la valeur d'Overflow (PR2) calcul = baseFreq * 256 / base; limite = round (Tempo * calcul); // config baseDelay = (int)base; PR2 = (int)limite - 1; // le timer déclenche un évènement au moment où il passe la limite PR2, pas quand il l'atteint // je dois aussi récupérer le Tempo en BPM : TempoBPM = 60000000/Tempo; // Lorsque je reçois un délai à attendre, il est simplement calculé comme ceci : return (DelaiLu * baseDelay); // puis le timer est démarré si le résultat n'est pas nul. Pourriez-vous m'expliquer quelles sont les opérations les plus lourdes là-dedans pour essayer de faire en sorte de les supprimer ? Merci beaucoup. Ce message a été modifié par Anard - 10 Mar 2018, 15:38. -------------------- "iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3,
"Portable" : HP Pavilion DV3500, Intel core2 T6400, 4Go DDR3, NVidia GeForce 9300M, HDD 256Go / Grub2 - Gentoo-Xfce |
|
|
![]() |
![]()
Message
#2
|
|
Macbidouilleur d'argent ! ![]() ![]() ![]() Groupe : Membres Messages : 659 Inscrit : 7 May 2015 Membre no 195 224 ![]() |
Bonjour et merci pour vos réponses.
J'ai réussi à revoir mes calculs pour n'utiliser que des entiers. J'arrive en fonction de la situation à une erreur finale de 0 à -5‰ au lieu de ±2,2‰ avec des float. Ce n'est en effet pas si dramatique et ça tourne beaucoup plus vite. J'ai également essayé d'écrire les données en dur en créant d'énormes tableaux, pour 7 valeurs de "ticks"/noire (120, 192, 240, 384, 480, 768, 960) souvent rencontrées et pour des tempos allant de 45 à 299 : Code const unsigned int limites[7][255] = {{252,252,252,253,254,249,..},\ {...},{...},{...},{...},{...},{...}}; const unsigned int bases[7][255] = {{ 44, 43, 42, 41, 40, 40, ..},\ {...},{...},{...},{...},{...},{...}}; C'est bourrin et ça prend pas mal de place en mémoire, mais en effet, ça fonctionne et va encore bien plus vite. Ca m'a surtout permis de constater que certains ralentissements venaient d'ailleurs dans le programme. Par exemple au moment d'afficher la modification à l'écran, en SPI, ce qui ralenti considérablement le temps de traitement s'il y a beaucoup de modifications à suivre (par exemple comme je le disais lors d'un changement de tempo progressif). Un DSP ? Je ne connais pas. C'est un composant externe qui s'occupe uniquement du calcul ? En tout cas, c'est déjà un peu mieux, merci beaucoup pour vos conseils, c'est exactement ce dont j'avais besoin pour avancer. Ce message a été modifié par Anard - 13 Mar 2018, 20:32. -------------------- "iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3,
"Portable" : HP Pavilion DV3500, Intel core2 T6400, 4Go DDR3, NVidia GeForce 9300M, HDD 256Go / Grub2 - Gentoo-Xfce |
|
|
![]() ![]() |
Nous sommes le : 18th July 2025 - 02:33 |