Je suis capable d'écrire un générateur d'onde sinusoïdale de base pour l'audio, mais je veux qu'il puisse passer en douceur d'une fréquence à l'autre. Si je cesse de générer une fréquence et que je passe immédiatement à une autre, il y aura une discontinuité dans le signal et un "clic" se fera entendre.
Ma question est de savoir quel est un bon algorithme pour générer une onde qui commence à, disons, 250 Hz, puis passe à 300 Hz, sans introduire de clics. Si l'algorithme comprend un temps de glissement / portamento en option, tant mieux.
Je peux penser à quelques approches possibles telles que le suréchantillonnage suivi d'un filtre passe-bas, ou peut-être en utilisant une table d'ondes, mais je suis sûr que c'est un problème suffisamment courant pour qu'il existe un moyen standard de le résoudre.
Réponses:
Une approche que j'ai utilisée dans le passé est de maintenir un accumulateur de phase qui est utilisé comme index dans une table de recherche de forme d'onde. Une valeur de delta de phase est ajoutée à l'accumulateur à chaque intervalle d'échantillonnage:
Pour changer la fréquence, vous changez le delta de phase qui est ajouté à l'accumulateur de phase à chaque échantillon, par exemple
où:
Cela garantit que la forme d'onde de sortie est continue même si vous modifiez dynamiquement phase_delta, par exemple pour les changements de fréquence, FM, etc.
Pour des changements de fréquence plus fluides (portamento), vous pouvez augmenter la valeur phase_delta entre son ancienne valeur et sa nouvelle valeur sur un nombre approprié d'intervalles d'échantillons plutôt que de simplement la changer instantanément.
Notez que
phase_index
et lesphase_delta
deux ont un entier et un composant fractionnel, à savoir qu'ils doivent être en virgule flottante ou point fixe. La partie entière de phase_index (taille de table modulo) est utilisée comme index dans la LUT de forme d'onde, et la partie fractionnaire peut éventuellement être utilisée pour l'interpolation entre les valeurs LUT adjacentes pour une sortie de meilleure qualité et / ou une taille LUT plus petite.la source
L'une des meilleures façons de créer une onde sinusoïdale est d'utiliser un phaseur complexe avec une mise à jour récursive. C'est à dire
où z [n] est le phaseur, , avec étant la fréquence angulaire de l'oscillateur en radians et l'indice de l'échantillon. Les parties réelle et imaginaire de sont des ondes sinusoïdales, elles sont déphasées de 90 degrés. Très pratique si vous avez besoin à la fois de sinus et de cosinus. Un seul calcul d'échantillon ne nécessite que 4 multiples et 4 ajouts et est BEAUCOUP moins cher que tout ce qui contient sin () cos () ou tables de recherche. Le problème potentiel est que l'amplitude peut dériver dans le temps en raison de problèmes de précision numérique. Cependant, il est assez simple de réparer cela. Disons que . Nous savons que doit avoir une grandeur unitaire, c'est-à-direΩ=exp(jω) ω n z[n] z[n]=a+jb z[n]
Nous pouvons donc vérifier de temps en temps si c'est toujours le cas et corriger en conséquence. La correction exacte serait
C'est un calcul gênant mais comme est très proche de l'unité, vous pouvez approximer les termes avec une expansion de Taylor autour de et nous obtenonsa⋅a+b⋅b 1/x−−√ x=1
de sorte que la correction se simplifie
L'application de cette simple correction toutes les quelques centaines d'échantillons maintiendra l'oscillateur stable pour toujours.
Pour faire varier la fréquence en continu, le multiplicateur W doit être mis à jour en conséquence. Même un changement non continu du multiplicateur maintiendra une fonction d'oscillateur continue. Si une augmentation de fréquence est nécessaire, la mise à jour peut être décomposée en quelques étapes ou vous pouvez utiliser le même algorithme d'oscillateur pour mettre à jour le multiplicateur lui-même (car il s'agit également d'un phaseur complexe à gain unitaire).
la source
De ce site :
On dirait que cela devrait fonctionner.
(En fait, s'ils sont tous deux synchronisés sur l'axe des x lors de la transition, je suppose qu'une transition progressive n'est pas nécessaire.)
la source
Je suis d'accord avec les suggestions précédentes d'utiliser un accumulateur de phase. L'entrée de commande est essentiellement la quantité d'avance de phase par étape ou par période d'horloge (ou par interruption ou autre), de sorte que la modification de cette valeur modifie la fréquence sans discontinuité dans la phase. L'amplitude de l'onde est ensuite déterminée à partir de la valeur de phase accumulée soit via une LUT, soit simplement par le calcul de sin (thêta) ou cos (thêta).
Il s'agit essentiellement de ce que l'on appelle communément un oscillateur à commande numérique (NCO) ou un synthétiseur numérique direct (DDS). Faire une recherche sur le Web sur ces termes donnera probablement plus que vous ne voulez en savoir sur la théorie et la pratique de leur bon fonctionnement.
L'ajout d'un accumulateur supplémentaire peut permettre des transitions transparentes entre les fréquences, comme vous l'avez suggéré, si vous le souhaitez également, en contrôlant le taux de changement de la valeur d'avance de phase. Ceci est parfois appelé un analyseur différentiel numérique, ou DDA.
la source
De premier ordre, vous devez ajuster la phase de démarrage de la nouvelle sinusoïde de fréquence afin qu'elle soit la même que celle qui serait la phase de la sinusoïde précédente au premier point d'échantillonnage de transition. Calculez la première fréquence et utilisez sa phase pour la deuxième fréquence.
La deuxième option pourrait consister à faire passer d_phase de celle d'une fréquence à la suivante sur plusieurs échantillons. Cela nettoiera la continuité du 1er dérivé et fournira une glisse.
La troisième option pourrait être d'utiliser une fenêtre de lissage, comme un cosinus surélevé, sur le taux de rampe d_phase.
la source