Question

J'ai écrit une bibliothèque wrapper bibliothèque WinMM qui expose les classes WaveOut et WaveIn aux fins d'enregistrement et la lecture de flux audio brutes.

Tout fonctionne très bien, mais pour suivre les spécifications du système d'exploitation sur la façon de gérer les tampons finis, j'ai ajouté un fil qui unprepares les tampons et libère la mémoire. Je suis aussi tout de la synchronisation vers le bas, de sorte que les classes sont solides et thread-safe.

Cependant, il semble y avoir un problème rare où ajouter un tampon au dispositif WaveOut et le système d'exploitation renvoie un code de succès, mais si le dispositif est remis à zéro immédiatement postfaces, le système d'exploitation ne marque pas le tampon comme fini et le retour à l'application.

Il semble qu'il est en train de perdre les tampons. Donc, le problème est, je garde une trace du nombre de tampons individuels envoyés au dispositif et le blocage se joindre à la fonction Close () sur le fil qui les nettoie.

Toutes les idées, ou des bugs connus?

PS:. Cela ne semble pas se produire sur un Quad Core dans Vista, mais ne se produit sur mon Dual Core dans XP pro

EDIT1. Je suis tout à fait prêt à exposer le code source complet, une fois que je l'obtiens téléchargé et propery sous licence sur CodePlex, si cela pouvait aider tout le monde

EDIT2: bibliothèque Publié à CodePlex: http://winmm.codeplex.com/

Voici une idée de ce qui cause le problème:

public partial class MainView : Form
{
    private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId);
    private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId);

    public MainView()
    {
        InitializeComponent();

        WaveFormat format = WaveFormat.Pcm44Khz16BitMono;

        waveOut.Open(format);

        waveIn.DataReady += new EventHandler<DataReadyEventArgs>(WaveIn_DataReady);

        // Tweaking these values affects the internal buffering thread.
        // Setting too small of a QueueSize with too small of a BufferSize
        //  will cause buffer underruns, which will sound like choppy audio.
        waveIn.BufferQueueSize = 200;
        waveIn.BufferSize = 64;

        waveIn.Open(format);

        waveIn.Start();
    }

    void WaveIn_DataReady(object sender, DataReadyEventArgs e)
    {
        if (waveOut != null)
        {
            lock (waveOut)
            {
                // We have to check for null after the lock,
                //  because waveOut may have been disposed
                //  inside another lock.
                if (waveOut != null)
                {
                    waveOut.Write(e.Data);
                }
            }
        }
    }

    private void MainView_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (waveIn != null)
        {
            lock (waveIn)
            {
                waveIn.Dispose();
                waveIn = null;
            }
        }

        if (waveOut != null)
        {
            lock (waveOut)
            {
                waveOut.Dispose();
                waveOut = null;
            }
        }
    }
}
Était-ce utile?

La solution

Je voudrais tout d'abord créer un object distinct sur lequel pour verrouiller. Cela devrait simplifier beaucoup de votre logique de vérification nulle (environ la moitié depuis que vous vérifiez avant et après le blocage).

En second lieu, Dispose ne sera pas mis votre variable à null, afin que vos autres chèques encore être autorisés par parce que l'objet est non nul, seulement disposé. Donc, je le ferais

waveOut.Dispose();
waveout = null;

pour vous assurer qu'il est explicitement défini sur null.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top