Partage
  • Partager sur Facebook
  • Partager sur Twitter

C# NAudio probleme resampling 32bit vers 16 bit

    17 juin 2019 à 9:58:27

    Bonjour,
    J'éssai de faire un programme écoutant le son du pc puis l'envoi par udp mais j'ai besoin de convertir le bitrate du son de 32 à 16 bit avec un sample rate de 44100 sinon c'est trop lourd pour le réseau.

    J'utilise WasapiLoopbackCapture mais je comprend pas tout ce que je fais. Ça fonctionne mais il y a des grésillements.
    J'ai testé de convertir chaque tableau d'octet puis de les écrire à la volée dans un fichier et je me suis rendu compte que le grésillement était entre deux écriture. Si je concatène tous les tableaux, puis que je convertis le tableau final, là, ca fonctionne sans grésillement mais le but d'envoyer du son en live c'est pas d'envoyer la totalité d'un coup.

    Les fonctions Convert16 et readStream sont de ce topic.

     public byte[] Convert16(byte[] input, int length, WaveFormat format)
        {
            if (length == 0)
                return new byte[0];
            using (var memStream = new MemoryStream(input, 0, length))
            {
                using (var inputStream = new RawSourceWaveStream(memStream, format))
                {
                    var sampleStream = new NAudio.Wave.SampleProviders.WaveToSampleProvider(inputStream);
                    var resamplingProvider = new NAudio.Wave.SampleProviders.WdlResamplingSampleProvider(sampleStream, audioRate);
                    var ieeeToPCM = new NAudio.Wave.SampleProviders.SampleToWaveProvider16(resamplingProvider);
                    var sampleStreams = new NAudio.Wave.StereoToMonoProvider16(ieeeToPCM);
                    sampleStreams.RightVolume = 0.5f;
                    sampleStreams.LeftVolume = 0.5f;
                    return readStream(sampleStreams, length);
                }
            }
        }
    
        private byte[] readStream(IWaveProvider waveStream, int length)
        {
            byte[] buffer = new byte[length];
            using (var stream = new MemoryStream())
            {
                int read;
                while ((read = waveStream.Read(buffer, 0, length)) > 0)
                {
                    stream.Write(buffer, 0, read);
                }
                return stream.ToArray();
            }
        }
    
    
        public void InputBufferToFileCallback(object sender, WaveInEventArgs e)
        {
            // Used to see WaveViewer and to test
            baseWriter.Write(e.Buffer, 0, e.BytesRecorded);
    
            // byte[] convertedTo16 -- PROBLEM IS HERE
            convertedTo16 = Convert16(e.Buffer, e.BytesRecorded, waveFormatIn);
    
            // Used to see WaveViewer and to test
            convertedWriter.Write(convertedTo16, 0, convertedTo16.Length);
    
            // Send over udp real time
            SendSoundController(convertedTo16);
        }


    On peut observer le problème entre l’écriture de deux tableau d'octets sur cette image: (En haut, le son avec un problème, en bas le son non convertit sans problème)

    • Partager sur Facebook
    • Partager sur Twitter
      17 juin 2019 à 10:11:12

      Bonjour,

      Je pense qu'il faudrait a ton programme un petit temps de conversion.

      Je m'explique, imaginons tu fait un programme ou les musiques sont préenregistré et elles passent en boucle.

      Charge tes musiques à l'avance ou au moins 1 musique d'avance.

      Tu stock ta musique converti et tu fait une Queue<byte[]>, ça te permettrais de ne pas avoir ce temps de conversion qui plante entre chaque écriture.

      Après si c'est un bot comme sur Discord ou TeamSpeak, où l'utilisateur peux choisir une musique, tu remarquera que ce n'est jamais de l’instantanée.

      Car la tu a un temps de latence dû au temps de conversion de ton Convert16(...).

      Je ne sais pas si c'est une bonne idée mais je pense que ça pourrait être une piste. :)

      Cordialement.

      • Partager sur Facebook
      • Partager sur Twitter

      Cordialement,

      Neross

      Vous pouvez m'ajouter sur Discord : Neross#8583

        17 juin 2019 à 11:48:59

        Merci pour ta réponse !
        Je pensais pas que ça pourrait être le problème car si on met de côté que j’envoie en udp, alors j’écris dans un fichier donc je pensais qu'il n'y avait pas de contrainte "temporel" mais en fait si puisqu'il reste l'enregistrement.

        Cela voudrait dire qu'entre 2 écriture, WasapiLoobackCapture n'as pas eu le temps d'enregistrer la prochaine frame donc ça produit le bruit blanc. Je vais essayer, je pensais que le pc était assez rapide pour ce genre de souci et que ça venait plutôt d'un problème dans une des fonctions.

        Ah oui et tu as dit que ce n'est jamais de l'instantané pour un bot mais comment font les enceintes bluetooth pour recevoir un son instantané ? Pareil pour les transmissions microphone ? En tout cas je n'avais pas vu le problème sous cet angle merci je te tiens au jus.

        • Partager sur Facebook
        • Partager sur Twitter
          17 juin 2019 à 13:04:24

          Les sons sont déjà compatibles. Il n'y a pas de conversion. Peux y avoir une décompression comme Spotify et l'application décompile le son mais il y a une partie minimale chargé, avec une connexion lente tu auras toujours 5 à 10 secondes préchargées avant d'être lu. Le logiciel envoi ensuite directement dans les écouteurs. Le chargement et l'envoi sont 2 processus simultanés.
          • Partager sur Facebook
          • Partager sur Twitter

          Cordialement,

          Neross

          Vous pouvez m'ajouter sur Discord : Neross#8583

            17 juin 2019 à 13:20:44

            Du coup, j'ai fais comme tu m'as dit en utilisant aussi un Thread mais ça ne règle pas le souci, il y a toujours les grésillements.
            Voici mon code, tu vois où est le problème ? Normalement, comme c'est en paralelle wasapi a le temps de record alors ça vient bien d'un problème dans une des fonctions ?

                    public void InputBufferToFileCallback(object sender, WaveInEventArgs e)
                    {
                        byte[] realbytes = new byte[e.BytesRecorded];
                        Array.Copy(e.Buffer, realbytes, e.BytesRecorded);
                        writebuffer.Enqueue(realbytes);
                    }
            
                    private void SendSoundThread()
                    {
                        while (isRunning)
                        {
                            if (writebuffer.Count > 0)
                            {
                                var buf = writebuffer.Dequeue();
                                buf = Convert16(buf, buf.Length, waveFormatIn);
                                convertedWriter.Write(buf, 0, buf.Length);
                            }
                        }
                    }



            -
            Edité par Timothée Dautrême 17 juin 2019 à 13:24:01

            • Partager sur Facebook
            • Partager sur Twitter
              17 juin 2019 à 14:21:01

              Après tu utilise de l'UDP, à tu essayer en TCP ?

              En UDP tu a de grande chance d'avoir une perte de données, ce qui peux créer des blancs.

              Par exemple Twitch utilise un lecteur TCP et non UDP pour éviter la perte de données.

              Autre exemple plus représentatif de ton cas Spotify : http://pansentient.com/2011/04/spotify-technology-some-stats-and-how-spotify-works/

              Spotify travail aussi en TCP pour éviter la perte de données.

              Ce ne sont que des pistes, je ne te garantie pas le bon fonctionnement direct. ^^'

              • Partager sur Facebook
              • Partager sur Twitter

              Cordialement,

              Neross

              Vous pouvez m'ajouter sur Discord : Neross#8583

                17 juin 2019 à 14:39:14

                Non mais là le problème c'est pas le réseau puisque même quand j’écris dans un fichier wav les bruits blancs sont là. Ducoup tcp ou pas bah ça change rien et j’essaie de faire une appli qui stream en live donc pas trop comme spotify. J'ai testé un autre converter mais il convertit qu'en 16 bit, il change pas le sample rate mais au moins il divise par 2 le bitrate et le poid donc 191 ko pour une seconde mais ça reste trop pour upload sur une connexion faible
                comme la mienne (Je download a 45 ko/s et upload a 9 ko/s, ne juge pas stp :lol:, j'ai peut-être fait le speedtest au mauvais moment)...
                • Partager sur Facebook
                • Partager sur Twitter

                C# NAudio probleme resampling 32bit vers 16 bit

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown