将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 位 uint 数,然后再次转换回该 32 位浮点数