Skip to content

Instantly share code, notes, and snippets.

@windytan

windytan/plot_rpm.pl

Created Apr 15, 2020
Embed
What would you like to do?
Plot the amplitude in an audio file as a grayscale image
#!/usr/bin/perl
use strict;
use warnings;
# Perl script to plot the amplitude in an audio file as a grayscale image.
# Uses SoX and ImageMagick via shell.
#
# Note that the height of the image is only limited by the length of the
# audio file.
### Settings are here ###
#########################
# Width of the output image in pixels
my $width = 1024;
# Lines per minute
my $lpm = 33 + 1/3;
# Use anti-aliasing lowpass (faster sampling)? (1=yes, 0=no)
my $antialias = 1;
# Signed amplitude? (1=yes, 0=no)
my $signed = 1;
# Brightness multiplier
my $brightness = 1.0;
# Source audio
my $src_file = 'source.flac';
# Image to be written
my $dst_file = 'out.png';
### Cursed magic here ###
#########################
my $lopass = $width / (60 / $lpm) / 2;
my $samplerate = ($antialias ? $lopass * 2.2 : 44100);
my @img;
my $time = 0;
my $height = 0;
$src_file =~ s/"/\\"/g;
open my $sox, '-|', 'sox "' . $src_file . '" -t .s16 -c 1 -r ' . $samplerate . ' - ' .
'vol 0.9 '.($antialias ? 'sinc -' . $lopass : '') or die $!;
while (not eof $sox) {
read $sox, my $sample, 2;
$sample = (unpack 's', $sample) / 32767 * $brightness;
my $x = int($time / (60 / $lpm) * $width);
my $y = int($x / $width);
$x = $x % $width;
$height = $y + 1;
$img[$x][$y] = $signed ? ($sample + 1) / 2 : abs($sample);
$time += 1 / $samplerate;
}
close $sox;
$dst_file =~ s/"/\\"/g;
open my $magick, '|-', 'magick -size ' . $width . 'x' . $height .
' -depth 8 gray:- "' . $dst_file . '"' or die $!;
for my $y (0..$height-1) {
for my $x (0..$width-1) {
my $grayvalue = ($img[$x][$y] // 0) * 255;
$grayvalue = 255 if ($grayvalue > 255);
$grayvalue = 0 if ($grayvalue < 0);
print {$magick} pack 'C', $grayvalue;
}
}
close $magick;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment