Skip to content

Instantly share code, notes, and snippets.

@dallaylaen
Created August 15, 2014 17:31
Show Gist options
  • Save dallaylaen/9d108de1d7c8826f3133 to your computer and use it in GitHub Desktop.
Save dallaylaen/9d108de1d7c8826f3133 to your computer and use it in GitHub Desktop.
music tones: guess how many notes should be in one octave
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $besterr = 1000;
foreach my $i ( 5..100 ) {
my ($err, $notes) = find_all( 2**(1/$i), qw(3/2 4/3 5/4 6/5 9/8) );
next if $err > 1.5*$besterr;
$besterr = $err if $err < $besterr;
print "2^$i: $err: ".Dumper($notes);
};
sub find_all {
my ($base, @ratios) = @_;
my $maxerr = 0;
my %notes;
foreach (@ratios) {
my ($pow, $err) = ratio_diff( $base, $_ );
$notes{$_} = $pow;
if ($err > $maxerr) {
$maxerr = $err;
};
};
return ( $maxerr, \%notes );
};
sub ratio_diff {
my ($base, $ratio) = @_;
$ratio =~ m{(\d+)/(\d+)}
and $ratio = $1/$2;
my $pow = int ((log ($ratio) / log ($base)) + 0.5);
my $appr = $base ** $pow;
my $err = abs ($ratio - $appr) / abs ($ratio);
return ($pow, $err);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment