我有一个csv
文件,它只是一个以逗号分隔的简单数字列表。我想将此csv
文件转换为二进制文件(只是一个字节序列,每个解释的数字都是csv
文件中的数字。)
我这样做的原因是能够从值的电子表格导入音频数据。在我的导入(我使用的是audacity)中,我有几种格式可供选择,用于二进制文件:
Encoding:
Signed 8, 24, 16, or 32 bit PCM
Unsigned 8 bit PCM
32 bit or 64 bit float
U-Law
A-Law
GSM 6.10
12, 16, or 24 bit DWVW
VOX ADPCM
Byte Order:
No endianness
Big endian
Little endian
我正沿着big endian 32-bit float
的路线前进,以保持简单。我想让事情变得尽可能简单,所以我认为bash
将是最佳工具。
答案 0 :(得分:3)
我有一个
csv
文件,它只是一个以逗号分隔的简单数字列表。我想将此csv
文件转换为二进制文件[...]我正沿着
big endian 32-bit float
的路线前进,以保持简单。
不确定如何在纯bash
中执行此操作(实际上怀疑它是可行的,因为float as binary是非标准转换)。
但是这里有一个简单的Perl单线:
$ cat example1.csv
1.0
2.1
3.2
4.3
$ cat example1.csv | perl -ne 'print pack("f>*", split(/\s*,\s*/))' > example1.bin
$ hexdump -C < example1.bin
00000000 3f 80 00 00 40 06 66 66 40 4c cc cd 40 89 99 9a |?...@.ff@L..@...|
00000010
它使用Perl的pack function和f
将浮点数转换为二进制数,使用<
将它们转换为BE。 (如果每行CSV行有多个数字,我也添加了拆分。)
P.S。将原子转换为16位短路的命令:
perl -ne 'print pack("s*", split(/\s*,\s*/))'
对BE使用"s>*"
,对LE使用"s<*"
,而不是"s*"
。
P.P.S。如果是音频数据,您还可以查看sox
工具。多年来没有使用它,但IIRC它可以将任何类似PCM的任何格式转换为任何格式,同时也可以应用效果。
答案 1 :(得分:2)
我会推荐Python超过bash
。 对于这个特定的任务,它更简单/更健全的IMO。
#!/usr/bin/env python
import array
with open('input.csv', 'rt') as f:
text = f.read()
entries = text.split(',')
values = [int(x) for x in entries]
# do a scalar here: if your input goes from [-100, 100] then
# you may need to translate/scale into [0, 2^16-1] for
# 16-bit PCM
# e.g.:
# values = [(val * scale) for val in values]
with open('output.pcm', 'wb') as out:
pcm_vals = array.array('h', values) # 16-bit signed
pcm_vals.tofile(out)
您也可以使用Python's wave
module而不是仅编写原始PCM。
以上是上述示例的工作原理:
$ echo 1,2,3,4,5,6,7 > input.csv
$ ./so_pcm.py
$ xxd output.pcm
0000000: 0100 0200 0300 0400 0500 0600 0700 ..............
xxd
显示二进制值。它使用了我机器的本机字节序(小)。