Silverlight Speex 快速播放

发布于 2024-12-10 02:24:53 字数 2730 浏览 0 评论 0原文

我使用 Speex 对原始数据进行编码,但在解码数据后,音频以更快的速度播放,因为它让你听起来像花栗鼠。我正在使用 NSpeex 和 Silverlight 4。

8kHz 采样

编码功能:

    JSpeexEnc encoder = new JSpeexEnc();
    int rawDataSize = 0;
    public byte[] EncodeAudio(byte[] rawData)
    {
        var encoder = new SpeexEncoder(BandMode.Narrow);
        var inDataSize = rawData.Length / 2;
        var inData = new short[inDataSize];

        for (var index = 0; index < rawData.Length; index += 2)
        {
            inData[index / 2] = BitConverter.ToInt16(rawData, index);
        }
        inDataSize = inDataSize - inDataSize % encoder.FrameSize;

        var encodedData = new byte[rawData.Length];
        var encodedBytes = encoder.Encode(inData, 0, inDataSize, encodedData, 0, encodedData.Length);

        byte[] encodedAudioData = null;
        if (encodedBytes != 0)
        {
            encodedAudioData = new byte[encodedBytes];
            Array.Copy(encodedData, 0, encodedAudioData, 0, encodedBytes);
        }
        rawDataSize = inDataSize; // Count of encoded shorts, for debugging
        return encodedAudioData;
    }

解码功能:

    SpeexDecoder decoder = new SpeexDecoder(BandMode.Narrow);
    public byte[] Decode(byte[] encodedData)
    {
        try
        {
            short[] decodedFrame = new short[8000]; // should be the same number of samples as on the capturing side
            int decoderBytes = decoder.Decode(encodedData, 0, encodedData.Length, decodedFrame, 0, false);

            byte[] decodedData = new byte[encodedData.Length];
            byte[] decodedAudioData = null;

            decodedAudioData = new byte[decoderBytes * 2];
            for (int shortIndex = 0, byteIndex = 0; byteIndex < decoderBytes; shortIndex++)
            {
                BitConverter.GetBytes(decodedFrame[shortIndex + byteIndex]).CopyTo(decodedAudioData, byteIndex * 2);
                byteIndex++;
            }

            // todo: do something with the decoded data
            return decodedAudioData;
        }
        catch (Exception ex)
        {
            ShowMessageBox(ex.Message.ToString());
            return null;
        }

    }

播放音频:

    void PlayWave(byte[] PCMBytes)
    {
        byte[] decodedBuffer = Decode(PCMBytes);
        MemoryStream ms_PCM = new MemoryStream(decodedBuffer);
        MemoryStream ms_Wave = new MemoryStream();

        _pcm.SavePcmToWav(ms_PCM, ms_Wave, 16, 8000, 1);

        WaveMediaStreamSource WaveStream = new WaveMediaStreamSource(ms_Wave);
        mediaElement1.SetSource(WaveStream);
        mediaElement1.Play();
    }

I'm using Speex to encode the raw data but after I decode the data the audio plays at a faster rate because it makes you sound like a chipmunk. I'm using NSpeex and Silverlight 4.

8kHz Sampling

Encoding Function:

    JSpeexEnc encoder = new JSpeexEnc();
    int rawDataSize = 0;
    public byte[] EncodeAudio(byte[] rawData)
    {
        var encoder = new SpeexEncoder(BandMode.Narrow);
        var inDataSize = rawData.Length / 2;
        var inData = new short[inDataSize];

        for (var index = 0; index < rawData.Length; index += 2)
        {
            inData[index / 2] = BitConverter.ToInt16(rawData, index);
        }
        inDataSize = inDataSize - inDataSize % encoder.FrameSize;

        var encodedData = new byte[rawData.Length];
        var encodedBytes = encoder.Encode(inData, 0, inDataSize, encodedData, 0, encodedData.Length);

        byte[] encodedAudioData = null;
        if (encodedBytes != 0)
        {
            encodedAudioData = new byte[encodedBytes];
            Array.Copy(encodedData, 0, encodedAudioData, 0, encodedBytes);
        }
        rawDataSize = inDataSize; // Count of encoded shorts, for debugging
        return encodedAudioData;
    }

Decoding Function:

    SpeexDecoder decoder = new SpeexDecoder(BandMode.Narrow);
    public byte[] Decode(byte[] encodedData)
    {
        try
        {
            short[] decodedFrame = new short[8000]; // should be the same number of samples as on the capturing side
            int decoderBytes = decoder.Decode(encodedData, 0, encodedData.Length, decodedFrame, 0, false);

            byte[] decodedData = new byte[encodedData.Length];
            byte[] decodedAudioData = null;

            decodedAudioData = new byte[decoderBytes * 2];
            for (int shortIndex = 0, byteIndex = 0; byteIndex < decoderBytes; shortIndex++)
            {
                BitConverter.GetBytes(decodedFrame[shortIndex + byteIndex]).CopyTo(decodedAudioData, byteIndex * 2);
                byteIndex++;
            }

            // todo: do something with the decoded data
            return decodedAudioData;
        }
        catch (Exception ex)
        {
            ShowMessageBox(ex.Message.ToString());
            return null;
        }

    }

Playing the audio:

    void PlayWave(byte[] PCMBytes)
    {
        byte[] decodedBuffer = Decode(PCMBytes);
        MemoryStream ms_PCM = new MemoryStream(decodedBuffer);
        MemoryStream ms_Wave = new MemoryStream();

        _pcm.SavePcmToWav(ms_PCM, ms_Wave, 16, 8000, 1);

        WaveMediaStreamSource WaveStream = new WaveMediaStreamSource(ms_Wave);
        mediaElement1.SetSource(WaveStream);
        mediaElement1.Play();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不必你懂 2024-12-17 02:24:53

抱歉大家回复晚了,但我知道问题出在哪里了。

在我的解码函数中,我循环遍历已解码的 short 数组,但我仅将一半字节复制到新的 byte 数组中。

它需要看起来像这样:

decodedAudioData = new byte[decoderBytes * 2];
for (int shortIndex = 0, byteIndex = 0; shortIndex < decodedFrame.Length; shortIndex++, byteIndex += 2)
{
    byte[] temp = BitConverter.GetBytes(decodedFrame[shortIndex]);
    decodedAudioData[byteIndex] = temp[0];
    decodedAudioData[byteIndex + 1] = temp[1];
}

Sorry guys for the late response but I figured out what the problem was.

Inside my decode function I loop through the decoded short array but I'm only copying half of the bytes into my new byte array.

It needs to look something like this:

decodedAudioData = new byte[decoderBytes * 2];
for (int shortIndex = 0, byteIndex = 0; shortIndex < decodedFrame.Length; shortIndex++, byteIndex += 2)
{
    byte[] temp = BitConverter.GetBytes(decodedFrame[shortIndex]);
    decodedAudioData[byteIndex] = temp[0];
    decodedAudioData[byteIndex + 1] = temp[1];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文