Windows Phone编码和解码音频使用NSpeex.解码有问题

本文关键字:解码 NSpeex 有问题 音频 编码 Windows Phone | 更新日期: 2023-09-27 17:54:31

我正在尝试使用Nspeex编码录制的音频,然后通过互联网传输并在另一端解码。我使用的是Windows Phone 7/8。为了编码和解码,我使用以下代码。但是在解码时,我没有得到正确的结果,我可以再次播放。谁能给我提供编码和解码代码,运行在WP7/8录制音频:

private static Microphone mic = Microphone.Default;
        private static byte[] EncodeSpeech(byte[] buf, int len)
        {
            BandMode mode = GetBandMode(mic.SampleRate);
            SpeexEncoder encoder = new SpeexEncoder(mode);
            // set encoding quality to lowest (which will generate the smallest size in the fastest time)
            encoder.Quality = 1;
            int inDataSize = len / 2;
            // convert to short array
            short[] data = new short[inDataSize];
            int sampleIndex = 0;
            for (int index = 0; index < len; index += 2, sampleIndex++)
            {
                data[sampleIndex] = BitConverter.ToInt16(buf, index);
            }
            // note: the number of samples per frame must be a multiple of encoder.FrameSize
            inDataSize = inDataSize - inDataSize % encoder.FrameSize;
            var encodedData = new byte[len];
            int encodedBytes = encoder.Encode(data, 0, inDataSize, encodedData, 0, len);
            if (encodedBytes != 0)
            {
                // each chunk is laid out as follows:
                // | 4-byte total chunk size | 4-byte encoded buffer size | <encoded-bytes> |
                byte[] inDataSizeBuf = BitConverter.GetBytes(inDataSize);
                byte[] sizeBuf = BitConverter.GetBytes(encodedBytes + inDataSizeBuf.Length);
                byte[] returnBuf = new byte[encodedBytes + sizeBuf.Length + inDataSizeBuf.Length];
                sizeBuf.CopyTo(returnBuf, 0);
                inDataSizeBuf.CopyTo(returnBuf, sizeBuf.Length);
                Array.Copy(encodedData, 0, returnBuf, sizeBuf.Length + inDataSizeBuf.Length, encodedBytes);
                return returnBuf;
            }
            else
                return buf;
        }

        private byte[] DecodeSpeech(byte[] buf)
        {
            BandMode mode = GetBandMode(mic.SampleRate);
            SpeexDecoder decoder = new SpeexDecoder(mode);
            byte[] inDataSizeBuf = new byte[4];
            byte[] sizeBuf = new byte[4];
            byte[] encodedBuf = new byte[buf.Length - 8];
            Array.Copy(buf, 0, sizeBuf, 0, 4);
            Array.Copy(buf, 4, inDataSizeBuf, 0, 4);
            Array.Copy(buf, 8, encodedBuf, 0, buf.Length - 8);
            int inDataSize = BitConverter.ToInt32(inDataSizeBuf, 0);
            int size = BitConverter.ToInt32(sizeBuf, 0);
            short[] decodedBuf = new short[inDataSize];
            int decodedSize = decoder.Decode(encodedBuf, 0, encodedBuf.Length, decodedBuf, 0, false);
            byte[] returnBuf = new byte[inDataSize * 2];
            for (int index = 0; index < decodedBuf.Length; index++)
            {
                byte[] temp = BitConverter.GetBytes(decodedBuf[index]);
                Array.Copy(temp, 0, returnBuf, index * 2, 2);
            }
            return returnBuf;
        }

        private static BandMode GetBandMode(int sampleRate)
        {
            if (sampleRate <= 8000)
                return BandMode.Narrow;
            if (sampleRate <= 16000)
                return BandMode.Wide;
            return BandMode.UltraWide;
        }

Windows Phone编码和解码音频使用NSpeex.解码有问题

我认为你的问题可能是你每次想要编码音频时都要更新一个新的SpeexEncoder。你应该试着让它成为你的类的成员,然后重用它。

我查看了Nspeex的代码,我注意到SpeexEncoder使用NbEncoder作为窄带。在那个类中,看起来它保留了一些以前音频数据的历史记录,以便执行编码。这应该意味着不同编码器实例的输出不会在一起。

private static Microphone mic = Microphone.Default;
private static SpeexEncoder encoder = CreateEncoder();
    private static SpeexEncoder CreateEncoder()
    {
        BandMode mode = GetBandMode(mic.SampleRate);
        SpeexEncoder encoder = new SpeexEncoder(mode);
        // set encoding quality to lowest (which will generate the smallest size in the fastest time)
        encoder.Quality = 1;
        return encoder;
    }
    private static byte[] EncodeSpeech(byte[] buf, int len)
    {
        int inDataSize = len / 2;
        ...