Algorithme de Karplus-Strong
Le terme d'algorithme de Karplus-Strong, du nom des enseignants-chercheurs Kevin Karplus (en) et Alexander Strong qui l'ont respectivement analysé et inventé, désigne un ensemble de techniques simples permettant la synthèse d'aspect réaliste d'instruments à cordes pincées et de batterie. Il est classé dans les algorithmes de synthèse par modélisation physique.
Il est documenté par les chercheurs susnommés dans le Computer Music Journal du Massachusetts Institute of Technology en 1983, qui le développent entre 1978 et 1979[1].
Son principe repose sur l'emploi répété d'un filtre passe-bas, lequel agit plus fortement sur les plus hautes fréquences et plus faiblement sur les plus basses fréquences, appliqué cycliquement sur une même forme d'onde. Il effectue donc une interpolation entre une forme d'onde complète et du silence, mais avec une disparition plus rapide des hautes fréquences, la périodicité de la forme d'onde de base entraînant également une absence de fréquences inharmoniques à cette forme d'onde.
Principe de fonctionnement
Algorithme du domaine temporel, il fonctionne, dans sa version la plus simple, par la répétition d'une forme d'onde (dans la publication originale, un extrait de bruit blanc), répétition qui peut être effectuée par la copie d'un buffer réinscriptible en informatique[2] ou l'emploi d'une ligne de délai avec retour en électronique[1] ; sur laquelle sera appliquée de manière répétée, au fil des itérations, un filtre dégradant progressivement les plus hautes harmoniques de la forme d'onde, de façon à modéliser la dégradation des vibrations telle qu'observable sur un vrai instrument.
Cette dégradation fonctionne, avec l'algorithme original, de manière très simple et naïve puisqu'elle se résume à effectuer des moyennes entre échantillons adjacents à chaque application successive. Néanmoins, n'importe quel filtre fréquentiel peut être utilisé pour obtenir un résultat semblable, du moment qu'il entraîne une dégradation plus rapide des harmoniques hautes et plus faible des harmoniques basses.
Implémentation électronique
L'implémentation électronique de Karplus-Strong, telle que décrite en figure 2, page 45 de la publication originale au sein du Computer Music Journal[1] est illustrée par le schéma ci-dessus.
- Tout d'abord, un extrait sonore de taille fixée ( échantillons discrets, correspondant à une seule forme d'onde dans le domaine temporel, et donc à une longueur d'onde à la fréquence fondamentale voulue) est envoyée dans le système. Dans l'implémentation initiale, il s'agit de bruit blanc, mais cela n'empêche pas l'emploi d'une autre forme d'onde comme un signal en dents de scie filtré ou non pour obtenir des résultats à la texture sensiblement différente.
- Cet extrait sonore, en plus d'être envoyé vers la sortie sonore principale, est simultanément envoyé vers une ligne de délai ayant un délai correspond à la taille de la forme d'onde ( échantillons), et qui produira donc une sortie une fois que la première forme d'onde aura été jouée.
- Un filtre passe-bas très basique est appliqué sur la sortie cette première ligne de délai. Il est implémenté, dans la publication initiale, par l'application d'une moyenne entre chaque échantillon de la forme d'onde et la précédente (cette moyenne impliquant l'utilisation d'une seconde ligne de délai d'une longueur d'un échantillon).
- Une sortie audio provenant de l'extrait sonore initial, le temps de première forme d'onde (elle est alors constituée de forme d'onde originale, avec toutes ses harmoniques, jouée une seule fois), puis du filtre passe-bas vers lequel est réinjecté cycliquement le signal modifié est produite.
Pour comprendre comment fonctionne le filtre passe-bas simple suggéré par l'article de recherche, il faut comprendre les effets de l'opération de moyenne utilisée. Puisque cette perte de résolution est effectuée sur des échantillons adjacents, les plus hautes fréquences sont d'abord touchées et davantage que les basses, et puisque chaque valeur est transformée en une moyenne entre elle-même et la précédente, l'amplitude totale de la forme d'onde finit forcément par décroître. Cela reflète l'amortissement de la résonance.
Variante pour la production de sons de batteries
En plus de l'algorithme de génération de cordes pincées mentionné ci-dessus, l'article de recherche fait mention, en pages 46 à 47 du journal de publication, d'un algorithme de génération de sons de batteries.
De base, son principe consiste, pour une fraction répartie aléatoirement correspondant à 50 % des échantillons produits, à inverser le signe de l'échantillon après l'opération de moyenne[1].
De fait, l'effet de filtre fréquentiel est perdu et le son produit, apériodique, se rapproche d'un simple extrait de bruit irrégulier avec un fondu en fermeture[2].
Implémentations informatiques
Le principe de l'algorithme de Karplus-Strong sert de base à de nombreux synthétiseurs, virtuels ou non. Le générateur « Pluck » (cordes pincées) du logiciel Audacity est basé sur son principe, d'après les déclarations des développeurs[3].
Ci-dessous se trouve un exemple d'implémentation basique de l'algorithme en langage Python.
#!/usr/bin/python3
#-*- encoding: Utf-8 -*-
from numpy import array as np_array
from scipy.io.wavfile import write
from sounddevice import play
from random import random
from typing import List
# Install dependencies:
# sudo pip3 install --upgrade scipy sounddevice numpy
# All frequencies used below are expressed in Hertz
def karplus_strong(
noise_samples : List[int],
number_output_samples : int
):
output_samples : List[int] = []
for wavetable_iteration in range(number_output_samples // len(noise_samples)):
for output_position in range(len(noise_samples)):
wavetable_position = output_position % len(noise_samples)
# Apply the (very simple) low-pass filter = mean over adjacent PCM
# samples values over each sample
noise_samples[wavetable_position] = (
noise_samples[wavetable_position] +
noise_samples[(wavetable_position - 1) % len(noise_samples)]
) / 2
# Copy the next iteration of filtered waveform into the output
output_samples += noise_samples
return np_array(output_samples)
def do_karplus_strong_with_noise(
output_length_seconds : float,
fundamental_frequency : int
) -> None:
work_sampling_frequency = 8000
resampled_sampling_frequency = int(8000 * (2.0 / output_length_seconds))
# Calculate the length in samples of a single wavelength
wavelength_in_samples = int(round(
(work_sampling_frequency / fundamental_frequency) *
(resampled_sampling_frequency / work_sampling_frequency)
))
# Generated random samples in the range [-1.0;1.0]; as expected by Numpy
noise_samples : List[float] = [random() * 2 - 1 for i in range(wavelength_in_samples)]
# Apply the Karplus-Strong plucked string algorithm over the noisey waveform
pluck_samples : List[float] = karplus_strong(
list(noise_samples),
work_sampling_frequency * 2 # Apply the algorithm to 2 seconds of sample at 8000 Hz
)
# Play the output sound
play(pluck_samples, blocking = True, samplerate = resampled_sampling_frequency)
# In addition, save the produced sound to a file in order to enable
# further analysis with software such as Audacity
write('output_file.wav', resampled_sampling_frequency, pluck_samples)
do_karplus_strong_with_noise(
output_length_seconds = 0.363,
fundamental_frequency = 303
)
Dans un langage de bas niveau, l'implémentation de l'algorithme est économe puisque l'opération de moyenne constituant le filtre passe-bas peut être implémentée avec une division et un décalage d'un bit vers la droite (équivalent d'une division par deux)[4]. À l'époque de la suggestion, en 1983, cela permet la synthèse en temps réel avec les processeurs de l'époque Intel 8080A, Texas Instruments TMS9900 (en) et SC/MP[5].
Plusieurs implémentations de référence en C++ de l'algorithme de synthèse de cordes pincées, ainsi que d'autres algorithmes dérivés de Karplus-Strong et notamment de type guide d'ondes numérique (en) sont présentes dans le STK (Sound Toolkit) édité par le CCRMA de l'université Stanford, publié sous licence libre[6].
Détail de la production des harmoniques
![](https://img.franco.wiki/i/Sample_Karplus-Strong_output_spectrogram%252C_obtained_with_Audacity.png.webp)
Dans l'algorithme de synthèse de sons de cordes pincées (algorithme de Strong inventé en décembre 1978), illustré ci-dessus, il peut être observé que le déclin d'une harmonique s'étale sur une durée approximativement proportionnelle au nombre d'échantillons d'une seule forme d'onde au cube, divisé par le numéro de l'harmonique en question au carré[7]. Une analyse mathématique plus détaillée est proposée par le papier de recherche, proposant notamment un calcul exact qui dépend de paramètres trigonométriques et est mis en relation avec le principe de transformée en Z, lui-même sous-jacent au plus classique filtre en peigne[8].
Plus prosaïquement, les corollaires de base qui permettent le fonctionnement de l'algorithme peuvent être expliquées expérimentalement comme il suit :
- Le fait de répéter cycliquement une forme d'onde aléatoire de taille courte suffit à créer un motif périodique, faisant apparaître à l'intervalle de la forme d'onde et à toutes ses harmoniques du contenu fréquentiel.
- Le fait que des harmoniques, de différentes intensités, soient présentes dans la forme d'onde initiale est dû au caractère apériodique de la forme d'onde choisie.
- Le lissage de la forme d'onde en remplaçant les valeurs discrètes par des moyennes contribue à la baisse progressive de la présence d'harmoniques au sein du signal, et donc de la présence de contenu fréquentiel audible (dans le domaine temporel, on tend vers un signal continu qui n'est pas audible ; l'amplitude moyenne décroît progressivement autour d'une intensité qui n'est pas 0).
- La première passe de l'algorithme ayant d'abord un effet sur les échantillons adjacents entre eux, et induira donc d'abord une perte de résolution au niveau des éventuelles harmoniques proches de la fréquence de Nyquist ; ce sera par effet boule de neige que, progressivement, le signal sera de plus en plus lisse puisque des intervalles de plus en plus grandes seront touchées par des moyennes entre échantillons éloignés.
La longueur du déclin, de même que la fréquence de base du son produit, peuvent être modulées par un rééchantillonnage ainsi que par un changement de la longueur d'onde correspondant à la fréquence de base. Le papier évoque également la possibilité de remplacer une partie des opérations de moyenne par des opérations de copie sans modification afin de l'« étendre », ce qui tend à modifier l'aspect du son[9].
Bibliographie
: document utilisé comme source pour la rédaction de cet article.
(en) Kevin Karplus (en) et Alex Strong, « Digital Synthesis of Plucked-String and Drum Timbres », Computer Music Journal, MIT Press, vol. 7, no 2, , p. 43-55 (ISSN 0148-9267, e-ISSN 1531-5169, lire en ligne)
- (en) David A. Jaffe (en) et Julius O. Smith, « Extensions of the Karplus-Strong Plucked String Algorithm », Computer Music Journal, MIT Press, vol. 7, no 2, , p. 56-69 (ISSN 0148-9267, e-ISSN 1531-5169, lire en ligne)
Notes et références
- https://users.soe.ucsc.edu/~karplus/papers/digitar.pdf
- https://flothesof.github.io/Karplus-Strong-python.html
- https://manual.audacityteam.org/man/pluck.html
- Pages 44 et 45 de la publication au sein du journal de recherche original
- Page 43 de la publication au sein du journal de recherche original
- (en) « The Synthesis ToolKit in C++ (STK) », sur CCRMA, Université Stanford (consulté le )
- Page 47 de la publication au sein du journal de recherche original
- Pages 50 à 52 de la publication au sein du journal de recherche original
- Pages 47 à 48 de la publication au sein du journal de recherche original