将32位浮点音频转换为16位

Posted zhan_zjb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将32位浮点音频转换为16位相关的知识,希望对你有一定的参考价值。

(注:只改变量化位数,并不改变采样率和声道数等信息) 

弄了一个下午加一个早上,终于算是弄完了,效果非常不错,音质无损失,之前一直用ffmpeg做重采样处理,但是一直是各种艰辛,各种奔溃,很无语,最后想了一下,从源头开始,自己想办法吧数据转换一下,搜了一下雷神的,他写了PCM从16位转到8位的,没有32位到16位的,所以只能自己摸索了,总结一下,核心代码:

注释的地方是探索的过程,实际不需要
  int pcm32_to_pcm16(const char *filename)   FILE *fp =  fopen(filename, "rb"); FILE *fp1 = fopen("output_16.pcm", "wb"); unsigned char *sample = (unsigned char*)calloc(1, 4+1); while(!feof(fp)) fread(sample, 4, 1, fp); sample[4] = '\\0'; float *sample32 = (float*)sample; short sample16 = (short)floor( (*sample32) * 32767 ); fwrite(&sample16, 2, 1, fp1); //               short sample16 = (short)((*sample32) >> 16); //               fwrite(&sample16, 2, 1, fp1);
 
// int nVar32 = *sample32; // short nLow = LOWORD(nVar32); // short nHigh = HIWORD(nVar32); // fwrite(&nLow,  2, 1, fp1); // fwrite(&nHigh, 2, 1, fp2); free(sample); fclose(fp); fclose(fp1); return 0;  

 

将 32 位浮点数转换为 16 位 PCM 范围

【中文标题】将 32 位浮点数转换为 16 位 PCM 范围【英文标题】:Convert 32-bit Floating Points to 16-bit PCM range 【发布时间】:2017-05-09 22:49:13 【问题描述】:

我有一些由 javascript HTML5 网络音频 api 生成的数据。它生成Float32Array,一个 32 位浮点数组,介于 -1 和 1 之间。我使用 websocket 将数据流式传输到我的服务器。

我需要将 32 位浮点数转换为介于 -32768 和 +32767(16 位有符号整数)之间的 16 位 PCM 范围。这样就可以将数据用作 wav 文件。

我在转换时遇到问题。我怀疑答案是使用 struct 模块,但我无法获得正确的格式。

【问题讨论】:

struct 模块不能直接在这些类型之间进行转换。它只能将 32 位浮点值解包为 Python 浮点数,并将 Python int 打包为 16 位整数。它也不会进行您需要的范围转换。 【参考方案1】:

这是一个 Python 2.7 示例程序,它读取包含原始 32 位浮点音频样本的文件并创建一个 WAV 文件,其中包含这些样本转换后的 16 位有符号整数样本:

import sys
import array
import struct
import wave

def convert(fin, fout, chunk_size = 1024 * 1024):
    chunk_size *= 4    # convert from samples to bytes

    waveout = wave.open(fout, "wb")
    waveout.setparams((1, 2, 44100, 0, "NONE", ""))

    while True:
        raw_floats = fin.read(chunk_size)
        if raw_floats == "":
            return
        floats = array.array('f', raw_floats)
        samples = [sample * 32767
                   for sample in floats]
        raw_ints = struct.pack("<%dh" % len(samples), *samples)
        waveout.writeframes(raw_ints)

convert(open(sys.argv[1], "rb"), open(sys.argv[2], "wb"))

代码使用array.array 将32 位浮点样本转换为Python 浮点数,因为它应该比struct.unpack 快一点。它还使用本机机器字节顺序,就像Float32Array 一样。无法使用array.array 创建 16 位整数样本,因为无论本机机器顺序如何,它们都需要使用小端字节序。范围转换由简单的 Python 代码处理。

【讨论】:

感谢您的帮助。我已将代码简化为:gist.github.com/richtier/6b05b2bb3ceff20f3d9557227b8789c6,但是当我使用此处定义的字节时:pastebin.com/raw/yCQ8Bg5w 我得到错误struct.error: required argument is not an integer 此时samples 看起来像例如[505.00430237688124, 487.5382216461003, 471.0005183443427, 440.09429602883756],这是有道理的因为samples 仍然是一个浮动列表 @rikAtee 你用的是什么版本的 Python? 3.5.2 在单独的注释中添加以下内容时,我认为它开始表现自己:samples = [int(sample * 32767) for sample in floats] 是的,我使用的是 2.7,似乎没有那么挑剔。使用int(sample * 32767) 应该可以解决问题。

以上是关于将32位浮点音频转换为16位的主要内容,如果未能解决你的问题,请参考以下文章

在 C/C+ 中从 16 位线性 PCM 音频转换为 32 位浮点的最佳方法?

将 32 位浮点数转换为 16 位 PCM 范围

32 位到 16 位浮点转换

将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数

在 Javascript 中将 32 位 WAV 转换为 16 位 WAV

Jack 中的“32 位浮点单声道音频”