【问题标题】:Float to 16bit, Stereo. Improve?浮动到 16 位,立体声。提升?
【发布时间】:2013-08-15 12:17:05
【问题描述】:

所以我将浮点 32 位转换为立体声中的 16 位。由于我自己并不完全理解,遗憾的是它几乎是复制粘贴。

但我想知道它是否可以在质量或速度方面进行改进? 并不是说它们中的任何一个都是可怕的或什么的。

    void SendWaloop(object sender, NAudio.Wave.WaveInEventArgs e)
    {

        byte[] newArray16Bit = new byte[e.BytesRecorded / 2];
        short two;
        float value;
        for (int i = 0, j = 0; i < e.BytesRecorded; i += 4, j += 2)
        {
            value = (BitConverter.ToSingle(e.Buffer, i));
            two = (short)(value * short.MaxValue);

            newArray16Bit[j] = (byte)(two & 0xFF);
            newArray16Bit[j + 1] = (byte)((two >> 8) & 0xFF);
        }
        if (connect == true && MuteMic.Checked == false)
        {
            udpSend.Send(newArray16Bit, newArray16Bit.Length, otherPartyIP.Address.ToString(), 1500);
        }

    }

很好,它将缓冲区从 32 位转换为 16 位,并使用 UDP 发送,没什么奇怪的。

虽然对我来说这看起来很复杂,但据我了解,它只是删除每 4 个字节或类似的东西。

编辑:

        unsafe
        {
            byte[] newArray16Bit = new byte[e.BytesRecorded / 2];
            fixed (byte* sourcePtr = e.Buffer)
            fixed (byte* targetPtr = newArray16Bit)
            {
                float* sourceTyped = (float*)sourcePtr;
                short* targetTyped = (short*)targetPtr;

                int count = e.BytesRecorded / 4;
                for (int i = 0; i < count; i++)
                {
                    targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
                }
            }

            if (connect == true && MuteMic.Checked == false)
            {
                udpSend.Send(newArray16Bit, newArray16Bit.Length, otherPartyIP.Address.ToString(), 1500);
            }
        }
    }

【问题讨论】:

  • 你应该在CodeReview问这个问题
  • 我猜是这样,但是当我上次问这样的问题时,他们说我不应该在那里问。如果没有人在这里回答,那么会问那里:)
  • 为什么用short而不是int16_t?由于您依赖它是 16 位,因此您应该确保它确实是...
  • 阅读their help,特别是“我很困惑!本网站的主题有哪些问题?”下的部分。我不去那里,所以我无法确定,但它看起来应该属于那里。如果某些东西适合其他地方,它不应该出现在Stack Overflow
  • @Dan 它是 C#,所以 short 保证是 16 位的。

标签: c#


【解决方案1】:

它需要测试,但我可能会尝试一些unsafe

fixed(byte* sourcePtr = e.Buffer)
fixed(byte* targetPtr = newArray16Bit)
{
    float* sourceTyped = (float*)sourcePtr;
    short* targetTyped = (short*)targetPtr;

    int count = e.BytesRecorded / 4;
    for(int i = 0 ; i < count ; i++)
    {
        targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
    }
}

为了显示相同的工作方式:

using System;
static class Program
{
    static void Main()
    {
        byte[] raw1 = new byte[64 * 1024];
        new Random(12345).NextBytes(raw1); // 64k of random data
        var raw2 = (byte[])raw1.Clone(); // just to rule out corruption
        var result1 = OriginalImplFromTopPost(raw1, raw1.Length - 20);
        var result2 = MyImpl(raw2, raw2.Length - 20);

        bool areSame = Convert.ToBase64String(result1) == Convert.ToBase64String(result2);
        Console.WriteLine(areSame); // True
    }

    public static unsafe byte[] MyImpl(byte[] source, int byteCount)
    {
        byte[] newArray16Bit = new byte[byteCount / 2];
        fixed (byte* sourcePtr = source)
        fixed (byte* targetPtr = newArray16Bit)
        {
            float* sourceTyped = (float*)sourcePtr;
            short* targetTyped = (short*)targetPtr;

            int count = byteCount / 4;
            for (int i = 0; i < count; i++)
            {
                targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
            }
        }
        return newArray16Bit;
    }

    public static byte[] OriginalImplFromTopPost(byte[] source, int byteCount)
    {
        byte[] newArray16Bit = new byte[byteCount / 2];
        short two;
        float value;
        for (int i = 0, j = 0; i < byteCount; i += 4, j += 2)
        {
            value = (BitConverter.ToSingle(source, i));
            two = (short)(value * short.MaxValue);

            newArray16Bit[j] = (byte)(two & 0xFF);
            newArray16Bit[j + 1] = (byte)((two >> 8) & 0xFF);
        }
        return newArray16Bit;
    }
}

【讨论】:

  • 不完全了解如何实现它,将在我的帖子中添加它以展示我是如何尝试的。
  • @user2587718 请注意,在 ral 代码中,您只想查看 e.BytesRecorded 的数据量 - e.Buffer 可能过大。唯一改变的是截止。事实上,我会编辑..它会比解释更容易......
  • 好的,现在可以了!如果我做错了什么,请最后一次在我的帖子中检查它,否则,这就是答案:) 而且,我是否需要担心“不安全”?
  • @user2587718 不,你不必担心unsafe 只要你得到正确的代码,我会这样做;p
  • 太棒了,所以最后我做对了,在很多帮助下,非常感谢:) 我想这有点加快了,因为根据我的理解,带有指针和东西的不安全代码更快如果做得对。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 2010-12-12
相关资源
最近更新 更多