#!/usr/local/bin/perl -w
use strict;
use Audio::Data;
use File::Temp qw(tempfile);
use Carp;
$SIG{__DIE__} = \&Carp::confess;

my $N    = 256;
my $STEP = $N/2;
my $POLES = 14;

my $au;
if (@ARGV)
 {
  my $file = shift;
  open(my $fh,$file) || die "Cannot open $file;$!";
  binmode($fh);
  $au =  Audio::Data->new(Load => $fh);
  $au->comment("From $file") unless defined $au->comment;
  close($fh);
 } 
else
 {
  $au = Audio::Data->new(rate => 8000);
  $au->tone(500,0.5,0.6);
  $au->comment("500Hz tone");
# $au->noise(0.5,0.6);
 } 
 
print "Using ",$au,"\n"; 
my $rate = $au->rate;

my @temp;
my ($ph,$plot) = tempfile();
push(@temp,$plot);
print $ph "set data style lines\n";
my $sep = "plot";

open(my $dh,">3d.dat") || die "Cannot open 3d.dat:$!";

my $x = 0;
# plot_it($au,"samples");
my $d = $au->difference;
# plot_it($d,"diff");
my $n = $d;
for (my $st = 0; $st < $n; $st += $STEP)
 {
  #my $rwindow = $d->hamming($N,$st);
  #$rwindow->r2_fft; 
  #fft_plot($rwindow,"raw$st");

  # plot_it($window,"window");
  my $window = $d->hamming($N,$st);
  # plot_it($window,"window");
  my ($auto,$ref);
  my $lpc = $window->lpc($POLES,$auto,$ref);
#  plot_it($lpc,"new lpc");
#  plot_it($auto,"new auto");
#  plot_it($ref,"ref");
  my $durbin;
  if (1)
   {
    my $auto2   = $window->autocorrelation($POLES);
    #plot_it($auto2,'auto');
    $durbin = $auto2->durbin;
    #plot_it($durbin,'durbin');
    my $gain = $durbin->[0];
    warn "Durbin gain is $gain\n";
    $durbin *= -1;
    $durbin->[0] = 1.0;
    $durbin->length($N);
    #plot_it($durbin,'prep');
    my $fft = $gain/$durbin->fft($N);
    $fft->comment("durbin");
    fft_plot($fft,"$fft");
   }
  
  if (0)
   {
    my $mod = Audio::Data->new(rate => $rate);
    $mod .= [1.0,map { -$_ } $durbin->amplitude(1,$POLES)];
    $mod->length($N); 
    plot_it($mod,'mod lpc');
    $mod->r2_fft; 
    #fft_plot($mod,"mod$st");
   } 
  if (0)
   {
    $lpc->length(0);
    $lpc .= [1.0, map { -$_} $ref->amplitude(1,$POLES)];
    plot_it($lpc,'mod ref');
   } 
   
  if (0)
   { 
    $ref->length($N); 
    $ref->r2_fft; 
    fft_plot($ref,"ref$st");
   } 

  if (0)
   {
    $lpc->length($N);
    $lpc->r2_fft;
    my @data = map { 1/$_ } $lpc->amplitude;
    $lpc->length(0);
    $lpc .= \@data;
    fft_plot($lpc,"lpc$st");
   } 
  $x++;
  print $dh "\n";
 }
 
close($dh); 
print $ph "\n";
close($ph);
system("gnuplot",'-persist',$plot);
unlink(@temp);

sub fft_plot
{
 my ($au,$lab) = @_;
 my $N = $au->samples;
 my $rate = $au->rate;
 # print "$lab has ",$N," samples\n";
 my ($fh,$data) = tempfile();
 push(@temp,$data);
 my @amp = $au->dB(0,$N/2+1);
 my @phase = $au->phase(0,$N/2+1);
 for my $i (0..$#amp)
  {
   my $f = $i*$rate/$N;
   print $fh $f,' ',$amp[$i],' ',$phase[$i]*50/Audio::Data::PI()+50,"\n"; 
   print $dh $x,' ',$f,' ',$amp[$i],"\n"; 
  }
 close($fh);
 print $ph qq[$sep "$data" using 1:2 title "$lab fft dB"];
#print $ph qq[$sep "$data" using 1:3 title "$lab fft ph"];
 $sep = ",\\\n";
}

sub plot_it
{
 my ($au,$lab) = @_;
 my $n = $au->samples;
 print "$lab has $n samples\n";
 if (1 || $n < 16)
  {
   print "$lab:",join(',',map { sprintf("%.3g",$_) } $au->amplitude(0,20)),"\n";
  }

 my ($fh,$data) = tempfile();
 push(@temp,$data);
 foreach my $samp ($au->amplitude)
  {
   print $fh $samp,"\n"; 
  }
 print $ph qq[$sep "$data" using 0:1 title "$lab"];
 $sep = ",\\\n";
}

