在 gnuplot 中绘制音频数据

发布于 2024-11-04 04:16:05 字数 238 浏览 1 评论 0原文

如何使用 gnuplot 将音频文件(例如 aiff)转换为 svg?我使用 sox(声音交换)将 .aiff 转换为 .dat,现在可以在 gnuplot 中加载它。

我做了类似的事情:

set terminal svg
set output "test.svg"
plot "test.dat"

我得到一个 svg 文件,但只有点/或很多 x。 我怎样才能把这些点连起来呢?

how could I convert an audio file such as a aiff into a svg using gnuplot? I used sox (sound exchange) to convert an .aiff into a .dat, which I can load now in gnuplot.

I did something similar to:

set terminal svg
set output "test.svg"
plot "test.dat"

I get a svg file, but only with dots / or a lot of x.
How could I connect the dots?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

聊慰 2024-11-11 04:16:05

要在点之间绘制线条,请使用

plot "test.dat" with lines

或要保留点标记以及线条,请使用

plot "test.dat" with linespoints

因此您的示例变为

set terminal svg    
set output "test.svg"
plot "test.dat" with lines

进一步提示:

不要考虑每个示例:

对于大文件,您也可能会发现它对于仅用“every n”绘制每 n 个样本很有用。这将使绘图的生成速度更快,并且还会生成更小(但不太详细)的 svg 文件。

例如

plot "test.dat" every 100 with lines

忽略 .dat 文件头:

如果您的 sox 生成的 .dat 文件有一些介绍性元数据行,例如

; Sample Rate 44100
; Channels 2

您可以添加以下内容以使 gnuplot 考虑这些行注释并忽略它们。

set datafile commentschars ";"

这将使您不必预处理 .dat 文件,以便在 gnuplot 阻塞之前删除这些行。

绘制立体声音频的左声道和右声道:

如果您正在处理立体声文件,您可能希望看到两个声道。

我们可以使用“multiplot”在共享 x 轴上将以下两个图(左通道和右通道)布置在另一个图的上方,就像许多声音编辑程序所做的那样。

set multiplot layout 2,1
plot "test.dat" using 1:2 with lines
plot ""         using 1:3 with lines

1:2 和 1:3 指示 gnuplot 将 dat 文件的哪些列用作 x 和 y 源。我假设你的 sox 生成的立体声 .dat 文件看起来和我的一样,其中列为
- 1:自第一个样本开始以来的时间
- 2:左通道归一化样本值
- 3:右通道归一化样本值

示例片段:

   10.840113       0.20101929      0.17840576 
   10.840136       0.26062012      0.14831543 
   10.840159       0.23779297      0.13146973 

将其放在一起:
这是一个将以上所有内容组合在一起的脚本。如果您没有立体数据文件来尝试此操作,则需要删除 1:3 的绘图和多重绘图设置。

#!/usr/bin/env gnuplot
set datafile commentschars ";"

set terminal svg
set output "test.svg"

set multiplot layout 2,1
plot "test.dat" using 1:2 every 100 with lines
plot ""         using 1:3 every 100 with lines
unset multiplot

美化

最后,我调整了演示脚本(大量借鉴了 Philipp K. Janert 所著的优秀的“gnuplot in action”书籍):

#!/usr/bin/env gnuplot
set datafile commentschars ";"

set terminal svg
set output "test.svg"

set multiplot layout 2,1

set ylabel "sample value"
set bmargin 0
set format x ""
set ytics -0.8,0.2
set key bottom
plot "test.dat" using 1:2 every 100 with lines lc rgbcolor "#a0a0b0" title "left channel"

set xlabel "time (s)"
set bmargin
set tmargin 0
set format x "%g"
set ytics -1.0,0.2,0.8
set key top

plot ""         using 1:3 every 100 with lines lc rgbcolor "#a0a0b0" title "right channel"
unset multiplot

这是一个示例输出(尽管是 png):
gnuplotted 音频数据(立体声示例)

如何制作 .dat 文件

对于关注以下网址的任何人在 home 中,您可以使用 sox 通过以下命令从音频文件生成 .dat 文件:

sox input.wav output.dat

大文件警告:即使在 40kHz 下转换 10 秒的立体声音频也会产生 25Mb 的输出文件。

To draw lines between the points, use

plot "test.dat" with lines

Or to keep the point markers as well as the lines, use

plot "test.dat" with linespoints

So your example becomes

set terminal svg    
set output "test.svg"
plot "test.dat" with lines

Further tips:

Don't consider every sample:

With large files you may also find it useful to plot only every nth sample with "every n". This will make the plot much faster to generate and will also yield a smaller (but less detailed) svg file.

e.g.

plot "test.dat" every 100 with lines

Ignore .dat file header:

If your sox-produced .dat file has some lines of introductory metadata, such as

; Sample Rate 44100
; Channels 2

you can add the following to have gnuplot consider those lines comments and ignore them.

set datafile commentschars ";"

This will save you having to pre-process your .dat file in order to remove those lines before gnuplot chokes on them.

Plot both left and right channels of stereo audio:

If you're working with a stereo file, you probably want to see both channels.

We can use "multiplot" to lay out the following two plots (of left then right channel) one above the other on a shared x-axis, as many sound-editing programs do.

set multiplot layout 2,1
plot "test.dat" using 1:2 with lines
plot ""         using 1:3 with lines

The 1:2 and 1:3 instruct gnuplot which columns of the dat file to use as x and y sources. I'm assuming your stereo .dat file produced by sox looks as mine does, with columns for
- 1: time since beginning of first sample
- 2: normalized sample value of left channel
- 3: normalized sample value of right channel

example snippet:

   10.840113       0.20101929      0.17840576 
   10.840136       0.26062012      0.14831543 
   10.840159       0.23779297      0.13146973 

Putting it together:
Here's a script which puts all of the above together. If you don't have a stereo data file to try this with, you'll want to remove the plot of 1:3 and the multiplot setting.

#!/usr/bin/env gnuplot
set datafile commentschars ";"

set terminal svg
set output "test.svg"

set multiplot layout 2,1
plot "test.dat" using 1:2 every 100 with lines
plot ""         using 1:3 every 100 with lines
unset multiplot

Prettification

Finally, I've tweaked the script for presentation (borrowing heavily from the excellent "gnuplot in action" book by Philipp K. Janert):

#!/usr/bin/env gnuplot
set datafile commentschars ";"

set terminal svg
set output "test.svg"

set multiplot layout 2,1

set ylabel "sample value"
set bmargin 0
set format x ""
set ytics -0.8,0.2
set key bottom
plot "test.dat" using 1:2 every 100 with lines lc rgbcolor "#a0a0b0" title "left channel"

set xlabel "time (s)"
set bmargin
set tmargin 0
set format x "%g"
set ytics -1.0,0.2,0.8
set key top

plot ""         using 1:3 every 100 with lines lc rgbcolor "#a0a0b0" title "right channel"
unset multiplot

Here's an example output (albeit png):
gnuplotted audio data (stereo example)

How to make a .dat file

For anyone following along at home, you can use sox to generate a .dat file from an audio file with the following command:

sox input.wav output.dat

Big file warning: Converting even just 10 seconds of stereo audio at 40kHz will produce a 25Mb output file.

贱人配狗天长地久 2024-11-11 04:16:05

请注意,您还可以直接绘制二进制数据:

set terminal svg
set output "test.svg"
plot '< sox test.aiff -t s32 -' binary format='%int32' using 0:1 with lines

Note that you can also plot the binary data directly:

set terminal svg
set output "test.svg"
plot '< sox test.aiff -t s32 -' binary format='%int32' using 0:1 with lines
苏璃陌 2024-11-11 04:16:05

只是想记录一下这一点 - 好吧,我一直在寻找一个 Linux 命令行音频波形查看器,它可以从命令行调用,以原始二进制文件作为输入,并且数据的格式可以是在命令行上指定。

Audacity 可以导入原始数据,但只能从 GUI 导入(无法通过其命令行选项指定原始数据文件格式);而 Wave 查看器如 gwavegtkwaveGaw - Gtk 模拟波形查看器 可以读取正确的 .wav 或基于 SPICE 的格式。

感谢 @Thor 的回答,现在我知道我可以使用 gnuplot 来达到目的。下面是一个示例命令行,它将原始二进制数据解释为 16 位立体声:

gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1 ; unset multiplot"

... 或分成几行:

gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1; \
unset multiplot"

注意:

  • 您应该只使用管道 "< ..."如果你想从 shell 命令输出 - 如果你有一个文件(如上),不要使用管道(否则权限被拒绝)
  • 注意格式 '%int16%int16' 将导致要“分组”为 2 个字节的字节流表示列(通道)1,接下来的 2 个字节表示列(通道)2,接下来的 2 个字节再次表示列 1,依此类推...请参阅 gnuplot docs_4.2:二进制通用 - 格式(也相关:Gnuplot:如何从二进制格式绘制多个时间序列
  • 最后通过两个独立的绘图,一个使用 0:1,另一个使用 0:2,我们可以获得典型的波形渲染(如接受的答案) - 一个通道高于另一个通道
  • 由于上面使用了 --persist 选项,gnuplot 将退出,而 (x11wxt) 窗口将保留 - 因此,典型的 gnuplot 与窗口的交互将不起作用

无论如何,很高兴我发现了这个,它将拯救我我认为相当长的时间 :)

Just wanted to document this - well, I was looking for a long time for a Linux command line audio waveform viewer, which could be called from the command line, with a raw binary file as input, and where the format of the data could be specified on the command line.

Audacity can import raw data, but only from the GUI (there is no way to specify raw datafile format through its command line options); while wave viewers like gwave, gtkwave or Gaw - Gtk Analog Wave viewer can either read proper .wav, or SPICE based formats.

And thanks to the answer by @Thor, now I know I can use gnuplot for the purpose. Here is an example command line, which interprets the raw binary data as 16-bit stereo:

gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1 ; unset multiplot"

... or broken in several lines:

gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1; \
unset multiplot"

Note that:

  • you should only use pipe "< ..." if you want to output from a shell command - if you have a file (like above), don't use the pipe (else getting permission denied)
  • Note the format '%int16%int16' will cause the byte stream to be "grouped" as 2 bytes representing column (channel) 1, the next 2 bytes as column (channel) 2, the next 2 bytes again as column 1, and so on... see gnuplot docs_4.2: Binary General - Format (also related: Gnuplot: How to plot multiple time series from a binary format)
  • Finally with two independent plots, one using 0:1 and the other using 0:2, we can get a typical waveform rendering (as in accepted answer) - with one channel above the other
  • Since the --persist option is used above, gnuplot will exit, while the (x11 or wxt) window will remain - and so, the typical gnuplot interaction with the window will not work

Anyways, glad I found this, will save me quite a bit of time, I think :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文