Tymbal : synthétiseur neuronal sur une seule puce
Tymbal est un synthétiseur polyphonique en temps réel fonctionnant sur un seul microcontrôleur STM32N657 (Cortex-M55 + NPU Neural-ART). Il utilise un réseau neuronal TCN comme raffineur résiduel pour ajouter un caractère non linéaire à un squelette harmonique déterministe, le tout dans des budgets de cycles stricts et sans sous-runs. Le projet détaille une optimisation approfondie, des transformations de graphe à la gestion de la mémoire, atteignant la performance en temps réel finale sur l'appareil.
Tymbal est un synthétiseur polyphonique temps réel sur une seule carte NUCLEO-N657X0-Q (STM32N657 : Cortex-M55 à 800 MHz + NPU Neural-ART), contrôlé via un clavier MIDI, avec sortie DAC I2S. L'audio est calculé par blocs de 4 ms ; à 800 MHz, cela représente 3,2 millions de cycles par bloc pour tout : voix, synthèse harmonique, réseau de neurones, banc de filtres, désaccordage, limiteur, avec zéro sous-écoulement (underrun). L'architecture utilise un domaine à quatre sous-bandes PQMF (12 kHz chacune) pour réduire les coûts et donner au réseau une entrée compacte. Le squelette harmonique est rendu directement dans les sous-bandes en utilisant des réponses de filtres complexes, avec une couche anti-ministère (auto-unisson, bloom spectral, micro-dérive). Un TCN causal avec 12 couches, dilatations de 1 à 32, canaux C=88, fonctionne sur le NPU comme affineur résiduel, quantifié en int8 via PTQ. Le point clé a été de constater qu'un réseau entraîné naïvement sur la prédiction résiduelle perd face à un FIR linéaire de 520 coefficients ; la solution a été de geler la partie linéaire en tant que 'couche zéro' (pred = FIR(x) + net(x)), afin que le réseau n'apprenne que le résidu non linéaire. Évaluation finale : le FIR seul donne une suppression de +11,25 dB, FIR+net en fp32 +17,16, int8 +16,89, avec une contribution du réseau de +5,64 dB. Les résultats de mise en route incluent : contenu ECC aléatoire après réinitialisation, banques AXISRAM désactivées, problèmes de chemin NOR-flash, diviseur d'horloge NPU incorrect (400 au lieu de 800 MHz), et une assertion fausse. L'optimisation budgétaire a commencé à 4,18 millions de cycles par bloc, pour finalement atteindre 2,47 millions dans le pire cas d'accord, avec zéro sous-écoulement. Les techniques comprenaient une boucle de mesure (cycles QEMU vs carte), un profilage des époques NPU, le pompage (appels NPU non bloquants entrelacés avec le rendu), le déplacement des tables chaudes vers DTCM, et une copie mémoire basée sur MVE pour l'anneau d'état.
Source: Habr — хаб ML —
original
