0

I'm using UdpClient to get a RTP stream from phone calls through Avaya DMCC sdk. I would like to play this stream through the computer's speakers. After a lot of searching I've only been able to find solutions that require saving to a file and then playing the file but I need to play the stream through the speakers without saving to a file. I'd like to send audio to the speakers as I receive it.

    public void StartClient()
    {
        // Create new UDP client. The IP end point tells us which IP is sending the data
        client = new UdpClient(port);
        endPoint = new IPEndPoint(System.Net.IPAddress.Any, port);

        selectedCodec = new MuLawChatCodec();
        waveOut = new WaveOut();
        waveProvider = new BufferedWaveProvider(selectedCodec.RecordFormat);
        waveOut.Init(waveProvider);
        waveOut.Play();
        listening = true;
        listenerThread = new Thread(ReceiveCallback);
        listenerThread.Start();

    }

    private void ReceiveCallback()
    {
        // Begin looking for the next packet
        while (listening)
        {
            // Receive packet
            byte[] packet = client.Receive(ref endPoint);

            // Packet header
            int version = GetRTPValue(packet, 0, 1);
            int padding = GetRTPValue(packet, 2, 2);
            int extension = GetRTPValue(packet, 3, 3);
            int csrcCount = GetRTPValue(packet, 4, 7);
            int marker = GetRTPValue(packet, 8, 8);
            int payloadType = GetRTPValue(packet, 9, 15);
            int sequenceNum = GetRTPValue(packet, 16, 31);
            int timestamp = GetRTPValue(packet, 32, 63);
            int ssrcId = GetRTPValue(packet, 64, 95);
            int csrcid = (csrcCount == 0) ? -1 : GetRTPValue(packet, 96, 95 + 32 * (csrcCount));
            int extHeader = (csrcCount == 0) ? -1 : GetRTPValue(packet, 128 + (32 * csrcCount), 127 + (32 * csrcCount));
            int payloadIndex = csrcCount == 0 ? 96 : 128 + 32 * csrcCount;
            int payload = GetRTPValue(packet, payloadIndex, packet.Length);

            byte[] Payload = new byte[packet.Length - payloadIndex];
            Buffer.BlockCopy(packet, payloadIndex, Payload, 0, packet.Length - payloadIndex);
            byte[] decoded = selectedCodec.Decode(Payload, 0, Payload.Length);


        }
    }

    private int GetRTPValue(byte[] packet, int startBit, int endBit)
    {
        int result = 0;

        // Number of bits in value
        int length = endBit - startBit + 1;

        // Values in RTP header are big endian, so need to do these conversions
        for (int i = startBit; i <= endBit; i++)
        {
            int byteIndex = i / 8;
            int bitShift = 7 - (i % 8);
            result += ((packet[byteIndex] >> bitShift) & 1) * (int)Math.Pow(2, length - i + startBit - 1);
        }
        return result;
    }

I now successfully have audio from the call being played over the speakers by adding a byte[] containing just the payload to NAudio's BufferedWaveProvider

1 Answers1

1

There's a demo of how to play audio received over the network included with the NAudio source code (see Network Chat Demo in the NAudioDemo project). Basically use an AcmStream to decode the audio, and then put it into a BufferedWaveProvider which the soundcard is playing from.

Mark Heath
  • 48,273
  • 29
  • 137
  • 194
  • Thanks for the pointer, I had actually been looking at that portion of the NAudioDemo but was having trouble setting the audio codec. I've edited the above post to include code attempting to use NAudio to play the RTP stream. All I hear is a buzzing sound of sorts. – Jonathan Chu Mar 30 '15 at 15:07
  • well that would indicate you've got the wrong codec, or are decoding your RTP packet incorrectly. Also, only the payload should be passed through the codec, not the whole RTP header. – Mark Heath Mar 30 '15 at 15:10