8

我正在尝试使用 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;

        }
4

1 回答 1

0

我认为您的问题可能是您每次想要对音频进行编码时都在更新一个新的 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;

        ...
于 2013-03-06T21:03:20.973 回答