6
votes

Comment jouer audio à partir d'un flux en temps réel

J'ai un programme qui produit des signaux audio censés être joués simultanément. Pour cela, je joue un intervalle de 100 ms de flux audio dans chaque période de 100 ms. Mais j'ai des signaux indésirables au début et à la fin de chaque flux audio de 100 ms (à cause de DC) de sorte que le son de sortie ne soit pas lisse, même la valeur des signaux est identique. Mon code est attaché ci-joint. S'il vous plaît aidez-moi ce que je devrais faire pour avoir un audio en temps réel correct.

using System;
using System.Windows.Forms;
using Microsoft.DirectX.DirectSound;
using System.IO;

namespace TestSound
{
    class CSound : Form
    {
        const int HEADER_SIZE = 44;
        const bool FLAG_STEREO = true;
        const short BITS_PER_SAMPLE = 16;
        const int SAMPLE_RATE = 44100;

        int numberOfSamples;
        MemoryStream stream;
        BinaryWriter writer;
        Device ApplicationDevice = null;
        SecondaryBuffer buffer = null;
        BufferDescription description;

        public CSound()
        {
            try
            {
                ApplicationDevice = new Device();
            }
            catch
            {
                MessageBox.Show("Unable to create sound device.");
                ApplicationDevice = null;
                return;
            }
            ApplicationDevice.SetCooperativeLevel(this, CooperativeLevel.Priority);
            description = new BufferDescription();
            description.ControlEffects = false;
            stream = new MemoryStream();
            writer = new BinaryWriter(stream);
        }

        private void AddHeader()
        {
            stream.Position = 0;

            writer.Write(0x46464952); // "RIFF" in ASCII
            writer.Write((int)(HEADER_SIZE + (numberOfSamples * BITS_PER_SAMPLE * (FLAG_STEREO ? 2 : 1) / 8)) - 8);
            writer.Write(0x45564157); // "WAVE" in ASCII
            writer.Write(0x20746d66); // "fmt " in ASCII
            writer.Write(16);
            writer.Write((short)1);
            writer.Write((short)(FLAG_STEREO ? 2 : 1));
            writer.Write(SAMPLE_RATE);
            writer.Write(SAMPLE_RATE * (FLAG_STEREO ? 2 : 1) * BITS_PER_SAMPLE / 8);
            writer.Write((short)((FLAG_STEREO ? 2 : 1) * BITS_PER_SAMPLE / 8));
            writer.Write(BITS_PER_SAMPLE);
            writer.Write(0x61746164); // "data" in ASCII
            writer.Write((int)(numberOfSamples * BITS_PER_SAMPLE * (FLAG_STEREO ? 2 : 1) / 8));
        }

        public void Play(short[] samples)
        {
            if (ApplicationDevice == null)
                return;

            stream.Position = HEADER_SIZE;
            numberOfSamples = samples.Length;
            for (int i = 0; i < numberOfSamples; i++)
            {
                writer.Write(samples[i]);
                if (FLAG_STEREO)
                    writer.Write(samples[i]);
            }
            AddHeader();
            stream.Position = 0;

            try
            {
                if (buffer != null)
                {
                    buffer.Dispose();
                    buffer = null;
                }
                buffer = new SecondaryBuffer(stream, description, ApplicationDevice);
                buffer.Play(0, BufferPlayFlags.Default);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        static short[] samples = new short[4410]; // 100 ms
        static CSound sound;

        static void Main()
        {
            Form form = new Form();
            form.Show();

            sound = new CSound();
            Random random = new Random();
            for (int i = 0; i < samples.Length; i++)
                samples[i] = 1000; // constant value

            while (true)
            {
                sound.Play(samples);
                System.Threading.Thread.Sleep(100); // 100 ms
            }
        }
     }
}


0 commentaires

3 Réponses :


1
votes

Il y a un certain nombre de choses qui ne vont pas avec ce code. Je suppose que lorsque vous exécutez ce code, vous entendez une entente en cliquant sur des sons de 100 ms. Ceci est dû à l'appel de thread.sleep (100) à l'intérieur de la boucle (vraie). Fondamentalement, votre application attend 100 ms (donnez ou prenez une petite quantité de temps) puis appelant la lecture (), qui fait un peu de traitement, puis festent la matrice pour la lecture. En conséquence, il y a un peu de temps entre le jeu de chaque matrice de 100 ms, qui produit les clics.

Toutefois, si vous venez de commenter la ligne thread.sleep (100), votre application irait dans une boucle infinie où elle continue à faire la queue de la matrice de 100 ms après 100 ms jusqu'à ce que vous sortiez de la mémoire. Mais au moins la lecture n'aurait pas les artefacts tous les 100 ms.

Si vous avez changé la ligne vers Whleep.sleep (80), cela fonctionnerait un peu mieux, en ce sens qu'il vous faudrait plus longtemps à manquer de mémoire, mais cela se produirait encore parce que vous alliez toujours des tampons de déversement dans le système de lecture audio plus rapidement que le système peut les lire.

Également, même si vous vous débarrassez du clic sur 100 ms, vous n'entendez rien du tout à sortir de vos haut-parleurs, car votre code définit chaque échantillon de valeur sur 1000. Vous n'entendrez jamais quelque chose si Vous modifiez les valeurs d'échantillonnage au fil du temps. Incidemment, la seule raison pour laquelle vous entendez des clics est que cette valeur d'échantillon est définie sur 1000 et pendant ces intervalles de temps entre les morceaux, la valeur de lecture revient à 0. Si vous définissez chaque valeur de l'échantillon sur 0, vous ne voudriez jamais entendre quoi que ce soit du tout.

Je pourrais vous aider avec cela, mais je devrais avoir une meilleure idée de ce que vous essayez de faire, exactement. Essayez-vous de jouer un ton continu à une certaine fréquence?


0 commentaires

4
votes

Si vous recherchez un moyen de jouer audio via un flux défini, avez-vous considéré Naudio HTTP: // Naudio .Codeplex.com / ?

Vous pouvez définir un flux, à partir d'un fichier ou d'un autre emplacement (c'est-à-dire la mémoire), puis remplissez le flux avec les données que vous souhaitez lire. Tant que vous pouvez continuer à fournir des données audio au flux avant que le pointeur de lecture arrive à la fin du tampon, vous n'entendez pas ces artefacts dans l'audio généré.

BTW - Je suppose que vous savez que les bibliothèques directrices directrices gérées pour .NET ne sont plus développées et sont effectivement une impasse pour ce type de développement audio?


0 commentaires

0
votes

Si par "signaux indésirables", vous voulez dire un léger bruit de saut à l'une ou l'autre extrémité, il pourrait s'agir d'un problème d'enveloppe qui, dans Csound, pourrait être contrôlé par l'opcode «Lin» ou quelque chose de similaire. L'idée étant que vous devez augmenter légèrement l'amplitude de l'amplitude et sur l'extrémité arrière pour éviter de cliquer sur le son des haut-parleurs qui cessent brusquement leur sortie à la mi-vague, pour ainsi dire. Quelques MS devraient suffire - expérimenter avec elle jusqu'à ce que vous vous débarrassiez du sautillement sans remarquer la modulation d'amplitude.

Regardez ici: http://www.csounds.com/journal/issue11/csoundenvelopes .html

Si vous essayez de produire un signal transparent en articulant une forme d'onde identique séquentiellement à intervalles réguliers, vous entendrez toujours ce son de saut car l'extrémité d'une forme d'onde ne fonctionne pas avec le début de la formulaire d'onde suivante. Il est très difficile d'obtenir les formes d'onde pour aligner avec précision et ce n'est pas vraiment une bonne stratégie. Une meilleure stratégie serait d'utiliser une enveloppe (comme décrit ci-dessus) et de chevaucher les formes d'onde (appelées à la queue de dove) de sorte que la carie de l'ancienne articulation arrive simultanément à la montée de la nouvelle articulation.

Cependant, cette stratégie ne produira pas un son totalement pur car la présence de deux formes d'onde quelque peu identiques se chevauchant de manière asynchrone s'annule un peu et provoque une diminution de l'amplitude à chaque jonction des formes d'onde.


0 commentaires