IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

DirectX Discussion :

DirectSound Stream Player


Sujet :

DirectX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Par défaut DirectSound Stream Player
    Bonjour à tous,

    J'ai un server UDP qui reçoit des données (environ 10 000 bytes par seconde). J'aimerais à l'aide DirectSound + C#, démarrer un Player Audio et interpréter le son reçu. Le son reçu est au format (8000hz, 16bits, 1 canal).

    Cependant, il se peut que le serveur reçoive moins de 10 000 bytes et d'autre fois plus... Si toutefois il manque des données, le player doit rester actif mais ne rien émettre comme son.

    Le problème, c'est que je n'ai pas vraiment trouvé de bonnes exemples qui pourrait m'aider. Si vous pourriez m'aider, ce serait apprécié

    Merci

  2. #2
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Par défaut
    Re-bonjour,

    En me basant sur le Microsoft SDK sample (CaptureSound), j'ai finalement réussi à faire quelque chose de très près de ce que j'ai besion. Cependant, lors de la lecture il se passe quelque chose de bizzare, comme si celle-ci se faisait trop rapidement ou que le tampon était mal remplit. Pour faire mes tests, j'ai créé un fichier wav à l'aide de SoundRec32 en utilisant le format que j'ai de besion (8000hz, 16bits, 1 canal). Par la suite je l'ai ouvert avec UltraEdit pour retirer la partis header ce qui laisse place seulement aux données du wav

    Voilà ce ce que j'ai jusqu'ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
     
    public class StreamPlayer
    {
        public const int NumberPlayNotifications = 16;
        private SecondaryBuffer m_PlayBuffer = null;
        private WaveFormat m_WaveFormat;
        private BufferDescription m_PlayBufferDescription;
        private AutoResetEvent m_NotificationEvent = null;
        private BufferPositionNotify[] m_PositionNotify = new BufferPositionNotify[NumberPlayNotifications + 1];  
        private Thread m_NotifyThread = null;
        private Notify m_ApplicationNotify = null;
        private int m_PlayBufferSize = 0;
        private int m_NextPlayOffset = 0;
        private int m_NotifySize = 0;
        private int m_SampleCount = 0;
        private Device m_SoundDevice;
        private bool m_Playing = false;
     
        // File to play
        private FileStream m_FileStream = null;
     
        // Constructor
        public StreamPlayer( Control owner )
        {
            m_SoundDevice = new Device();
            m_SoundDevice.SetCooperativeLevel(owner, CooperativeLevel.Normal);
     
            // Define the format for the raw waveform data.
            m_WaveFormat = new WaveFormat();
            m_WaveFormat.SamplesPerSecond = 8000;
            m_WaveFormat.BitsPerSample = 16;
            m_WaveFormat.Channels = 1;
            m_WaveFormat.FormatTag = WaveFormatTag.Pcm;
            m_WaveFormat.BlockAlign = (short)(m_WaveFormat.Channels * (m_WaveFormat.BitsPerSample / 8));
            m_WaveFormat.AverageBytesPerSecond = m_WaveFormat.SamplesPerSecond * m_WaveFormat.BlockAlign;
     
            // Sound buffer description
            m_PlayBufferDescription = new BufferDescription(m_WaveFormat);
     
            // Load wav file (hard coded here to test class)
            m_FileStream = new FileStream("Test.riff", FileMode.Open, FileAccess.Read);
        }
     
        // Create capture buffer
        private void CreatePlayerBuffer()
        {
            // Free ressource
            if (m_ApplicationNotify != null)
            {
                m_ApplicationNotify.Dispose();
                m_ApplicationNotify = null;
            }
            if (m_PlayBuffer != null)
            {
                m_PlayBuffer.Dispose();
                m_PlayBuffer = null;
            }
     
            // Set the notification size
            m_NotifySize = (1024 > m_WaveFormat.AverageBytesPerSecond / 8) ? 1024 : (m_WaveFormat.AverageBytesPerSecond / 8);
            m_NotifySize -= m_NotifySize % m_WaveFormat.BlockAlign;
     
            // Set the buffer sizes
            m_PlayBufferDescription.BufferBytes = m_PlayBufferSize = (m_NotifySize * NumberPlayNotifications);
            m_PlayBufferDescription.ControlVolume = true;
            m_PlayBufferDescription.GlobalFocus = true;
            m_PlayBufferDescription.ControlPositionNotify = true;
     
            // Create the actual sound buffer; the heart of the streaming sound features.
            m_PlayBuffer = new SecondaryBuffer(m_PlayBufferDescription, m_SoundDevice);
     
            // Play buffer is set to 0
            m_NextPlayOffset = 0;
     
            // Init notifications
            InitNotifications();
        }
     
        // Init notifications
        private void InitNotifications()
        {
            // Create a thread to monitor the notify events
            if (m_NotifyThread == null)
            {
                m_NotifyThread = new Thread(new ThreadStart(WaitThread));
                m_Playing = true;
                m_NotifyThread.Start();
     
                // Create a notification event, for when the sound stops playing
                m_NotificationEvent = new AutoResetEvent(false);
            }
     
            // Setup the notification positions
            for (int i = 0; i < NumberPlayNotifications; i++)
            {
                m_PositionNotify[i].Offset = (m_NotifySize * i) + m_NotifySize - 1;
                m_PositionNotify[i].EventNotifyHandle = m_NotificationEvent.Handle;
            }
            m_ApplicationNotify = new Notify( m_PlayBuffer );
            m_ApplicationNotify.SetNotificationPositions(m_PositionNotify, NumberPlayNotifications);
        }
     
        // Wait thread (waiting for notification)
        private void WaitThread()
        {
            // Start playing buffer content now
            this.m_PlayBuffer.Play(0, BufferPlayFlags.Looping); 
     
            // Wait for notification
            while (m_Playing)
            {
                // Sit here and wait for a message to arrive
                m_NotificationEvent.WaitOne(Timeout.Infinite, true);
                FillBuffer();
            }
        }
     
        /// Fill buffer on notification
        private void FillBuffer()
        {
            try
            {
                // Read n data in file stream
                byte[] playData = null;
                int fileStreamLength = (int)m_FileStream.Length;
                if (m_SampleCount >= fileStreamLength)
                {
                    // Sound has been sucessfully played
                    m_Playing = false;
                    return;
                }
                else if ((m_SampleCount + m_NotifySize) <= fileStreamLength)
                {
                    // Fill playing buffer with n data from file stream
                    m_FileStream.Seek(m_SampleCount, SeekOrigin.Current);
                    playData = new byte[m_NotifySize];
                    m_FileStream.Read(playData, 0, m_NotifySize);
                    m_PlayBuffer.Write(m_NextPlayOffset, playData, LockFlag.None);
                    m_SampleCount += playData.Length;
                    m_NextPlayOffset += playData.Length;
                }
                else if ((m_SampleCount + m_NotifySize) > fileStreamLength)
                {
                    // Fill playing buffer with lefting data from file stream
                    m_FileStream.Seek(m_SampleCount, SeekOrigin.Current);
                    playData = new byte[m_NotifySize];
                    int byteLefting = fileStreamLength - m_SampleCount;
                    m_FileStream.Read(playData, 0, byteLefting);
                    m_PlayBuffer.Write(m_NextPlayOffset, playData, LockFlag.None);
                    m_SampleCount += byteLefting;
                    m_NextPlayOffset += byteLefting;
                }
     
                // Circular buffer
                m_NextPlayOffset %= m_PlayBufferSize;
            }
            catch (Exception e)
            {
                System.Console.WriteLine("StreamPlayer : FillBuffer (" + e.ToString() + ")");
            }
     
        }
     
        // Start playing
        public void StartPlaying()
        {
            CreatePlayerBuffer();
        }
     
        // Stop playing
        public void StopPlaying()
        {
            this.m_Playing = false;
            if (m_PlayBuffer != null)
            {
                m_PlayBuffer.Stop();
                m_PlayBuffer = null;
            }
        }
    }
    J'ai beau tout essayé, revisé mais rien à faire je ne trouve pas mon bug :S
    Merci à l'avance pour votre aide.

  3. #3
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Par défaut
    Bonjour,

    Est-ce que quelqu'un pourrait me donner un coup de main ? Au pire cela pourrait être en C++ ou n'importe qu'elle autre language cela m'importe peu.
    J'ai épuisé toutes mes ressources sur ce problème

    Le malheur avec DirectSound c'est qu'il n'y a presque pas de tutoriel sur le sujet et l'aide en ligne est tout aussi pauvre .

  4. #4
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Salut.

    Je peux t'aider en C++ mais pas en C#.

    Il me semble que pour ton programme, le sample "capturesound" n'est pas indiqué.

    Je pense que le sample "DSNetwork", de DirectShow sera plus approprié.

    Sinon, et si tu souhaites continuer avec ton code (et vu que le son est joué rapidement), je dirais qu'il te manque une "Reference Clock", comme avec DirectShow, qui permet à ton programme d'envoyer les données à la carte son à une vitesse bien précise. J'ai l'impression que ton programme envoie les données à la carte son dès que c'est prêt, alors que celles-ci doivent être émises à intervalles réguliers (et qui je pense doit tenir compte du débit du format audio wav).

  5. #5
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Par défaut
    Bonjour,
    Je tiens spécialement à te remercier pour ton aide, c'est très apprécié

    Pour débuter, je n'y vois aucune objection à ce que tu m'aide en C++ car je le comprend très bien. Bref ce ne sera pas la syntaxe qui sera le problème mes plutôt DirectX. Sous le C# .Net il est en version Managed COM. Donc il me faudra juste tout débrouisailler (conversion non-managed à managed).

    Pour le sample CaptureSound il est dans Samples\Managed\DirectSound\CaptureSound

    Dis-moi si je me trompe mais DirectShow n'est pas pour la VIDÉO ? Moi ce n'est qu'un wave stream que j'essais de faire jouer.

    Finalement, le code est joué rapidement mais je ne crois pas que ce soit dû au fait qu'il me manque une "Reference Clock". Si j'ai bien compris, au début on créer un large buffer où on y affecte 16 play notifications.
    Une fois que l'on appel la méthode Buffer.PLAY() alors j'attend l'avertissement d'un des notification pour remplir mon buffer au bon moment et au bon endroit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while (m_Playing)
    {
       // Ici j'attend le signal avant de remplir la partie du buffer requise
       m_NotificationEvent.WaitOne(Timeout.Infinite, true); 
       FillBuffer();
    }
    Encore une fois

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Re.

    DirectShow, c'est pour la video ET l'audio.

    Je te conseilles de lire la documentation de directshow (directshow.chm), du dernier SDK. La doc se trouve aussi sur la MSDN.
    L'article qui te concerne: directshow->about directshow->times and clock in directshow->live sources. Tu y verras plus clair.

    Pour le code que tu me donnes, effectivement tu attends une notification, mais à quel moment est synchronisé le flux? Admettons que la notification se produise au bout de 6ms, puis de 3ms, puis de 22ms, etc... A quel moment ton code s'assure de transmettre les données à la carte son avec un timing régulier de 8ms par exemple.

    Avec la capture de directsound, directx assure pour toi la synchronisation par rapport au différent matériel utilisé. Pour ton système réseau, directx est incapable de déterminer la synchronisation (je pense que c'est ce qui explique que ça ne marche pas comme pour la capture).

Discussions similaires

  1. Player HLS (Http Live Streaming) sur tablette
    Par broadpeak dans le forum Android
    Réponses: 5
    Dernier message: 31/05/2012, 12h44
  2. Flash streaming audio player
    Par pennylanesworld dans le forum Flash
    Réponses: 3
    Dernier message: 17/11/2006, 23h29
  3. DirectSound et le streaming
    Par Shakram dans le forum DirectX
    Réponses: 57
    Dernier message: 09/06/2005, 11h05
  4. Réponses: 1
    Dernier message: 27/05/2002, 01h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo