Aide à la mise en œuvre de la compression de la plage dynamique audio

8

J'essaie d'implémenter la compression de la plage dynamique audio en JavaScript (sans utiliser l'API audio Web).

Il y a beaucoup d'articles pour les techniciens du son et une documentation de haut niveau, mais je n'ai trouvé aucune référence utile pour implémenter la compression de la plage dynamique numérique.

D'après ce que je comprends, il y a au moins 3 étapes dans le calcul du signal rectifié.

  1. calculer le niveau d'entrée
  2. calculer le gain à appliquer au signal
  3. appliquer le gain

Je traite l'audio en blocs, donc pour 1) je pensais calculer le RMS d'un bloc

Des conseils sur une bonne référence? Ou quelqu'un qui veut m'expliquer un peu les étapes nécessaires pour mettre en œuvre cela?

sebpiq
la source
1
Juste pour être sûr: vous voulez implémenter quelque chose comme ceci: waves.com/plugins/c1-compressor , non?
Deve
oui :) mais beaucoup plus simple! Les contrôles dont j'ai besoin seraient le seuil, le genou, le ratio, l'attaque, la libération. Mais je peux commencer avec encore plus simple
sebpiq

Réponses:

4

Voici quelques suggestions:

  • Il existe de nombreuses implémentations open source (Sox, Audacity, etc.). Même si vous ne les comprenez pas, vous pourrez peut-être traduire le code de C en javascript.
  • Je ne connais pas une bonne explication du processus en ligne, mais il y a beaucoup de livres sur le sujet:
    • Le traitement du signal audio numérique couvre ce sujet et est bien écrit. (Tout comme DAFX , mais DAFX est mal organisé et la couverture est moins simple)
    • Digital Audio with Java couvre également ce sujet et est livré avec du code Java fonctionnel qui devrait être facile à traduire dans d'autres langues, comme javascript. Ce livre a de nombreux défauts, mais il est bon pour quelqu'un sans expérience en programmation audio.

Le principe est de créer une enveloppe du signal (contrôlée par l'attaque et le relâchement), de façonner cette enveloppe à l'aide d'une fonction de transfert (contrôlée par le rapport, le seuil et le genou), puis d'appliquer ce résultat au signal d'origine. Une étape de gain de maquillage suit souvent.

La réponse de @ Deve suggère quelques fonctions de transfert possibles.

Bjorn Roche
la source
Le problème est que je ne connais pas C, et oui, c'est un gros obstacle lorsque je travaille avec du dsp audio, car je ne peux pas vérifier les implémentations existantes. Sinon, merci pour les livres, je vais certainement vérifier le premier au moins.
sebpiq
Le livre DAFX a un code matlab. IDK s'il a un code matlab pour un compresseur.
Bjorn Roche
Pour le livre "Traitement du signal audio numérique", les commentaires d'Amazon disent qu'il vaut mieux pour les personnes ayant une formation d'ingénieur électricien. Connaissez-vous un livre qui se concentre davantage sur les algorithmes, le meilleur serait par exemple en pseudo-code?
sebpiq
1
D'une manière ou d'une autre, vous allez devoir acquérir de nouvelles compétences, je pense.
Bjorn Roche
Oui je sais! Et je suis prêt pour ça. C'est juste que je ne veux pas vraiment de code matlab par exemple, car je ne veux pas payer pour que matlab puisse les tester. C'est pourquoi j'ai demandé si vous connaissez d'autres livres avec par exemple un pseudo code, au lieu d'un langage spécifique (comme Java que je ne suis vraiment pas intéressé à apprendre).
sebpiq
2

Pour un démarrage simple, j'utiliserais une caractéristique non linéaire g(X) qui comprime votre signal d'entrée:

y=g(X)

où (comme indiqué par endolith dans les commentaires) Xest l' enveloppe du signal audio d'entrée ety est l'enveloppe de sortie qui est appliquée au signal audio réel. g(X)peut être n'importe quelle fonction qui atténue les grandes valeurs d'entrée plus fortes que les petites valeurs d'entrée. La loi A etμ-Des fonctions de loi ont été développées pour compresser des signaux vocaux pour la téléphonie, par exemple. Je ne sais pas à quel point cela sonne bien pour la musique.

Une autre fonction de compression très simple serait d'atténuer toutes les amplitudes au-dessus d'un certain seuil δ:

g(X)={XpourXδuneX+(1-une)δpourX>δ
une<1est l'atténuation. Mais cela ne fonctionnera pas très bien car notre sens de l'audition est logarithmique de sorte que l'atténuation pourrait être beaucoup trop forte. C'est pourquoi les compresseurs audio fonctionnent sur une échelle logarithmique et cela conduit à la même fonction que ci-dessus, mais toutes les valeurs sont prises logarithmiquement et par rapport à la valeur maximale possible. PourX>0:
Journal(g(X))={Journal(X)pourXδ1rJournal(X)+(1-1r)Journal(δ)pourX>δ

Pour les compresseurs audio, δ est généralement donné en dB et r est exprimé sous forme de rapport, par exemple 3: 1 (c.-à-d. r=3). Cela donne une fonction exponentielle, lorsqu'elle est exprimée linéairement (espérons qu'elle est correcte, veuillez la vérifier, égalementX>0):

g(X)={XpourXδδ1-1/rX1/rpourX>δ
Cette fonction a un «genou dur», ce qui signifie que la fonction Journalg(X) n'est pas différenciable à X=δ. Pour un «genou mou», vous auriez besoin d'une transition en douceur à ce point. L'extension des fonctions ci-dessus pour le négatifX est simple, multipliez simplement par la fonction de signe et prenez la valeur absolue de X.

L'attaque et la libération ont un impact sur différents sons comme les coups de pied, les collets et la voix. Ils déterminent combien de temps avant que le seuil soit atteint, le compresseur doit commencer à fonctionner et combien de temps il doit encore fonctionner après que le signal est tombé en dessous du seuil. Pour mettre en œuvre cela, vous devrez utiliser une sorte d'anticipation.

Comme toutes les amplitudes ci-dessous δsont atténués, la plage dynamique disponible n'est pas pleinement exploitée. Ceci est corrigé par le soi-disant "gain de rattrapage" qui est juste une simple multiplication du signal compressé avec un facteur de gaing>1. En réduisant d'abord la plage dynamique puis en amplifiant les compresseurs de signal, la musique peut paraître "plus forte".

Deve
la source
Merci! Grande explication. Je suis arrivé à une fonction de transfert proche de celle que vous avez donnée, mais la mienne n'a pas inclus le seuil (j'ai simplifié avec seuil = 0), donc je dois recalculer.
sebpiq
En fait, la fonction de transfert que j'obtiens en ajoutant le seuil est x ^ (1 / r) * 10 ^ (- sigma / (20 * r))
sebpiq
Désolé, mes définitions de fonctions étaient un gâchis parce que j'avais oublié d'ajouter le biais constant. J'ai corrigé cela. La dernière expression, cependant, est correcte à mon avis. Il doit remplirg(δ)=δ. Il n'y a aucun facteur de 20 impliqué ici parce que nous prenons le logarithme des côtés gauche et droit afin que tout facteur constant s'annule.
Deve
Ceux-ci ressemblent à de la distorsion, pas à de la compression. La distorsion est un changement de niveau qui se produit échantillon par échantillon, tandis que la compression se produit sur plusieurs cycles de la forme d'onde (chacun étant composé de nombreux échantillons). La distorsion non linéaire va sonner horriblement.
endolith
@endolith Vous avez raison, merci pour l'astuce. J'ai mis à jour ma réponse en conséquence.
Deve