Пример #1
0
 public void QueueChunk(AudioChunk chunk)
 {
     if (_outputDevice != null)
     {
         _activeStream.QueueChunk(chunk);
     }
 }
Пример #2
0
            public void QueueChunk(AudioChunk chunk)
            {
                _streamLock.WaitOne();
                short[]    resampledData  = Lanczos.Resample(chunk.Data, chunk.SampleRate, 44100);
                AudioChunk resampledChunk = new AudioChunk(resampledData, 44100);

                _inputChunks.Enqueue(resampledChunk);
                _streamLock.ReleaseMutex();
            }
Пример #3
0
        public AudioChunk Concatenate(AudioChunk other)
        {
            AudioChunk toConcatenate      = other;
            int        combinedDataLength = DataLength + toConcatenate.DataLength;

            short[] combinedData = new short[combinedDataLength];
            Array.Copy(Data, combinedData, DataLength);
            Array.Copy(toConcatenate.Data, 0, combinedData, DataLength, toConcatenate.DataLength);
            return(new AudioChunk(combinedData, SampleRate));
        }
Пример #4
0
        public byte[] Compress(AudioChunk input)
        {
            int frameSize = GetFrameSize();

            if (input != null)
            {
                short[] newData = input.Data;
                _incomingSamples.Write(newData);
            }
            else
            {
                // If input is null, assume we are at end of stream and pad the output with zeroes
                int paddingNeeded = _incomingSamples.Available() % frameSize;
                if (paddingNeeded > 0)
                {
                    _incomingSamples.Write(new short[paddingNeeded]);
                }
            }

            int outCursor = 0;

            if (_incomingSamples.Available() >= frameSize)
            {
                unsafe
                {
                    fixed(byte *benc = scratchBuffer)
                    {
                        short[] nextFrameData  = _incomingSamples.Read(frameSize);
                        byte[]  nextFrameBytes = AudioMath.ShortsToBytes(nextFrameData);
                        IntPtr  encodedPtr     = new IntPtr(benc);

                        _timer.Reset();
                        _timer.Start();
                        int thisPacketSize = opus_encode(_encoder, nextFrameBytes, frameSize, encodedPtr, scratchBuffer.Length);

                        outCursor += thisPacketSize;
                        _timer.Stop();
                    }
                }
            }

            if (outCursor > 0)
            {
                _statistics.EncodeSpeed = _frameSize / ((double)_timer.ElapsedTicks / Stopwatch.Frequency * 1000);
            }

            byte[] finalOutput = new byte[outCursor];
            Array.Copy(scratchBuffer, 0, finalOutput, 0, outCursor);
            return(finalOutput);
        }
Пример #5
0
        public void Run(object dummy)
        {
            foreach (var inputStream in InputFiles)
            {
                inputStream.Initialize();
            }

            _running = true;

            _player.Start();

            while (_running)
            {
                // Spin until the output buffer has some room
                while (_player.BufferSizeMs() > BUFFER_LENGTH_MS)
                {
                    Thread.Sleep(5);
                }

                // Check for updated parameters and send them to the codec if needed
                _codecParamLock.WaitOne();
                if (_codecParamChanged)
                {
                    _currentCodec.SetBitrate(_bitrate);
                    _currentCodec.SetComplexity(_complexity);
                    _currentCodec.SetFrameSize(_frameSize);
                    _currentCodec.SetPacketLoss(_packetLoss);
                    _currentCodec.SetApplication(_application);
                    _currentCodec.SetVBRMode(_useVBR, _useCVBR);
                    _codecParamChanged = false;
                }

                AudioChunk inputPcm = _currentMusic.ReadChunk();
                _codecParamLock.ReleaseMutex();

                // Run the opus encoder and decoder
                byte[] compressedFrame = _currentCodec.Compress(inputPcm);
                if (compressedFrame != null && compressedFrame.Length > 0)
                {
                    AudioChunk decompressed = _currentCodec.Decompress(compressedFrame);

                    // Pipe the output to the audio device
                    _player.QueueChunk(decompressed);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Sends an encoded audio sample through a decompressor and returns the decoded audio
        /// </summary>
        /// <param name="input"></param>
        /// <param name="decompressor"></param>
        /// <returns></returns>
        internal static AudioChunk DecompressAudioUsingStream(byte[] input, IAudioDecompressionStream decompressor)
        {
            if (decompressor == null)
            {
                return(null);
            }

            AudioChunk first  = decompressor.Decompress(input);
            AudioChunk second = decompressor.Close();

            if (second != null && second.DataLength > 0)
            {
                first = first.Concatenate(second);
            }

            return(first);
        }
Пример #7
0
        /// <summary>
        /// Sends an entire audio chunk through a compressor and returns the byte array output and encode params
        /// </summary>
        /// <param name="audio"></param>
        /// <param name="compressor"></param>
        /// <param name="encodeParams"></param>
        /// <returns></returns>
        internal static byte[] CompressAudioUsingStream(AudioChunk audio, IAudioCompressionStream compressor, out string encodeParams)
        {
            if (compressor == null)
            {
                encodeParams = "ERROR: NULL ENCODER";
                return(new byte[0]);
            }

            encodeParams = compressor.GetEncodeParams();
            byte[] body   = compressor.Compress(audio);
            byte[] footer = compressor.Close();
            if (footer == null)
            {
                footer = new byte[0];
            }

            byte[] returnVal = new byte[body.Length + footer.Length];
            Array.Copy(body, 0, returnVal, 0, body.Length);
            Array.Copy(footer, 0, returnVal, body.Length, footer.Length);
            return(returnVal);
        }
Пример #8
0
            public int Read(float[] buffer, int offset, int count)
            {
                if (_nextChunk == null)
                {
                    _streamLock.WaitOne();
                    if (_inputChunks.Count != 0)
                    {
                        _nextChunk = _inputChunks.Dequeue();
                        _streamLock.ReleaseMutex();
                    }
                    else
                    {
                        // Serious buffer underrun. In this case, just return silence instead of stuttering
                        _nextChunk = null;
                        for (int c = 0; c < count; c++)
                        {
                            buffer[c + offset] = 0.0f;
                        }

                        _streamLock.ReleaseMutex();
                        return(count);
                    }
                }

                int samplesWritten = 0;

                short[] returnVal = new short[count];

                while (samplesWritten < count && _nextChunk != null)
                {
                    int remainingInThisChunk = _nextChunk.DataLength - _inCursor;
                    int remainingToWrite     = (count - samplesWritten);
                    int chunkSize            = Math.Min(remainingInThisChunk, remainingToWrite);
                    Array.Copy(_nextChunk.Data, _inCursor, returnVal, samplesWritten, chunkSize);
                    _inCursor      += chunkSize;
                    samplesWritten += chunkSize;

                    if (_inCursor >= _nextChunk.DataLength)
                    {
                        _inCursor = 0;

                        _streamLock.WaitOne();
                        if (_inputChunks.Count != 0)
                        {
                            _nextChunk = _inputChunks.Dequeue();
                            _streamLock.ReleaseMutex();
                        }
                        else
                        {
                            _nextChunk = null;
                            for (int c = 0; c < count; c++)
                            {
                                buffer[c + offset] = 0.0f;
                            }

                            _streamLock.ReleaseMutex();
                            return(count);
                        }
                    }
                }

                for (int c = 0; c < samplesWritten; c++)
                {
                    buffer[c + offset] = ((float)returnVal[c]) / ((float)short.MaxValue);
                }

                return(samplesWritten);
            }