Algorithme de Karplus-StrongLe 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 fonctionnementAlgorithme 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 électroniqueL'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.
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 batteriesEn 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 informatiquesLe 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. Exemple d'implémentation basique de l'algorithme de Karplus-Strong en 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![]() 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 :
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]. Détail de la manifestation physiqueHistorique des brevetsAlgorithmes similairesBibliographie
Notes et références
Voir aussiArticles connexesLiens externes |