c# - 从 base64 解码后的嘈杂音频剪辑

标签 c# audio unity3d base64

我用 base64 编码了 wav 文件(资源/声音中的 audioClipName.txt)。

HERE IS THE SOURCE WAVE FILE

然后我尝试解码它,从中制作一个 AudioClip 并像这样播放它:

public static void CreateAudioClip()
{
    string s = Resources.Load<TextAsset> ("Sounds/audioClipName").text;

    byte[] bytes = System.Convert.FromBase64String (s);
    float[] f = ConvertByteToFloat(bytes);

    AudioClip audioClip = AudioClip.Create("testSound", f.Length, 2, 44100, false, false);
    audioClip.SetData(f, 0);

    AudioSource as = GameObject.FindObjectOfType<AudioSource> ();
    as.PlayOneShot (audioClip);
}

private static float[] ConvertByteToFloat(byte[] array) 
{
    float[] floatArr = new float[array.Length / 4];

    for (int i = 0; i < floatArr.Length; i++) 
    {
        if (BitConverter.IsLittleEndian) 
            Array.Reverse(array, i * 4, 4);

        floatArr[i] = BitConverter.ToSingle(array, i * 4);
    }

    return floatArr;
}

一切正常,除了声音只是一种噪音。

我找到了 this这里是堆栈溢出,但答案并没有解决问题。

以下是有关 Unity3D 的 wav 文件的详细信息:

enter image description here

有谁知道这里的问题是什么?

编辑

我写下了二进制文件,一个是从 base64 解码后的,第二个是最终转换后的,并将其与原始二进制 wav 文件进行比较:

enter image description here

如您所见,文件已正确编码,因为只需对其进行解码并像这样写下文件:

string scat = Resources.Load<TextAsset> ("Sounds/test").text;

byte[] bcat = System.Convert.FromBase64String (scat);
System.IO.File.WriteAllBytes ("Assets/just_decoded.wav", bcat);

给了同样的文件。所有文件都有一定的长度。

但是最后一个是错误的,所以问题出在转换为 float 组的某个地方。但我不明白哪里出了问题。

编辑:

下面是写下final.wav的代码:

string scat = Resources.Load<TextAsset> ("Sounds/test").text;

byte[] bcat = System.Convert.FromBase64String (scat);
float[] f = ConvertByteToFloat(bcat);

byte[] byteArray = new byte[f.Length * 4];
Buffer.BlockCopy(f, 0, byteArray, 0, byteArray.Length);

System.IO.File.WriteAllBytes ("Assets/final.wav", byteArray);

最佳答案

您尝试播放的 wave 文件 (meow.wav) 具有以下属性:

  • PCM
  • 2 个 channel
  • 44100 赫兹
  • 带符号的 16 位小端

您的主要错误是,您正在解释二进制数据好像它已经代表了一个 float 。这就是 BitConverter.ToSingle() 的作用。

但您需要做的是,从每两个字节创建一个带符号的 16 位小端值(如 Wavefile header 中指定的),cast 将其转换为 float ,然后将其归一化。对于您的文件(16 位!),每个两个 字节构成一个样本,而不是四个 个字节。数据是小字节序 (s16le),因此如果主机不是,您只需交换它。

这将是更正后的转换函数:

private static float[] ConvertByteToFloat(byte[] array) {
    float[] floatArr = new float[array.Length / 2];

    for (int i = 0; i < floatArr.Length; i++) {
        floatArr[i] = ((float) BitConverter.ToInt16(array, i * 2))/32768.0;
    }

    return floatArr;
}

并且您应该跳过波形文件的标题(真正的音频数据从偏移量 44 开始)。

对于干净的解决方案,您必须正确解释 Wave-header 并根据那里指定的内容调整您的操作(或者如果它包含不受支持的参数则退出)。 例如,必须注意样本格式(每个样本的位数和字节序)、采样率和 channel 数。

关于c# - 从 base64 解码后的嘈杂音频剪辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35228767/

相关文章:

C# 检查按键是否有延迟(控制台应用程序)

c# - WAV 文件修剪和添加静音

android - unity 中的 fatal error checkdisalowAllocation

C# - 相同的存储库,还是拆分?

c# - 使用 BindingList 时 json.net 中的反序列化问题

c# - 使用 foreach 从 List 中过滤对象

iphone - iOS 上 Safari 中的 HTML 5/QuickTime 音频缓存

c# - 如何用 C# 和 NAudio 覆盖两个 wav 文件?

c# - 如何快速检查网格点之间是否存在任何路径?

c# - 角度边界问题