Fils de producteur audio avec fil de consommation OSX AudioComponent et rappel en C

Cette question ne concerne pas un plugin, mais une conception de programme d’application autonome et est liée à quelques questions que j’ai déjà posées.

Je dois écrire une fonction de synthèse audio multithreads, dont la quantité de données crunching dépasse de loin ce qui peut être logé sur le fil de rendu CoreAudio : plusieurs milliers d’oscillateurs indépendants à amplitude et phase interpolant en temps réel. Cela nécessite plus de puissance de processeur que tout cœur de processeur unique, avec toutes les optimisations disponibles.

Je fais de mon mieux pour l’apprendre, mais cela semble être un mur, pas une courbe. Le thread consommateur peut être une simple priorité de CA en temps réel rendant le rappel en acceptant AudioBufferList, iodata , etc…… mais quel devrait être le ou les threads producteurs? Si vous choisissez un autre AudioComponent, cela ne vaut pas mieux que de tout avoir sur le thread de sortie – cela devient de plus en plus compliqué et introduit une latence supplémentaire.

Si vous placez n AudioComponents parallèles dans un graphique qui alimente un tampon en anneau, qui alimente le thread consommateur, comment peut-on garantir qu’il ne se retrouvera pas sur le même thread, restr synchronisé et précis à l’échantillon?

Si vous écriviez n threads POSIX traditionnels avec des sorties jointes, comment réaliser le modèle d’extraction CoreAudio coexisterait-il avec un tel modèle push en temps réel?

Existe-t-il un exemple de code librement disponible? Existe-t-il une référence, un manuel ou un tutoriel pour écrire un tel code? Je n’ai trouvé aucune information accessible au public. Cela me rend un peu étonnant qu’une telle question n’ait pas été posée auparavant?

Merci d’avance!

Ma stratégie consisterait à créer un ou plusieurs threads distincts, générant votre audio LPCM en temps réel et l’écrivant dans un tampon circulaire de taille appropriée. Le fil audio principal lit à partir de cette mémoire tampon en anneau.

Si le lecteur (thread audio principal) demande plus d’audio que ce qui est disponible, vous obtenez un abandon ( mémoire tampon insuffisante ), car le lecteur ne peut pas attendre. Cela indique que vous avez besoin d’une mémoire tampon plus grande ou que votre algorithme de génération audio n’est pas en temps réel et doit être optimisé.

Si le rédacteur tente d’écrire dans la mémoire tampon de sonnerie lorsqu’elle est pleine, l’audio le plus ancien est écrasé et vous avez un autre problème, cette fois via une saturation. Dans ce cas, votre code de génération audio s’exécute trop rapidement et doit apprendre à attendre. Ici, il serait pratique d’append une attente d’écriture, via une variable de condition.

Je connais deux implémentations sympas de ringbuffer qui utilisent des astuces de mémoire virtuelle pour implémenter efficacement l’access mémoire modulaire:

  • Mike Ash’s MAMirrored Queue
  • TPCircularBuffer de Michael Tyson

Si vous cherchez quelque chose de plus portable, il existe CBuffer pour les systèmes de type Unix et Magic Ring Buffer pour Windows.

Toutefois! Vous n’avez pas à utiliser de tampons en anneau MMU complexes, vous pouvez utiliser une version C ancienne et portable si vous le souhaitez.