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

Posted

技术标签:

【中文标题】Windows Phone 使用 NSpeex 编码和解码音频。解码有问题?【英文标题】:Windows Phone Encoding and Decoding audio using NSpeex. Having issue with decoding? 【发布时间】:2013-01-18 19:17:34 【问题描述】:

我正在尝试使用 Nspeex 对录制的音频进行编码,然后通过 Internet 将其传输并在另一端进行解码。我在 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;

        

【问题讨论】:

【参考方案1】:

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

        ...

【讨论】:

以上是关于Windows Phone 使用 NSpeex 编码和解码音频。解码有问题?的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用啥库在 C# 中处理 VoIP 流?

Microsoft.Phone.Maps.Services 可以在 Windows 应用商店应用中使用吗?

windows phone 8 和 10 的 windows phone 应用程序开发

使用windows phone读取txt文件

如何使用 PushSharp 为 Windows Phone 8 设置徽章值

Windows Phone 8 上的 Azure 表存储使用啥库?