Advertisement
Yunga

oscillo.pl

Dec 28th, 2014
286
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.88 KB | None | 0 0
  1. # Rendering PCM with simulated phosphor persistence by Oona Räisänen
  2. # http://www.windytan.com/2013/03/rendering-pcm-with-simulated-phosphor.html
  3.  
  4. use warnings;
  5. use Getopt::Std;
  6.  
  7. getopt('xytGgwsf',\%opts);
  8.  
  9. # pcm file = $opts{f}
  10.  
  11. # samples per pixel x
  12. $xscale = $opts{x} // 1200;
  13.  
  14. # quant levels per pixel y
  15. $yscale = $opts{y} // 100;
  16.  
  17. # oversampling target rate
  18. $targetrate = $opts{t} // 1_099_961;
  19.  
  20. # wave preamplification, dB
  21. $ygain = $opts{G} // 0;
  22.  
  23. # brightness added by one sample
  24. $gain   = $opts{g} // 6;
  25.  
  26. # img width
  27. $w      = $opts{w} // 1000;
  28.  
  29. # skip amount of seconds
  30. $skip_sec = $opts{s} // 0.05;
  31.  
  32. ############
  33.  
  34. # turquoise tint
  35. for (0..127)   { @{$gradient[$_]} = ($_/2, $_*1.5 ,$_*1.5); }
  36. for (128..255) { @{$gradient[$_]} = (64+ ($_-128)*1.5, 192+($_-128)/2, 192+($_-128)/2); }
  37.  
  38. open(S,"sox \"".$opts{f}."\" -r $targetrate -b 16 -c 2 -t .raw -e signed - trim $skip_sec gain $ygain|");
  39.  
  40. $n=0;
  41. while(not eof(S)) {
  42.   read(S,$a,2);
  43.   $a = -unpack("s",$a);
  44.  
  45.   # pixel position of this sample
  46.   $x = $n/$xscale;
  47.   $y = ($a+32768)/$yscale;
  48.  
  49.   # bilinear interpolation
  50.   $xdec = $x-int($x);
  51.   $ydec = $y-int($y);
  52.   $pix[$x][$y]     += (1-$xdec) * (1-$ydec);
  53.   $pix[$x+1][$y]   += ($xdec)   * (1-$ydec);
  54.   $pix[$x][$y+1]   += (1-$xdec) * ($ydec);
  55.   $pix[$x+1][$y+1] += ($xdec)   * ($ydec);
  56.  
  57.   last if ($n/$xscale > $w);
  58.   read(S,$a,2);
  59.   $n++;
  60. }
  61.  
  62. close(S);
  63.  
  64. open(U,"|convert -depth 8 -size ".$w."x".int(65536/$yscale)." rgb:- osc.png");
  65. for $y (0..65536/$yscale-1) {
  66.   for $x (0..$w-1) {
  67.     $p = ($pix[$x][$y] // 0) * $gain;
  68.     $p = 255 if ($p > 255);
  69.     if ($y == round(65536/$yscale/2)) {
  70.       @a = @{$gradient[$p]};
  71.       for (@a) { $_ += 64; $_ = 255 if ($_ > 255); }
  72.       print U pack("CCC",@a);
  73.     } else {
  74.       print U pack("CCC",@{$gradient[$p]});
  75.     }
  76.   }
  77. }
  78. close(U);
  79.  
  80.  
  81. sub round { int($_[0]+.5); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement