Example #1
0
        public int Encode(byte[] inputBuffer, int inputBufferOffset, int dataLength, byte[] outputBuffer,
                          int outputBufferOffset, int quality)
        {
            var compressedSize   = 0;
            var speexBits        = new Speex.SpeexBits();
            var compressedBits   = new byte[MAX_FRAME_SIZE];
            var unmanagedStorage = IntPtr.Zero;

            try
            {
                var encoderState = IntPtr.Zero;
                unmanagedStorage = Marshal.AllocHGlobal(4);
                try
                {
                    var mode = Speex.speex_lib_get_mode(Speex.SPEEX_MODEID_NB);

                    var       header = new Speex.SpeexHeader();
                    const int rate   = 8000;
                    Speex.speex_init_header(ref header, rate, 1, mode);
                    header.frames_per_packet = 1;
                    header.vbr         = 0;
                    header.nb_channels = 1;

                    encoderState = Speex.speex_encoder_init(mode);

                    Speex.speex_encoder_ctl(encoderState, Speex.SPEEX_GET_FRAME_SIZE, unmanagedStorage);
                    var frameSize = Marshal.ReadInt32(unmanagedStorage);

                    const int complexity = 10;
                    Marshal.WriteInt32(unmanagedStorage, complexity);
                    Speex.speex_encoder_ctl(encoderState, Speex.SPEEX_SET_COMPLEXITY, unmanagedStorage);

                    Marshal.WriteInt32(unmanagedStorage, rate);
                    Speex.speex_encoder_ctl(encoderState, Speex.SPEEX_SET_SAMPLING_RATE, unmanagedStorage);

                    Marshal.WriteInt32(unmanagedStorage, quality);
                    Speex.speex_encoder_ctl(encoderState, Speex.SPEEX_SET_QUALITY, unmanagedStorage);

                    const int lookahead = 0;
                    Marshal.WriteInt32(unmanagedStorage, lookahead);
                    Speex.speex_encoder_ctl(encoderState, Speex.SPEEX_GET_LOOKAHEAD, unmanagedStorage);

                    Speex.speex_bits_init(ref speexBits);

                    var input = new byte[MAX_FRAME_SIZE];
                    using (var inStream = new MemoryStream(inputBuffer, inputBufferOffset, dataLength))
                        using (
                            var outStream = new MemoryStream(outputBuffer, outputBufferOffset,
                                                             outputBuffer.Length - outputBufferOffset))
                        {
                            while (true)
                            {
                                var pcmBytesToRead = 16 / 8 * header.nb_channels * frameSize;
                                var numBytesRead   = inStream.Read(input, 0, pcmBytesToRead);
                                if (numBytesRead == 0)
                                {
                                    break;
                                }
                                var numSamplesToBlank = (pcmBytesToRead - numBytesRead) / (16 / 8 * header.nb_channels);
                                var numSamplesRead    = numBytesRead / (16 / 8 * header.nb_channels);

                                for (var i = numSamplesRead; i < numSamplesRead + numSamplesToBlank; i++)
                                {
                                    input[(i * 2)]     = 0;
                                    input[(i * 2) + 1] = 0;
                                }
                                var thisFrameBytesAsShort = new short[input.Length / 2];
                                for (var i = 0; i < thisFrameBytesAsShort.Length; i++)
                                {
                                    thisFrameBytesAsShort[i] = BitConverter.ToInt16(input, (i * 2));
                                }
                                Speex.speex_encode_int(encoderState, thisFrameBytesAsShort, ref speexBits);
                                Speex.speex_bits_insert_terminator(ref speexBits);

                                var numBytesEncodedThisFrame =
                                    (byte)Speex.speex_bits_write(ref speexBits, compressedBits, MAX_FRAME_SIZE);
                                Speex.speex_bits_reset(ref speexBits);

                                outStream.WriteByte(numBytesEncodedThisFrame);
                                compressedSize += 1;

                                outStream.Write(compressedBits, 0, numBytesEncodedThisFrame);
                                compressedSize += numBytesEncodedThisFrame;
                            }
                        }
                }
                finally
                {
                    Speex.speex_encoder_destroy(encoderState);
                    Speex.speex_bits_destroy(ref speexBits);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(unmanagedStorage);
            }
            return(compressedSize);
        }
Example #2
0
        public int Decode(byte[] inputBuffer, int inputBufferOffset, int dataLength, ref byte[] outputBuffer,
                          int outputBufferOffset)
        {
            var speexBits    = new Speex.SpeexBits();
            var decoderState = IntPtr.Zero;

            var bytesWritten = 0;

            var compressedBits   = new byte[200];
            var decompressedBits = new short[MAX_FRAME_SIZE];

            var unmanagedStoragePointer  = IntPtr.Zero;
            var compressedBitsGCHandle   = new GCHandle();
            var decompressedBitsGCHandle = new GCHandle();

            try
            {
                unmanagedStoragePointer  = Marshal.AllocHGlobal(4);
                compressedBitsGCHandle   = GCHandle.Alloc(compressedBits, GCHandleType.Pinned);
                decompressedBitsGCHandle = GCHandle.Alloc(decompressedBits, GCHandleType.Pinned);

                try
                {
                    Speex.speex_bits_init(ref speexBits);
                    var mode = Speex.speex_lib_get_mode(Speex.SPEEX_MODEID_NB);
                    decoderState = Speex.speex_decoder_init(mode);
                    Marshal.WriteInt32(unmanagedStoragePointer, 0);
                    Speex.speex_decoder_ctl(decoderState, Speex.SPEEX_SET_ENH, unmanagedStoragePointer);

                    Speex.speex_decoder_ctl(decoderState, Speex.SPEEX_GET_FRAME_SIZE, unmanagedStoragePointer);
                    var frameSize = Marshal.ReadInt32(unmanagedStoragePointer);

                    const int rate = 8000;
                    Marshal.WriteInt32(unmanagedStoragePointer, rate);
                    Speex.speex_decoder_ctl(decoderState, Speex.SPEEX_SET_SAMPLING_RATE, unmanagedStoragePointer);

                    Speex.speex_decoder_ctl(decoderState, Speex.SPEEX_GET_LOOKAHEAD, unmanagedStoragePointer);
                    var lookahead = Marshal.ReadInt32(unmanagedStoragePointer);

                    using (var inStream = new MemoryStream(inputBuffer, inputBufferOffset, dataLength))
                        using (
                            var outstream = new MemoryStream(outputBuffer, outputBufferOffset,
                                                             outputBuffer.Length - outputBufferOffset))
                        {
                            while (true)
                            {
                                var numBytesThisFrame = inStream.ReadByte();
                                if (numBytesThisFrame < 1)
                                {
                                    break;
                                }
                                var bytesRead = inStream.Read(compressedBits, 0, numBytesThisFrame);
                                if (bytesRead < numBytesThisFrame)
                                {
                                    throw new IOException("Unexpected end of stream encountered.");
                                }
                                Speex.speex_bits_read_from(ref speexBits, compressedBits, numBytesThisFrame);

                                var returnVal     = Speex.speex_decode_int(decoderState, ref speexBits, decompressedBits);
                                var bitsRemaining = Speex.speex_bits_remaining(ref speexBits);
                                if (returnVal == -1)
                                {
                                    break;
                                }
                                if (returnVal == -2)
                                {
                                    throw new IOException("Decoding error: corrupted stream?\n");
                                }
                                else if (bitsRemaining < 0)
                                {
                                    throw new IOException("Decoding overflow: corrupted stream?\n");
                                }

                                for (var i = 0; i < frameSize; i++)
                                {
                                    if (outstream.Position > outstream.Length - 2)
                                    {
                                        break;
                                    }
                                    outstream.Write(BitConverter.GetBytes(decompressedBits[i]), 0, 2);
                                    bytesWritten += 2;
                                }
                            }
                            outstream.Flush();
                            outstream.Close();
                            inStream.Close();
                        }
                }
                finally
                {
                    Speex.speex_decoder_destroy(decoderState);
                    Speex.speex_bits_destroy(ref speexBits);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(unmanagedStoragePointer);
                compressedBitsGCHandle.Free();
                decompressedBitsGCHandle.Free();
                //modeGCHandle.Free();
            }
            return(bytesWritten);
        }