From b866ae24fac9dd066cfae9ab2871aa67b6f2390a Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 25 Jan 2003 16:19:40 +0000 Subject: [PATCH] Added transpose mode. --- vs.pl | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 4 deletions(-) diff --git a/vs.pl b/vs.pl index 0ac0fb5..ad9be12 100755 --- a/vs.pl +++ b/vs.pl @@ -134,6 +134,81 @@ for(;;) { } } +### Chords ### + +package VS::Chord; + +# Internal representation of chords: : (so C="0:", C#="1:", Dmi="2:mi" etc.) +# but usually they are accompanied by position info after a second colon + +our (%t2n, @n2t); + +BEGIN { +%t2n = ( + "C" => 0, + "C#" => 1, + "Db" => 1, + "D" => 2, + "D#" => 3, + "Eb" => 3, + "E" => 4, + "Fb" => 4, + "E#" => 5, + "F" => 5, + "F#" => 6, + "Gb" => 6, + "G" => 7, + "G#" => 8, + "Ab" => 8, + "A" => 9, + "Bb" => 9, + "A#" => 10, + "Hb" => 10, + "B" => 10, + "H" => 11, + "B#" => 11, + "Cb" => 11, + "H#" => 0 +); +@n2t = ( "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "B", "H" ); +} + +sub parse_line($) { + my $r = shift @_; + my @l = (); + my $pos = 0; + while (my ($spaces,$chord,$rest) = $r =~ /(\s*)(\S+)(.*)/) { + $pos += length $spaces; + if (my ($tone,$sh,$mod) = ($chord =~ /^([CDEFGABH](#|b|))(.*)$/)) { + my $k = $t2n{$tone}; + push @l, "$k:$mod:$pos" + } else { + push @l, "0:?$chord:$pos"; + } + $pos += length $chord; + $r = $rest; + } + return \@l; +} + +sub synthesize_line($$) { + my ($l,$xpos) = @_; + my $pp = 0; + my $result = ""; + for (my $i=0; $i<@$l; $i++) { + my ($tone,$mod,$pos) = split(/:/, $l->[$i]); + $tone = ($tone + $xpos) % 12; + my $chord = $n2t[$tone] . "$mod "; + if ($pp < $pos) { + $result .= " " x ($pos - $pp); + $pp = $pos; + } + $result .= $chord; + $pp += length $chord; + } + return $result; +} + ### Window Objects ### package VS::Window; @@ -181,9 +256,12 @@ sub new($) { $w->{"file"} = ""; $w->{"attrs"} = {}; $w->{"lines"} = ["", "", " The Virtual Songbook 0.0\n", " (c) 2003 Martin Mares "]; - $w->{"linetype"} = [0,0,0,0]; + $w->{"chords"} = [0,0,0,0]; $w->{"n"} = 4; $w->{"top"} = 0; + $w->{"chords_analysed"} = 0; + $w->{"current_xpose"} = 0; + $w->{"requested_xpose"} = 0; return bless $w; } @@ -192,6 +270,8 @@ sub view($$$) { if ($w->{"file"} ne $f) { $w->{"file"} = $f; $w->{"xfile"} = $x; + $w->{"current_xpose"} = 0; + $w->{"chords_analysed"} = 0; $f =~ s@^./@@; $x =~ s@^./@@; if (open X, $f) { @@ -204,16 +284,17 @@ sub view($$$) { } } my @lines = (); - my @types = (); + my @chords = (); while () { chomp; - if (s/^!//) { push @types, 1; } else { push @types, 0; } + if (s/^!//) { push @chords, 1; } else { push @chords, 0; } push @lines, $_; } close X; $w->{"attrs"} = \%attrs; $w->{"lines"} = \@lines; - $w->{"linetypes"} = \@types; + $w->{"chords"} = \@chords; + $w->{"chordtable"} = []; $w->{"top"} = 0; $w->{"n"} = scalar @lines; $w->redraw; @@ -228,6 +309,24 @@ sub view($$$) { } } +sub transpose($) { + my $w = shift @_; + if (!$w->{"chords_analysed"}) { + for (my $i=0; $i<$w->{"n"}; $i++) { + if ($w->{"chords"}->[$i]) { + $w->{"chordtable"}->[$i] = VS::Chord::parse_line($w->{"lines"}->[$i]); + } + } + $w->{"chords_analysed"} = 1; + } + for (my $i=0; $i<$w->{"n"}; $i++) { + if ($w->{"chords"}->[$i]) { + $w->{"lines"}->[$i] = VS::Chord::synthesize_line($w->{"chordtable"}->[$i], $w->{"requested_xpose"}); + } + } + $w->{"current_xpose"} = $w->{"requested_xpose"}; +} + sub redraw_line($$) { my ($w,$i) = @_; my $win = $w->{"win"}; @@ -244,6 +343,7 @@ sub redraw_line($$) { sub redraw($) { my $w = shift @_; + $w->transpose if $w->{"current_xpose"} != $w->{"requested_xpose"}; my $win = $w->{"win"}; my $top = $w->{"top"}; my $cnt = $w->{"n"} - $w->{"top"}; @@ -294,6 +394,9 @@ sub key($$) { elsif ($key eq KEY_NPAGE) { $w->go($w->{"h"}-1); } elsif ($key eq KEY_HOME) { $w->go(-1000000000); } elsif ($key eq KEY_END) { $w->go(1000000000); } + elsif ($key eq "+" || $key eq "=") { $w->{"requested_xpose"} = ($w->{"requested_xpose"}+1)%12; $status_window->redraw; $w->redraw; } + elsif ($key eq "-") { $w->{"requested_xpose"} = ($w->{"requested_xpose"}+11)%12; $status_window->redraw; $w->redraw; } + elsif ($key eq "0") { $w->{"requested_xpose"} = 0; $status_window->redraw; $w->redraw; } else { $status_window->tell("Unknown key <$key>"); } } @@ -463,6 +566,9 @@ sub redraw($) { $win->bkgdset($attr_status); $win->addstr(0, 0, $w->{"msg"}); $win->clrtoeol; + my $aux = ""; + $aux = "T=" . $main_window->{"requested_xpose"} if ($main_window->{"requested_xpose"}); + $win->addstr(0, $w->{"w"}-length $aux, $aux) if $aux ne ""; $win->refresh; } -- 2.39.2