#!/usr/bin/perl -w

use Term::ReadKey;

my $tempo = 0.4; #1/4 note duration in seconds

my $sound = "pluck"; #also: "sine", "triangle", "square" ... (man sox)

my @notes = (
             "G3", "G#3", "A3", "A#3", "B3",
             "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
             "C5", "C#5", "D5"
             );

open F, "<klingel.bin" or die "cannot open 'klingel.bin'\n";
binmode F;
read F, $raw, 2048 or die "cannot read 'klingel.bin'\n";
close F;

@raw = unpack "C*", $raw;

my $pos = 0;
my $byte;
while (defined($byte = shift @raw)) {
    $pos++;
    next unless $byte == 0xF0;
    my @melody = ();
    while (defined($byte = shift @raw)) {
        if ($byte < 0xF0) {
            push @melody, $byte;
        } else {
            unshift @raw, $byte;
            play($pos-1, @melody);
            $pos += scalar @melody;
            last;
        }
    }
}

exit 0;


sub play
{
    my $pos = shift;
    printf "song found at 0x%04x : %d bytes - play? (yes / [no] / quit)\n", $pos, scalar @_;

    ReadMode('cbreak');
    my $key = ReadKey(0);
    ReadMode('normal');

    if (lc $key eq "q") {
        exit 0;
    }
    if (lc $key ne "y") {
        return;
    }

    while (my $byte = shift)
    {
        my $len = $byte & 0x07;
        if ($byte < 8) {
            #Pause
            if ($len == 0) {
                #1/16
                system sprintf "sleep %f", $tempo/4;
            }
            elsif ($len == 1) {
                #1/8
                system sprintf "sleep %f", $tempo/2;
            }
            elsif ($len == 3) {
                #1/4
                system sprintf "sleep %f", $tempo;
            }
            elsif ($len == 7) {
                #1/2
                system sprintf "sleep %f", $tempo*2;
            }
        }
        else {
            my $note = $notes[$byte/8 - 1];
            if ($len == 0) {
                #1/16
                system sprintf "play -q -n synth %f %s %s", $tempo/4, $sound, $note;
            }
            elsif ($len == 1) {
                #3/16
                system sprintf "play -q -n synth %f %s %s", $tempo*3/4, $sound, $note;
            }
            elsif ($len == 2) {
                #1/8
                system sprintf "play -q -n synth %f %s %s", $tempo/2, $sound, $note;
            }
            elsif ($len == 3) {
                #2x 1/8
                system sprintf "play -q -n synth %f %s %s", $tempo/2, $sound, $note;
                system sprintf "play -q -n synth %f %s %s", $tempo/2, $sound, $note;
            }
            elsif ($len == 4) {
                #3/8
                system sprintf "play -q -n synth %f %s %s", $tempo*3/2, $sound, $note;
            }
            elsif ($len == 5) {
                #1/4
                system sprintf "play -q -n synth %f %s %s", $tempo, $sound, $note;
            }
            elsif ($len == 6) {
                #2x 1/4
                system sprintf "play -q -n synth %f %s %s", $tempo, $sound, $note;
                system sprintf "play -q -n synth %f %s %s", $tempo, $sound, $note;
            }
            else {
                #1/2
                system sprintf "play -q -n synth %f %s %s", $tempo*2, $sound, $note;
            }
        }
    }
}
