示例#1
0
        private void WritePCM16(float *data, int length)
        {
            if (_outputBuffer == null || _outputBuffer.Length != (length * sizeof(Int16)))
            {
                _outputBuffer = null;
                _outputBuffer = new byte[length * sizeof(Int16)];
            }
            var ptr = data;

            for (var i = 0; i < length; i++)
            {
                var average = (Int16)(((*ptr++ + *ptr++) / 2) * 32767.0f);
                _outputBuffer[(i * 2)]     = (byte)(average & 0x00ff);
                _outputBuffer[(i * 2) + 1] = (byte)(average >> 8);
            }
            int buffer_length = length * sizeof(Int16);

            System.Buffer.BlockCopy(_outputBuffer, 0, resampleStream.SourceBuffer, 0, buffer_length);
            int sourceBytesConverted = 0;

            var convertedBytes = resampleStream.Convert(buffer_length, out sourceBytesConverted);

            if (sourceBytesConverted != buffer_length)
            {
                Console.WriteLine("We didn't convert everything");
            }
            TrxwaveFile.Write(resampleStream.DestBuffer, 0, convertedBytes);
        }
示例#2
0
        protected override byte[] ProcessRecordedData(byte[] recorded, int offset, int count)
        {
            lock (lockObject)
            {
                int    sourceSamples = count / 4;
                int    outSamples    = sourceSamples;
                byte[] sourceBuffer  = new byte[sourceSamples * 4];
                Buffer.BlockCopy(recorded, offset, sourceBuffer, 0, sourceSamples * 4);
                byte[]     outBuffer        = new byte[outSamples * 2];
                WaveBuffer sourceWaveBuffer = new WaveBuffer(sourceBuffer);
                WaveBuffer destWaveBuffer   = new WaveBuffer(outBuffer);
                int        destOffset       = 0;
                for (int sample = 0; sample < sourceSamples; sample++)
                {
                    #region 32 bit float to 16bit short, same channels

                    float sample32 = sourceWaveBuffer.FloatBuffer[sample] * 1.0f;              // clip
                    if (sample32 > 1.0f)
                    {
                        sample32 = 1.0f;
                    }
                    if (sample32 < -1.0f)
                    {
                        sample32 = -1.0f;
                    }
                    destWaveBuffer.ShortBuffer[destOffset++] = (short)(sample32 * Int16.MaxValue);

                    #endregion

                    #region 32 bit float to 16bit short, combine left and right channels
                    // adjust volume
                    //float leftSample32 = sourceWaveBuffer.FloatBuffer[sample] * 1.0f;              // clip
                    //if (leftSample32 > 1.0f)
                    //    leftSample32 = 1.0f;
                    //if (leftSample32 < -1.0f)
                    //    leftSample32 = -1.0f;

                    //float rightSample32 = sourceWaveBuffer.FloatBuffer[sample + 1] * 1.0f;

                    //if (rightSample32 > 1.0f)
                    //    rightSample32 = 1.0f;
                    //if (rightSample32 < -1.0f)
                    //    rightSample32 = -1.0f;

                    //short spl = (short)(((leftSample32 * Int16.MaxValue) + (int)(rightSample32 * Int16.MaxValue)) / 2);

                    //destWaveBuffer.ShortBuffer[destOffset++] = spl;
                    #endregion
                }
                Array.Copy(destWaveBuffer.ByteBuffer, convertionStream.SourceBuffer, outSamples * 2);
                int converted = convertionStream.Convert(outSamples * 2);
                converted -= converted % 4;
                byte[] result = new byte[converted];
                Array.Copy(convertionStream.DestBuffer, result, converted);
                return(base.ProcessRecordedData(result, 0, converted));
            }
        }
示例#3
0
        private static byte[] ResamplePcm(ref byte[] toResample, ref int sourceLength, WaveFormat sourceFormat, WaveFormat destPcmFormat, out int resultLength)
        {
            Debug.Assert(destPcmFormat.Encoding == WaveFormatEncoding.Pcm, "Codec format must be PCM");

            if (resampleRateStream != null && (!lastResampleSourceFormat.Equals(sourceFormat) || !lastResampleDestFormat.Equals(destPcmFormat)))
            {
                resampleRateStream.Dispose();
                resampleRateStream = null;
            }
            if (resampleRateStream == null)
            {
                WaveFormat sourceRateFormat = new WaveFormat(sourceFormat.SampleRate, sourceFormat.BitsPerSample, destPcmFormat.Channels);
                resampleRateStream = new AcmStream(sourceRateFormat, destPcmFormat);
                if (sourceFormat.Channels != destPcmFormat.Channels)
                {
                    WaveFormat destChanFormat = new WaveFormat(sourceFormat.SampleRate, sourceFormat.BitsPerSample, destPcmFormat.Channels);
                    if (resampleChannelStream != null)
                    {
                        resampleChannelStream.Dispose();
                    }
                    resampleChannelStream = new AcmStream(sourceFormat, destChanFormat);
                }
                lastResampleSourceFormat = sourceFormat;
                lastResampleDestFormat   = destPcmFormat;
            }

            int bytesConverted;

            if (sourceFormat.Channels != destPcmFormat.Channels)
            {
                if (destPcmFormat.Channels == 1 && sourceFormat.Channels == 2)
                {
                    toResample   = MixStereoToMono(toResample, sourceLength);
                    sourceLength = toResample.Length;
                }
                else
                {
                    Buffer.BlockCopy(toResample, 0, resampleChannelStream.SourceBuffer, 0, sourceLength);
                    sourceLength = resampleChannelStream.Convert(sourceLength, out bytesConverted);
                    if (bytesConverted >> 1 != sourceLength)
                    {
                        Console.WriteLine("WARNING: All input bytes were not converted.");
                    }
                    toResample = resampleChannelStream.DestBuffer;
                }
            }

            Buffer.BlockCopy(toResample, 0, resampleRateStream.SourceBuffer, 0, sourceLength);
            resultLength = resampleRateStream.Convert(sourceLength, out bytesConverted);
            if (bytesConverted != sourceLength)
            {
                Console.WriteLine("WARNING: All input bytes were not converted.");
                return(null);
            }

            return(resampleRateStream.DestBuffer);
        }
示例#4
0
        public static async Task ConvertForDiscord(byte[] audiodata, int sampleRate, int channels, VoiceTransmitSink discordTarget, ILogger logger)
        {
            var resampleStream = new AcmStream(new WaveFormat(sampleRate, 16, 1), new WaveFormat(OutSampleRate, 16, 1));

            if (audiodata.Length > resampleStream.SourceBuffer.Length)
            {
                int offset = 0;
                logger.LogInformation("Large audio returned, the copy will need to be streamed in");
                int remaining = (audiodata.Length - offset);
                while (remaining > 0)
                {
                    Array.Clear(resampleStream.SourceBuffer, 0, resampleStream.SourceBuffer.Length);
                    Array.Clear(resampleStream.DestBuffer, 0, resampleStream.DestBuffer.Length);
                    int copyamount = remaining > resampleStream.SourceBuffer.Length ? resampleStream.SourceBuffer.Length : remaining;
                    Buffer.BlockCopy(audiodata, offset, resampleStream.SourceBuffer, 0, copyamount);
                    int sourceBytesConverted = 0;
                    // logger.LogInformation("Resampling");
                    var convertedBytes = resampleStream.Convert(copyamount, out sourceBytesConverted);
                    if (sourceBytesConverted != copyamount)
                    {
                        logger.LogError("Resample didn't produce correct bytestream");
                        break;
                    }
                    await discordTarget.WriteAsync(resampleStream.DestBuffer);

                    offset   += copyamount;
                    remaining = (audiodata.Length - offset);
                }
            }
            else
            {
                Buffer.BlockCopy(audiodata, 0, resampleStream.SourceBuffer, 0, audiodata.Length);
                int sourceBytesConverted = 0;
                // logger.LogInformation("Resampling");
                var convertedBytes = resampleStream.Convert(audiodata.Length, out sourceBytesConverted);
                if (sourceBytesConverted != audiodata.Length)
                {
                    logger.LogError("Resample didn't produce correct bytestream");
                }
                await discordTarget.WriteAsync(resampleStream.DestBuffer);
            }
        }
示例#5
0
        private void WritePCM16(float *data, int length)
        {
            if (_outputBuffer == null || _outputBuffer.Length != (length * sizeof(Int16)))
            {
                _outputBuffer = null;
                _outputBuffer = new byte[length * sizeof(Int16)];
            }
            var ptr = data;

            for (var i = 0; i < length; i++)
            {
                var average = (Int16)(((*ptr++ + *ptr++) / 2) * 32767.0f);
                _outputBuffer[(i * 2)]     = (byte)(average & 0x00ff);
                _outputBuffer[(i * 2) + 1] = (byte)(average >> 8);
            }
            int buffer_length = length * sizeof(Int16);

            System.Buffer.BlockCopy(_outputBuffer, 0, resampleStream.SourceBuffer, 0, buffer_length);
            int sourceBytesConverted = 0;

            var convertedBytes = resampleStream.Convert(buffer_length, out sourceBytesConverted);

            if (sourceBytesConverted != buffer_length)
            {
                Console.WriteLine("We didn't convert everything");
            }
            var converted = new byte[convertedBytes];

            System.Buffer.BlockCopy(resampleStream.DestBuffer, 0, converted, 0, convertedBytes);
            int counter = 0;

            byte[] packet   = new byte[MAX_PAYLOAD];
            var    TxStream = new WaveFormat(48000, 16, 1);

            for (var i = 0; i < convertedBytes; i++)
            {
                if (counter == MAX_PAYLOAD)
                {
                    _udpClient.Send(packet, counter, _udpEP);
                    MarkAndWait(counter, TxStream.AverageBytesPerSecond);
                    counter = 0;
                }
                packet[counter] = converted[i];
                counter++;
            }
            if (counter > 0)
            {
                counter--;
                _udpClient.Send(packet, counter, _udpEP);
                MarkAndWait(counter, TxStream.AverageBytesPerSecond);
            }
        }
示例#6
0
        public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
        {
            Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
            int sourceBytesConverted = 0;
            int converted            = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted);

            if (sourceBytesConverted != frame.FrameLength)
            {
                throw new InvalidOperationException("Couldn't convert the whole MP3 frame");
            }
            Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, converted);
            return(converted);
        }
示例#7
0
        private static byte[] Convert(AcmStream conversionStream, byte[] data, int offset, int length, ref int sourceBytesLeftovers)
        {
            int bytesInSourceBuffer = length + sourceBytesLeftovers;

            Array.Copy(data, offset, conversionStream.SourceBuffer, sourceBytesLeftovers, length);
            int bytesConverted = conversionStream.Convert(bytesInSourceBuffer, out var sourceBytesConverted);

            sourceBytesLeftovers = bytesInSourceBuffer - sourceBytesConverted;
            if (sourceBytesLeftovers > 0)
            {
                Array.Copy(conversionStream.SourceBuffer, sourceBytesConverted, conversionStream.SourceBuffer, 0, sourceBytesLeftovers);
            }
            byte[] encoded = new byte[bytesConverted];
            Array.Copy(conversionStream.DestBuffer, 0, encoded, 0, bytesConverted);
            return(encoded);
        }
示例#8
0
        public void ProcessSamples(bool bHasAudio, byte[] samples)
        {
            if (samples == null || samples.Length <= 0)
            {
                return;
            }

            if (bHasAudio)
            {
                KickRecording(AudioKickState.Kick);
            }
            if (_recordingEnabled && _waveWriter != null)
            {
                if (_useResampler)
                {
                    Buffer.BlockCopy(samples, 0, _resampleStream.SourceBuffer, 0, samples.Length);
                    int sourceBytesConverted = 0;
                    int convertedBytes       = _resampleStream.Convert(samples.Length, out sourceBytesConverted);
                    if (sourceBytesConverted == samples.Length)
                    {
                        byte[] convBytes = new byte[convertedBytes];
                        Buffer.BlockCopy(_resampleStream.DestBuffer, 0, convBytes, 0, convertedBytes);
                        _waveWriter.Write(convBytes, 0, convBytes.Length);
                    }
                }
                else
                {
                    _waveWriter.Write(samples, 0, samples.Length);
                }
            }

            long curTicks = DateTime.Now.Ticks;

            if (_currentKickState == AudioKickState.On)
            {
                if (_forceOnEndTicks == 0 || _forceOnEndTicks < curTicks)
                {
                    _forceOnEndTicks  = 0;
                    _endTicks         = curTicks + RecordingKickTimeTicks;
                    _currentKickState = AudioKickState.Kick;
                }
            }
            else if (!_recordingEnabled || (_endTicks == 0) || (_currentKickState == AudioKickState.Kick && _endTicks < DateTime.Now.Ticks))
            {
                EndRecording();
            }
        }
示例#9
0
        /// <summary>
        /// Decompresses a frame
        /// </summary>
        /// <param name="frame">The MP3 frame</param>
        /// <param name="dest">destination buffer</param>
        /// <param name="destOffset">Offset within destination buffer</param>
        /// <returns>Bytes written into destination buffer</returns>
        public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
        {
            if (frame == null)
            {
                throw new ArgumentNullException("frame", "You must provide a non-null Mp3Frame to decompress");
            }
            Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
            int converted = conversionStream.Convert(frame.FrameLength, out int sourceBytesConverted);

            if (sourceBytesConverted != frame.FrameLength)
            {
                throw new InvalidOperationException(String.Format("Couldn't convert the whole MP3 frame (converted {0}/{1})",
                                                                  sourceBytesConverted, frame.FrameLength));
            }
            Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, converted);
            return(converted);
        }
示例#10
0
        private async Task PlayAudioAsync(IAudioClient client)
        {
            var discord = client.CreatePCMStream(AudioApplication.Music);
            WasapiLoopbackCapture CaptureInstance = new WasapiLoopbackCapture(WasapiLoopbackCapture.GetDefaultLoopbackCaptureDevice());

            CaptureInstance.DataAvailable += (s, a) =>
            {
                //step 1
                //var resampleStream = new AcmStream(WaveFormat.CreateCustomFormat(WaveFormatEncoding.IeeeFloat, 48000, 2, 384000, 8, 32), WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 48000, 2, 16000, 8, 16));
                var resampleStream = new AcmStream(new WaveFormat(41000, 16, 2), new WaveFormat(4800, 16, 2));                 //causes demonic screeching

                //step 2
                byte[] source = a.Buffer;
                Buffer.BlockCopy(source, 0, resampleStream.SourceBuffer, 0, a.BytesRecorded);

                //step 3
                int sourceBytesConverted = 0;
                var convertedBytes       = resampleStream.Convert(source.Length, out sourceBytesConverted);
                if (sourceBytesConverted != source.Length)
                {
                    Console.WriteLine("We didn't convert everything {0} bytes in, {1} bytes converted");
                }

                //step 4
                var converted = new byte[convertedBytes];
                Buffer.BlockCopy(resampleStream.DestBuffer, 0, converted, 0, convertedBytes);


                discord.Write(converted, 0, a.BytesRecorded);
            };

            CaptureInstance.RecordingStopped += (s, a) =>
            {
                Console.WriteLine("Stopped Recording!");
                CaptureInstance.Dispose();
                discord.Dispose();
            };

            CaptureInstance.StartRecording();

            await Task.Delay(5000);

            CaptureInstance.StopRecording();
            await Task.Delay(5000);
        }
        private static byte[] Convert(AcmStream conversionStream, byte[] data, int offset, int length, ref int sourceBytesLeftovers)
        {
            int bytesInSourceBuffer = length + sourceBytesLeftovers;

            Array.Copy(data, offset, conversionStream.SourceBuffer, sourceBytesLeftovers, length);
            int bytesConverted = conversionStream.Convert(bytesInSourceBuffer, out var sourceBytesConverted);

            sourceBytesLeftovers = bytesInSourceBuffer - sourceBytesConverted;
            if (sourceBytesLeftovers > 0)
            {
                //Debug.WriteLine(String.Format("Asked for {0}, converted {1}", bytesInSourceBuffer, sourceBytesConverted));
                // shift the leftovers down
                Array.Copy(conversionStream.SourceBuffer, sourceBytesConverted, conversionStream.SourceBuffer, 0, sourceBytesLeftovers);
            }
            byte[] encoded = new byte[bytesConverted];
            Array.Copy(conversionStream.DestBuffer, 0, encoded, 0, bytesConverted);
            return(encoded);
        }
示例#12
0
        static void Main(string[] args)
        {
            var fi = new FileInfo(args[0]);
            var fn = fi.FullName;

            using (var wfr = new WaveFileReader(fn))
            {
                var wf0   = wfr.WaveFormat;
                var wf1   = new WaveFormat(48000, 1);
                var size0 = wf0.AverageBytesPerSecond * RNNoiseCLR.FRAME_SIZE / 48000;
                var size1 = sizeof(short) * RNNoiseCLR.FRAME_SIZE;
                using (var acmr = new AcmStream(wf0, wf1))
                    using (var wfw = new WaveFileWriter(fn.Substring(0, fn.Length - fi.Extension.Length) + "_out" + fi.Extension, wf0))
                        using (var acmw = new AcmStream(wf1, wf0))
                            using (var rnn = new RNNoiseCLR())
                            {
                                var samples  = new short[RNNoiseCLR.FRAME_SIZE];
                                var _samples = new float[RNNoiseCLR.FRAME_SIZE];
                                int read;
                                while ((read = wfr.Read(acmr.SourceBuffer, 0, size0)) > 0)
                                {
                                    var converted = acmr.Convert(read, out _);
                                    for (var i = converted; i < size1; ++i)
                                    {
                                        acmr.DestBuffer[i] = 0;
                                    }
                                    Buffer.BlockCopy(acmr.DestBuffer, 0, samples, 0, size1);
                                    for (var i = 0; i < RNNoiseCLR.FRAME_SIZE; ++i)
                                    {
                                        _samples[i] = samples[i] * _32767;
                                    }
                                    rnn.Transform(_samples, _samples);
                                    for (var i = 0; i < RNNoiseCLR.FRAME_SIZE; ++i)
                                    {
                                        samples[i] = (short)(_samples[i] * 32767);
                                    }
                                    Buffer.BlockCopy(samples, 0, acmw.SourceBuffer, 0, converted);
                                    wfw.Write(acmw.DestBuffer, 0, acmw.Convert(converted, out _));
                                    wfw.Flush();
                                }
                            }
            }
        }
        //private int leftoverSourceOffset = 0;

        /// <summary>
        /// Reads bytes from this stream
        /// </summary>
        /// <param name="buffer">Buffer to read into</param>
        /// <param name="offset">Offset in buffer to read into</param>
        /// <param name="count">Number of bytes to read</param>
        /// <returns>Number of bytes read</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = 0;

            if (count % BlockAlign != 0)
            {
                //throw new ArgumentException("Must read complete blocks");
                count -= (count % BlockAlign);
            }

            while (bytesRead < count)
            {
                // first copy in any leftover destination bytes
                int readFromLeftoverDest = Math.Min(count - bytesRead, leftoverDestBytes);
                if (readFromLeftoverDest > 0)
                {
                    Array.Copy(conversionStream.DestBuffer, leftoverDestOffset, buffer, offset + bytesRead, readFromLeftoverDest);
                    leftoverDestOffset += readFromLeftoverDest;
                    leftoverDestBytes  -= readFromLeftoverDest;
                    bytesRead          += readFromLeftoverDest;
                }
                if (bytesRead >= count)
                {
                    // we've fulfilled the request from the leftovers alone
                    break;
                }

                // now we'll convert one full source buffer
                if (leftoverSourceBytes > 0)
                {
                    // TODO: still to be implemented: see moving the source position back below:
                }

                // always read our preferred size, we can always keep leftovers for the next call to Read if we get
                // too much
                int sourceBytesRead = sourceStream.Read(conversionStream.SourceBuffer, 0, preferredSourceReadSize);
                if (sourceBytesRead == 0)
                {
                    // we've reached the end of the input
                    break;
                }

                int sourceBytesConverted;
                int destBytesConverted = conversionStream.Convert(sourceBytesRead, out sourceBytesConverted);
                if (sourceBytesConverted == 0)
                {
                    Debug.WriteLine(String.Format("Warning: couldn't convert anything from {0}", sourceBytesRead));
                    // no point backing up in this case as we're not going to manage to finish playing this
                    break;
                }
                else if (sourceBytesConverted < sourceBytesRead)
                {
                    // cheat by backing up in the source stream (better to save the lefto
                    sourceStream.Position -= (sourceBytesRead - sourceBytesConverted);
                }

                if (destBytesConverted > 0)
                {
                    int bytesRequired = count - bytesRead;
                    int toCopy        = Math.Min(destBytesConverted, bytesRequired);

                    // save leftovers
                    if (toCopy < destBytesConverted)
                    {
                        leftoverDestBytes  = destBytesConverted - toCopy;
                        leftoverDestOffset = toCopy;
                    }
                    Array.Copy(conversionStream.DestBuffer, 0, buffer, bytesRead + offset, toCopy);
                    bytesRead += toCopy;
                }
                else
                {
                    // possible error here
                    Debug.WriteLine(string.Format("sourceBytesRead: {0}, sourceBytesConverted {1}, destBytesConverted {2}",
                                                  sourceBytesRead, sourceBytesConverted, destBytesConverted));
                    //Debug.Assert(false, "conversion stream returned nothing at all");
                    break;
                }
            }
            position += bytesRead;
            return(bytesRead);
        }
示例#14
0
        /// <summary>
        /// Reads bytes from this stream
        /// </summary>
        /// <param name="array">Buffer to read into</param>
        /// <param name="offset">Offset in array to read into</param>
        /// <param name="count">Number of bytes to read</param>
        /// <returns>Number of bytes read</returns>
        public override int Read(byte[] array, int offset, int count)
        {
            int bytesRead = 0;

            if (count % BlockAlign != 0)
            {
                //throw new ApplicationException("Must read complete blocks");
                count -= (count % BlockAlign);
            }

            while (bytesRead < count)
            {
                int destBytesRequired = count - bytesRead;
                int sourceBytes       = DestToSource(destBytesRequired);

                sourceBytes = Math.Min(conversionStream.SourceBuffer.Length, sourceBytes);
                // temporary fix for alignment problems
                // TODO: a better solution is to save any extra we convert for the next read

                /* MRH: ignore this for now - need to check ramifications
                 * if (DestToSource(SourceToDest(sourceBytes)) != sourceBytes)
                 * {
                 *  if (bytesRead == 0)
                 *      throw new ApplicationException("Not a one-to-one conversion");
                 *  break;
                 * }*/

                int sourceBytesRead = sourceStream.Read(conversionStream.SourceBuffer, 0, sourceBytes);
                if (sourceBytesRead == 0)
                {
                    break;
                }
                int silenceBytes = 0;
                if (sourceBytesRead % sourceStream.BlockAlign != 0)
                {
                    // we have been returned something that cannot be converted - a partial
                    // buffer. We will increase the size we supposedly read, and zero out
                    // the end.
                    sourceBytesRead -= (sourceBytesRead % sourceStream.BlockAlign);
                    sourceBytesRead += sourceStream.BlockAlign;
                    silenceBytes     = SourceToDest(sourceStream.BlockAlign);
                }

                int sourceBytesConverted;
                int bytesConverted = conversionStream.Convert(sourceBytesRead, out sourceBytesConverted);
                if (sourceBytesConverted < sourceBytesRead)
                {
                    // MRH: would normally throw an exception here
                    // back up - is this the right thing to do, not sure
                    sourceStream.Position -= (sourceBytesRead - sourceBytesConverted);
                }

                if (bytesConverted > 0)
                {
                    position += bytesConverted;
                    int availableSpace = array.Length - bytesRead - offset;
                    int toCopy         = Math.Min(bytesConverted, availableSpace);
                    //System.Diagnostics.Debug.Assert(toCopy == bytesConverted);
                    // TODO: save leftovers
                    Array.Copy(conversionStream.DestBuffer, 0, array, bytesRead + offset, toCopy);
                    bytesRead += toCopy;
                    if (silenceBytes > 0)
                    {
                        // clear out the final bit
                        Array.Clear(array, bytesRead - silenceBytes, silenceBytes);
                    }
                }
                else
                {
                    break;
                }
            }
            return(bytesRead);
        }
示例#15
0
        /// <summary>
        /// Reads bytes from this stream
        /// </summary>
        /// <param name="buffer">Buffer to read into</param>
        /// <param name="offset">Offset in buffer to read into</param>
        /// <param name="count">Number of bytes to read</param>
        /// <returns>Number of bytes read</returns>
        public int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = 0;

            if (count % WaveFormat.BlockAlign != 0)
            {
                //throw new ArgumentException("Must read complete blocks");
                count -= (count % WaveFormat.BlockAlign);
            }

            while (bytesRead < count)
            {
                // first copy in any leftover destination bytes
                int readFromLeftoverDest = Math.Min(count - bytesRead, leftoverDestBytes);
                if (readFromLeftoverDest > 0)
                {
                    Array.Copy(conversionStream.DestBuffer, leftoverDestOffset, buffer, offset + bytesRead, readFromLeftoverDest);
                    leftoverDestOffset += readFromLeftoverDest;
                    leftoverDestBytes  -= readFromLeftoverDest;
                    bytesRead          += readFromLeftoverDest;
                }
                if (bytesRead >= count)
                {
                    // we've fulfilled the request from the leftovers alone
                    break;
                }

                // now we'll convert one full source buffer
                var sourceReadSize = Math.Min(preferredSourceReadSize,
                                              conversionStream.SourceBuffer.Length - leftoverSourceBytes);

                // always read our preferred size, we can always keep leftovers for the next call to Read if we get
                // too much
                int sourceBytesRead      = sourceProvider.Read(conversionStream.SourceBuffer, leftoverSourceBytes, sourceReadSize);
                int sourceBytesAvailable = sourceBytesRead + leftoverSourceBytes;
                if (sourceBytesAvailable == 0)
                {
                    // we've reached the end of the input
                    break;
                }

                int sourceBytesConverted;
                int destBytesConverted = conversionStream.Convert(sourceBytesAvailable, out sourceBytesConverted);
                if (sourceBytesConverted == 0)
                {
                    Debug.WriteLine(String.Format("Warning: couldn't convert anything from {0}", sourceBytesAvailable));
                    // no point backing up in this case as we're not going to manage to finish playing this
                    break;
                }
                leftoverSourceBytes = sourceBytesAvailable - sourceBytesConverted;

                if (leftoverSourceBytes > 0)
                {
                    // buffer.blockcopy is safe for overlapping copies
                    Buffer.BlockCopy(conversionStream.SourceBuffer, sourceBytesConverted, conversionStream.SourceBuffer,
                                     0, leftoverSourceBytes);
                }

                if (destBytesConverted > 0)
                {
                    int bytesRequired = count - bytesRead;
                    int toCopy        = Math.Min(destBytesConverted, bytesRequired);

                    // save leftovers
                    if (toCopy < destBytesConverted)
                    {
                        leftoverDestBytes  = destBytesConverted - toCopy;
                        leftoverDestOffset = toCopy;
                    }
                    Array.Copy(conversionStream.DestBuffer, 0, buffer, bytesRead + offset, toCopy);
                    bytesRead += toCopy;
                }
                else
                {
                    // possible error here
                    Debug.WriteLine(string.Format("sourceBytesRead: {0}, sourceBytesConverted {1}, destBytesConverted {2}",
                                                  sourceBytesRead, sourceBytesConverted, destBytesConverted));
                    //Debug.Assert(false, "conversion stream returned nothing at all");
                    break;
                }
            }
            return(bytesRead);
        }
示例#16
0
        protected override void ProcessSamples(byte[] buffer, int offset, int count)
        {
            float[] samples = null;
            if (_silenceHelper != null)
            {
                samples = _silenceHelper.PreProcessSamplesToFloat(buffer, offset, count, _sourceFormat.BitsPerSample / 8, _sourceFormat.Encoding == WaveFormatEncoding.IeeeFloat);
            }

            base.ProcessSamples(buffer, offset, count);

            byte[] sampleBytes = null;

            if (_useResampler)
            {
                Buffer.BlockCopy(buffer, offset, _resampleStream.SourceBuffer, 0, count);
                int sourceBytesConverted = 0;
                int convertedBytes       = _resampleStream.Convert(count, out sourceBytesConverted);
                if (sourceBytesConverted == count)
                {
                    byte[] convBytes = new byte[convertedBytes];
                    Buffer.BlockCopy(_resampleStream.DestBuffer, 0, convBytes, 0, convertedBytes);
                    sampleBytes = convBytes;
                }
                samples = null;
            }
            else
            {
                byte[] tmpBuffer;
                if (offset == 0)
                {
                    tmpBuffer = buffer;
                }
                else
                {
                    tmpBuffer = new byte[count];
                    Array.Copy(buffer, offset, tmpBuffer, 0, count);
                }
                sampleBytes = tmpBuffer;
            }

            bool bHasSound = _hasAudio;

            if (sampleBytes != null)
            {
                if (samples == null || samples.Length <= 0)
                {
                    samples = BytesToFloatSamples(sampleBytes);
                }
                if (samples != null && samples.Length > 0)
                {
                    bHasSound = _silenceHelper.HasSound;
                    _recorder.ProcessSamples(bHasSound, sampleBytes);
                    if (_mdc != null)
                    {
                        _mdc.ProcessSamples(samples, samples.Length, bHasSound);
                    }
                    if (_star != null)
                    {
                        _star.ProcessSamples(samples, samples.Length, bHasSound);
                    }
                    if (_rootDecoder != null)
                    {
                        _rootDecoder.ProcessSamples(samples, samples.Length, bHasSound);
                    }
                }
            }
            if (bHasSound != _hasAudio)
            {
                _hasAudio = bHasSound;
                FirePropertyChanged(false);
            }
        }