Пример #1
0
        /// <summary>
        /// Sends a pseudo-random sample to replicate white noise.
        /// </summary>
        private void SendNoiseSample(object state)
        {
            lock (_audioStreamTimer)
            {
                int     bufferSize = SAMPLE_RATE / 1000 * AUDIO_SAMPLE_PERIOD_MILLISECONDS;
                float[] linear     = new float[bufferSize];
                _signalGenerator.Read(linear, 0, bufferSize);

                byte[] encodedSample = new byte[bufferSize];

                short[] pcm = linear.Select(x => (short)(x * 32767f)).ToArray();

                if (_sendingFormat.FormatCodec == SDPMediaFormatsEnum.G722)
                {
                    _g722Codec.Encode(_g722CodecState, encodedSample, pcm, bufferSize);
                }
                else
                {
                    for (int index = 0; index < bufferSize; index++)
                    {
                        if (_sendingFormat.FormatCodec == SDPMediaFormatsEnum.PCMA)
                        {
                            encodedSample[index] = ALawEncoder.LinearToALawSample(pcm[index]);
                        }
                        else
                        {
                            encodedSample[index] = MuLawEncoder.LinearToMuLawSample(pcm[index]);
                        }
                    }
                }

                SendAudioFrame((uint)bufferSize, (int)_sendingFormat.FormatCodec, encodedSample);
            }
        }
Пример #2
0
        public byte[] EncodeAudio(short[] pcm, AudioFormat format)
        {
            if (format.Codec == AudioCodecsEnum.G722)
            {
                if (_g722Codec == null)
                {
                    _g722Codec      = new G722Codec();
                    _g722CodecState = new G722CodecState(G722_BIT_RATE, G722Flags.None);
                }

                int    outputBufferSize = pcm.Length / 2;
                byte[] encodedSample    = new byte[outputBufferSize];
                int    res = _g722Codec.Encode(_g722CodecState, encodedSample, pcm, pcm.Length);

                return(encodedSample);
            }
            else if (format.Codec == AudioCodecsEnum.PCMA)
            {
                return(pcm.Select(x => ALawEncoder.LinearToALawSample(x)).ToArray());
            }
            else if (format.Codec == AudioCodecsEnum.PCMU)
            {
                return(pcm.Select(x => MuLawEncoder.LinearToMuLawSample(x)).ToArray());
            }
            else if (format.Codec == AudioCodecsEnum.L16)
            {
                // When netstandard2.1 can be used.
                //return MemoryMarshal.Cast<short, byte>(pcm)

                // Put on the wire in network byte order (big endian).
                return(pcm.SelectMany(x => new byte[] { (byte)(x >> 8), (byte)(x) }).ToArray());
            }
            else if (format.Codec == AudioCodecsEnum.PCM_S16LE)
            {
                // Put on the wire as little endian.
                return(pcm.SelectMany(x => new byte[] { (byte)(x), (byte)(x >> 8) }).ToArray());
            }
            else
            {
                throw new ApplicationException($"Audio format {format.Codec} cannot be encoded.");
            }
        }
Пример #3
0
        /// <summary>
        /// Event handler for audio sample being supplied by local capture device.
        /// </summary>
        private void LocalAudioSampleAvailable(object sender, WaveInEventArgs args)
        {
            byte[] sample      = new byte[args.Buffer.Length / 2];
            int    sampleIndex = 0;

            if (_sendingAudioFormat.FormatCodec == SDPMediaFormatsEnum.PCMA || _sendingAudioFormat.FormatCodec == SDPMediaFormatsEnum.PCMU)
            {
                for (int index = 0; index < args.BytesRecorded; index += 2)
                {
                    if (_sendingAudioFormat.FormatCodec == SDPMediaFormatsEnum.PCMU)
                    {
                        var ulawByte = NAudio.Codecs.MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(args.Buffer, index));
                        sample[sampleIndex++] = ulawByte;
                    }
                    else if (_sendingAudioFormat.FormatCodec == SDPMediaFormatsEnum.PCMA)
                    {
                        var alawByte = NAudio.Codecs.ALawEncoder.LinearToALawSample(BitConverter.ToInt16(args.Buffer, index));
                        sample[sampleIndex++] = alawByte;
                    }
                }

                base.SendAudioFrame(_rtpAudioTimestampPeriod, Convert.ToInt32(_sendingAudioFormat.FormatID), sample);
            }
            else if (_sendingAudioFormat.FormatCodec == SDPMediaFormatsEnum.G722)
            {
                // NAudio provides 16 Bit PCM little endian samples. Each sample consists of two bytes.
                short[] inBuffer = new short[args.Buffer.Length / 2];
                for (int index = 0; index < args.BytesRecorded; index += 2)
                {
                    inBuffer[sampleIndex++] = BitConverter.ToInt16(args.Buffer, index);
                }

                byte[] outBuffer = new byte[inBuffer.Length / 2];

                int encodedSamples = _g722Encode.Encode(_g722EncodeState, outBuffer, inBuffer, inBuffer.Length);

                //Log.LogDebug($"g722 encode input samples {args.Buffer.Length}, encoded samples {encodedSamples}, output buffer length {outBuffer.Length}.");

                base.SendAudioFrame(_rtpAudioTimestampPeriod, Convert.ToInt32(_sendingAudioFormat.FormatID), outBuffer);
            }
        }
Пример #4
0
        /// <summary>
        /// Encodes a 16 bit PCM sample and sends to the remote party.
        /// </summary>
        /// <param name="sample">The PCM 16 bit *=8KHz sample to send.</param>
        /// <param name="sampleLength">The length of the sample</param>
        /// <param name="sampleRate">The sample rate of either 8 or 16 KHz for the supplied sample.</param>
        private void EncodeAndSendAudioSample(byte[] sample, int sampleLength, AudioSamplingRatesEnum sampleRate)
        {
            byte[] encodedSample = null;

            // Convert buffer into a PCM sample (array of signed shorts) that's
            // suitable for input into the chosen encoder.
            short[] pcm = new short[sampleLength / 2];
            for (int i = 0; i < pcm.Length; i++)
            {
                pcm[i] = BitConverter.ToInt16(sample, i * 2);
            }

            if (_sendingFormat.FormatCodec == SDPMediaFormatsEnum.G722)
            {
                if (sampleRate == AudioSamplingRatesEnum.SampleRate16KHz)
                {
                    // No up sampling required.
                    int outputBufferSize = pcm.Length / 2;
                    encodedSample = new byte[outputBufferSize];
                    int res = _g722Codec.Encode(_g722CodecState, encodedSample, pcm, pcm.Length);
                }
                else
                {
                    // Up sample the supplied PCM signal by doubling each sample.
                    int outputBufferSize = pcm.Length;
                    encodedSample = new byte[outputBufferSize];

                    short[] pcmUpsampled = new short[pcm.Length * 2];
                    for (int i = 0; i < pcm.Length; i++)
                    {
                        pcmUpsampled[i * 2]     = pcm[i];
                        pcmUpsampled[i * 2 + 1] = pcm[i];
                    }

                    _g722Codec.Encode(_g722CodecState, encodedSample, pcmUpsampled, pcmUpsampled.Length);
                }
            }
            else
            {
                Func <short, byte> encode = (_sendingFormat.FormatCodec == SDPMediaFormatsEnum.PCMA)
                    ? (Func <short, byte>)ALawEncoder.LinearToALawSample
                    : MuLawEncoder.LinearToMuLawSample;

                if (sampleRate == AudioSamplingRatesEnum.SampleRate8KHz)
                {
                    // No down sampling required.
                    int outputBufferSize = pcm.Length;
                    encodedSample = new byte[outputBufferSize];

                    for (int index = 0; index < pcm.Length; index++)
                    {
                        encodedSample[index] = encode(pcm[index]);
                    }
                }
                else
                {
                    // Down sample the supplied PCM signal by skipping every second sample.
                    int outputBufferSize = pcm.Length / 2;
                    encodedSample = new byte[outputBufferSize];
                    int encodedIndex = 0;

                    // Skip every second sample.
                    for (int index = 0; index < pcm.Length; index += 2)
                    {
                        encodedSample[encodedIndex++] = encode(pcm[index]);
                    }
                }
            }

            int sampleRateTicks      = (sampleRate == AudioSamplingRatesEnum.SampleRate8KHz) ? 8000 : 16000;
            int durationMilliseconds = (sample.Length * 1000) / (sampleRateTicks * 2);
            int rtpTimestampDuration = _sendingAudioRtpRate / 1000 * durationMilliseconds;

            //Log.LogDebug($"send audio frame sample rate {sampleRateTicks}, duration ms {durationMilliseconds}, rtp timestamp duration {rtpTimestampDuration}.");

            SendAudioFrame((uint)rtpTimestampDuration, (int)_sendingFormat.FormatCodec, encodedSample);
        }
Пример #5
0
        public byte[] EncodeAudio(short[] pcm, AudioCodecsEnum codec, AudioSamplingRatesEnum sampleRate)
        {
            byte[] encodedSample = null;

            if (codec == AudioCodecsEnum.G722)
            {
                if (_g722Codec == null)
                {
                    _g722Codec      = new G722Codec();
                    _g722CodecState = new G722CodecState(G722_BIT_RATE, G722Flags.None);
                }

                if (sampleRate == AudioSamplingRatesEnum.Rate16KHz)
                {
                    // No up sampling required.
                    int outputBufferSize = pcm.Length / 2;
                    encodedSample = new byte[outputBufferSize];
                    int res = _g722Codec.Encode(_g722CodecState, encodedSample, pcm, pcm.Length);
                }
                else
                {
                    // Up sample the supplied PCM signal by doubling each sample.
                    int outputBufferSize = pcm.Length;
                    encodedSample = new byte[outputBufferSize];

                    short[] pcmUpsampled = new short[pcm.Length * 2];
                    for (int i = 0; i < pcm.Length; i++)
                    {
                        pcmUpsampled[i * 2]     = pcm[i];
                        pcmUpsampled[i * 2 + 1] = pcm[i];
                    }

                    _g722Codec.Encode(_g722CodecState, encodedSample, pcmUpsampled, pcmUpsampled.Length);
                }

                return(encodedSample);
            }
            else if (codec == AudioCodecsEnum.PCMA ||
                     codec == AudioCodecsEnum.PCMU)
            {
                Func <short, byte> encode = (codec == AudioCodecsEnum.PCMA) ?
                                            (Func <short, byte>)ALawEncoder.LinearToALawSample : MuLawEncoder.LinearToMuLawSample;

                if (sampleRate == AudioSamplingRatesEnum.Rate8KHz)
                {
                    // No down sampling required.
                    int outputBufferSize = pcm.Length;
                    encodedSample = new byte[outputBufferSize];

                    for (int index = 0; index < pcm.Length; index++)
                    {
                        encodedSample[index] = encode(pcm[index]);
                    }
                }
                else
                {
                    // Down sample the supplied PCM signal by skipping every second sample.
                    int outputBufferSize = pcm.Length / 2;
                    encodedSample = new byte[outputBufferSize];
                    int encodedIndex = 0;

                    // Skip every second sample.
                    for (int index = 0; index < pcm.Length; index += 2)
                    {
                        encodedSample[encodedIndex++] = encode(pcm[index]);
                    }
                }

                return(encodedSample);
            }
            else
            {
                throw new ApplicationException($"Audio format {codec} cannot be encoded.");
            }
        }