2010-08-05 22 views
0

Ok, j'ai essayé toutes sortes de titres et ils ont tous échoué (donc si quelqu'un vient avec un meilleur titre, n'hésitez pas à le modifier: P)Problème de logique de sous-dépassement de la mémoire tampon, tutoriel de filetage?

J'ai le problème suivant: J'utilise une API pour accéder matériel, que je n'ai pas codé, pour ajouter des bibliothèques à cette API, j'ai besoin d'hériter de l'interface API, et l'API fait tout.

Je mets dans cette API, une bibliothèque de générateur de musique, le problème est que l'API mentionnée appelle seulement la bibliothèque de musique quand le tampon est vide, et demande une quantité de données codées en dur (exactement 1024 * 16 échantillons ... ne sais pas pourquoi). Cela signifie que la librairie de générateur de musique ne peut pas utiliser tout le potentiel du processeur pendant la lecture de musique, même si la librairie musicale ne fonctionne pas, l'utilisation de la CPU reste faible (3%), donc dans certaines parties de la musique qu'il y a des trucs trop complexes, les buffers underuns (c'est-à-dire: la carte son joue la zone dans le buffer qui est vide, parce que la fonction de bibliothèque musicale n'est pas encore revenue).

Peaufiner le nombre hardcoded, ne ferait que faire fonctionner le logiciel dans certaines machines, et ne pas travailler dans d'autres, en fonction de plusieurs facteurs ...

Alors je suis venu avec deux solutions: Hack l'API avec une nouvelle logique de tampon, mais je ne ai rien compris sur ce point.

Ou celui que j'ai réellement pensé la logique: Faire de la bibliothèque musicale avoir son propre thread, il aura son propre tampon séparé qu'il remplira tout le temps, lorsque l'API appelle la bibliothèque musicale pour plus de données, à la place de générer, il va simplement copier les données de ce tampon séparé dans le tampon de la carte son, puis reprend la génération de musique.

Mon problème est que même si j'ai plusieurs années d'expérience en programmation, j'ai toujours évité le multi-threading, je ne sais même pas par où commencer ...

La question est: Quelqu'un peut-il trouver une autre solution, Ou pointez-moi dans un endroit qui me donnera des informations sur la façon d'implémenter ma solution filetée?

EDIT:

Je ne suis pas en train de lire des fichiers, je suis GÉNÉRATION ou CALCULER, la musique, il a obtenu? Ce n'est pas une bibliothèque .wav ou .ogg. C'est pourquoi j'ai mentionné le temps CPU, si je pouvais utiliser 100% CPU, je n'aurais jamais une sous-performance, mais je ne peux utiliser CPU dans le court laps de temps entre le programme réalisant que le tampon atteint la fin, et la fin réelle de le tampon, et cette fois est parfois moins que le temps que le programme prend pour calculer la musique.

+0

duplication possible de [Threading books for C++] (http://stackoverflow.com/questions/2334568/threading-books-for-c) –

+0

lisez-vous (1024 * 16) octets à partir du disque chaque fois que l'API appelle votre fonction de rappel? – carlsborg

+0

@Hans Pas de doublon, parce que je ne veux pas de livres, j'ai 2 jours pour l'implémenter: P Et il n'y a rien de complexe ... @tholomew Non, je génère 1024 * 16 octets, mais en streaming. wav files l'API lit 1024 * 16 octets depuis le disque, mais cette partie n'a rien à voir avec moi quand même ... – speeder

Répondre

2

Je crois que la solution avec thread séparé qui préparera les données pour la bibliothèque afin qu'il soit prêt lorsque demandé est le meilleur moyen de réduire la latence et de résoudre ce problème. Un thread génère des données musicales et les stocke dans le tampon, et le thread API reçoit des données de ce tampon quand il en a besoin. Dans ce cas, vous devez synchroniser l'accès au tampon, que vous soyez en train de lire ou d'écrire, et assurez-vous que vous n'avez pas trop de tampon dans les cas où l'API est trop lente. Pour implémenter cela, vous avez besoin d'une thread, mutex et condition primitives de la bibliothèque threading et deux drapeaux - un pour indiquer quand stop est demandé et un autre pour demander au fil de pause de remplir le tampon si l'API ne peut pas suivre et devient trop grand.Je vous recommande d'utiliser la bibliothèque de discussion Boost C++, voici quelques articles utiles avec des exemples qui viennent à l'esprit:

+0

Malheureusement votre réponse était trop tardive, j'avais déjà implémenté une solution pthread ... Mais c'est une bonne chose réponse quand même – speeder

0

Vous ne devez pas nécessairement un nouveau fil pour résoudre ce problème. Votre système d'exploitation peut fournir une opération de lecture asynchrone; Par exemple, sous Windows, vous devez ouvrir le fichier avec le fichier FILE_FLAG_OVERLAPPED pour rendre les opérations asynchrones.

Si votre système d'exploitation prend en charge cette fonctionnalité, vous pouvez créer un grand tampon pouvant contenir quelques appels d'une valeur de données. Lorsque l'application démarre, vous remplissez le tampon, puis une fois qu'il est rempli, vous pouvez passer la première section du tampon à l'API. Lorsque l'API retourne, vous pouvez lire plus de données pour remplacer la section du tampon que votre dernier appel API a consommé. Comme la lecture est asynchrone, elle remplira le tampon pendant que l'API joue de la musique. L'implémentation pourrait être plus complexe que cela, c'est-à-dire utiliser un tampon circulaire ou attendre que quelques sections aient été consommées, puis lire dans plusieurs sections à la fois, au lieu de lire dans une section à la fois.

+0

Bonne idée, si seulement cette API supportait les E/S asynchrones qui ne semblent pas être un cas. –