Skip to main content
Topic: Noteworthy to ABC (ABCgen) (Read 28918 times) previous topic - next topic

Noteworthy to ABC (ABCgen)

Here is my first attempt at a UserTool to generate ABC from Noteworthy 2. It is not fully functional but covers my basic needs as a folk musician.

Code: [Select · Download]
<?php
/*******************************************************************************
kbsc_ABCgen.php Version 1.01

This script generates abc code from the selected Noteworthy code

Copyright © 2009 by K.B.S. Creer.
All Rights Reserved

HISTORY:
================================================================================
[2009-01-13] Version 1.00: Initial release
*******************************************************************************/
require_once("lib/nwc2clips.inc");

$keySorF = array ("Fb", "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F#", "C#" , "G#" , "D#", "A#", "E#", "B#");
$keyName = array ("BEADGCF" => "Cb", "BEADGC" => "Gb", "BEADG" => "Db", "BEAD" => "Ab", "BEA" => "Eb", "BE" => "Bb", "B" => "F", "C" => "C", "F" => "G", "FC" => "D", "FCG" => "A", "FCGD" => "E", "FCGDA" => "B", "FCGDAE" => "F#", "FCGDAEB" => "C#");
$noteName = array ("C,,", "D,,", "E,,", "F,,", "G,,", "A,,", "B,,", "C,", "D,", "E,", "F,", "G,", "A,", "B,", "C", "D", "E", "F", "G", "A", "B", "c", "d", "e", "f", "g", "a", "b", "c'", "d'", "e'", "f'", "g'", "a'", "b'");
$durArray = array ( "Whole" => 64*4, "Half" => 32*4, "4th" => 16*4, "8th" => 8*4, "16th" => 4*4, "32nd" => 2*4, "64th" => 4 ) ;
$durCodeArray = array ( 448 => "14", 384 => "12", 256 => "8", 224 => "7", 192 => "6", 128 => "4", 112 => "7/2", 96 => "3", 64 => "2", 56 => "7/4", 48 => "3/2", 32 => "", 28 => "7/8", 24 => "3/4", 16 => "/", 14 => "7/16", 12 => "3/8", 8 => "//", 7 => "7/32", 6 => "3/16", 4 => "///");
$Accidentals = array ("x" => "^^", "#" => "^", "n" => "=", "b" => "_", "v" => "__");
$knownTypes = array ("Clef", "Key", "TimeSig", "Bar", "Note", "Chord", "Ending", "Tempo", "Rest");
$tempoValue = array ("Eighth" => "1/8", "Eighth Dotted" => "3/16", "Quarter" => "1/4", "Quarter Dotted" => "3/8", "Half" => "1/2", "Half Dotted" => "3/4");

$clef="";
$timeSig="";
$keySig="C";
$tempo="1/4=120";
$beamOn=TRUE;
$slurStart=FALSE;
$slurOn=FALSE;
$slurEnd=FALSE;
$noteDuration=0;
$item=null;
$afterNewLine=TRUE;

$clip = new NWC2Clip('php://stdin');

function nextItem() {
global $knownTypes, $item, $clip;

$oType = "";
while (!in_array($oType, $knownTypes)) {
$item=array_shift($clip->Items);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
}
return $o;
}

function buildNote2 ($src, $dur) {
global $durArray, $durCodeArray, $clef, $noteName, $Accidentals, $beamOn, $slurStart, $slurOn, $slurEnd, $noteDuration;

$noteFactor=1;
$noteBase=1;
$graceNote=FALSE;
$triplet="";
$modifiers="";
foreach ($dur as $key => $val) {
switch ($key) {
case "Triplet":
if ($val=="First") $triplet="(3";
break;
case "Grace":
$graceNote=TRUE;
break;
case "Dotted":
$noteFactor=3/2;
break;
case "DblDotted":
$noteFactor=7/4;
break;
case "Staccato":
$modifiers.=".";
break;
case "Tenuto":
break;
case "Accent":
$modifiers.="L";
break;
case "Slur":
if (!$slurOn) {
$slurStart=TRUE;
$slurOn=TRUE;
}
$slurEnd=FALSE;
break;
default:
$noteBase=$durArray[$key];
break;
}
}
$noteDuration=$noteBase*$noteFactor;
$noteDurChars=$durCodeArray[$noteDuration];

if (!is_array($src)) $src = array($src);
$noteString="";
foreach ($src as $pos) {
$n = new NWC2NotePitchPos($pos);
switch ($clef) {
case "Treble":
$posShift=20;
break;
case "Bass":
$posShift=8;
break;
case "Alto":
$posShift=14;
break;
case "Tenor":
$posShift=12;
break;
default:
$posShift=20;
break;
}

if ($graceNote) $noteString.="{";

$noteString.=$modifiers . $triplet;
if ($n->Accidental!="") $noteString.=$Accidentals[$n->Accidental];
$noteString.=$noteName[$n->Position+$posShift] . $noteDurChars;

if ($graceNote) $noteString.="}";
if ($n->Tied=="^") $noteString.="-";
}

return $noteString;
}

function buildNote ($opts) {
global $durArray, $durCodeArray, $clef, $noteName, $beamOn, $slurStart, $slurOn, $slurEnd, $noteDuration;

$slurEnd=TRUE;

$src=$opts["Pos"];
$dur=$opts["Dur"];
$noteString=buildNote2 ($src, $dur);

if (isset($opts["Pos2"])) {
$src=$opts["Pos2"];
$dur=$opts["Dur2"];
$noteString.=buildNote2 ($src, $dur);
}

if ($slurStart) {$noteString="(" . $noteString; $slurStart=FALSE;}
if (!$beamOn) $noteString=" " . $noteString;

if ($noteDuration>=64) {
$beamOn=TRUE;
} else {
$beamOn=FALSE;
}

if (isset($opts["Opts"])) {
$opts2=$opts["Opts"];
foreach ($opts2 as $key => $val) {
switch ($key) {
case "Beam":
if ($val=="End") {
$beamOn=FALSE;
} else {
$beamOn=TRUE;
}
break;
default:
break;
}
}
}

if ($slurEnd && $slurOn) {$noteString=$noteString . ")"; $slurOn=FALSE;}

return $noteString;
}

function buildRest ($opts) {
global $durArray, $durCodeArray;

$dur=$opts["Dur"];
$restFactor=1;
$restBase=1;
$triplet="";
foreach ($dur as $key => $val) {
switch ($key) {
case "Triplet":
if ($val=="First") $triplet="(3";
break;
case "Dotted":
$restFactor=3/2;
break;
case "DblDotted":
$restFactor=7/4;
break;
default:
$restBase=$durArray[$key];
break;
}
}
$restDuration=$restBase*$restFactor;
$restDurChars=$durCodeArray[$restDuration];
$restString=$triplet . "z" . $restDurChars;

return $restString;
}


echo "X:1\n".
"T:insert tune name here\n";

$o=nextItem();
$oType = $o->GetObjType();
$opts = $o->GetOpts();
while (($oType == "Clef") || ($oType == "Key") || ($oType == "TimeSig") || ($oType == "Tempo")) {
switch ($oType) {
case  "Clef":
$clef=$opts["Type"];
break;
case  "Key":
$keyNotes="";
foreach ($opts["Signature"] as $key => $val) {
$keyNotes .= substr($key, 0, 1);
}
$keySig=$keyName[$keyNotes];
break;
case  "TimeSig":
$timeSig = $o->GetTaggedOpt("Signature") ;
break;
case  "Tempo":
if (isset($opts["Base"])) {
$base=$opts["Base"];
} else {
$base="Quarter";
}
$baseTrans=$tempoValue[$base];
$tempoCount=$opts["Tempo"];
$tempo=$baseTrans . "=" . $tempoCount;
break;
}
$o=nextItem();
$oType = $o->GetObjType();
$opts = $o->GetOpts();
}

if ($timeSig != "") echo "M:" . $timeSig . " \n";
echo "L:1/8" . " \n";
echo "Q:" . $tempo . "\n";

$Kcommand="K:" . $keySig;
if ($clef != "" && $clef != "Treble") $Kcommand .= "clef=" . $clef;
$Kcommand .= " \n";
echo $Kcommand;

array_unshift ($clip->Items, $item);
$clef="";
$keySig = "";
foreach ($clip->Items as $item) {
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
if ($oType!="Clef" && $oType!="Key") {
if ($clef!="" || $keySig!="") {
if ($afterNewLine) {
$Kcode = "K:";
} else {
$Kcode = "[K:";
}
if ($keySig!="") {
$Kcode .= $keySig;
}
if ($clef!="") {
$Kcode .= " clef=" . $clef;
}
if ($afterNewLine) {
$Kcode .= "\n";
} else {
$Kcode .= "]";
}
echo $Kcode;
$clef="";
$keySig = "";
}
}
switch ($oType) {
case "Bar":
$opts = $o->GetOpts();
if (isset($opts["Style"])) {
switch ($opts["Style"]) {
case "Double":
echo "||";
break;
case "SectionOpen":
echo "[|";
break;
case "SectionClose":
echo "|]";
break;
case "MasterRepeatOpen":
echo "|:";
break;
case "MasterRepeatClose":
echo ":|";
break;
case "LocalRepeatOpen":
break;
case "LocalRepeatClose":
break;
default:
echo "|";
break;
}
} else {
echo "|";
}
if (isset($opts["SysBreak"])) {echo "\n"; $afterNewLine=TRUE;}
$beamOn=TRUE;
break;
case "Note":
$afterNewLine=FALSE;
$opts = $o->GetOpts();
echo buildNote($opts);
break;
case "Chord":
$afterNewLine=FALSE;
$opts = $o->GetOpts();
echo "[" . buildNote($opts) . "]";
break;
case "Ending":
$afterNewLine=FALSE;
$opts = $o->GetOpts();
$endingCode="[";
foreach ($opts["Endings"] as $key => $val) {
$endingCode .= $key . ",";
}
$endingCode = substr($endingCode, 0, -1) . " ";
echo $endingCode;
break;
case  "Rest":
$afterNewLine=FALSE;
$opts = $o->GetOpts();
echo buildRest($opts);
break;
case  "Clef":
$clef=$o->GetTaggedOpt("Type");
break;
case  "Key":
$opts = $o->GetOpts();
$keyNotes="";
foreach ($opts["Signature"] as $key => $val) {
$keyNotes .= substr($key, 0, 1);
}
$keySig = $keyName[$keyNotes];
break;
case  "TimeSig":
if ($afterNewLine) {
echo "M:" . $o->GetTaggedOpt("Signature")  . "\n";
} else {
echo "[M:" . $o->GetTaggedOpt("Signature")  . "]";
}
break;
case  "Tempo":
$opts = $o->GetOpts();
if (isset($opts["Base"])) {
$base=$opts["Base"];
} else {
$base="Quarter";
}
$baseTrans=$tempoValue[$base];
$tempoCount=$opts["Tempo"];
if ($afterNewLine) {
echo "Q:" . $baseTrans . "=" . $tempoCount . "\n";
} else {
echo "[Q:" . $baseTrans . "=" . $tempoCount . "]";
}
break;
default:
break;
}
unset($o);
}

exit(NWC2RC_REPORT);
?>

Bug reports, comments and suggestions for what functionality to add next are very welcome. I'm on a fairly steep learning curve for php and object oriented programming.

Bryan

Re: Noteworthy to ABC (ABCgen)

Reply #1
Nice!
thanks!
[move]remember you are only as strong as your weakest link.[/move]

 

Re: Noteworthy to ABC (ABCgen)

Reply #2
When I installed this, I got a generic error message on a file with just a simple, two measure d major scale on the treble clef.  Any ideas?

Bryan hasn't posted in over a year.
Since 1998

Re: Noteworthy to ABC (ABCgen)

Reply #3
There are no generic error messages :-)

I didn't get errors unless I tried to send 'File text', where I got:
Quote from: STDERR
Error: [in <path>\lib\obj_NWC2Clip.inc, at line 35] --> Unrecognized notation clip format header
IOW, the tool only supports 1 staff.
Registered user since 1996

Re: Noteworthy to ABC (ABCgen)

Reply #4
I got
Quote
Command process failed
when a radio button was preselected to STDERR.
Since 1998

Re: Noteworthy to ABC (ABCgen)

Reply #5
Look at the User Tool Description 'Command:' field. It should start with: php\php.exe
Registered user since 1996

Re: Noteworthy to ABC (ABCgen)

Reply #6
I only had "php.php.exe" .. close but no cigar.

After fixing it I took it's output to my gizmo--the generated line was almost identical to the original.  The notes were fine but there were a few problems with slurs and beams on grace notes and I couldn't handle tenuto lines over some notes.  Finally a major incentive to learn php.

Once again, many thanks for your help.
Since 1998

Re: Noteworthy to ABC (ABCgen)

Reply #7
Bryan hasn't posted in over a year.

More like two. I'm getting the same on my new PC under Windows 7. Don't know if that has anything to do with it. Do I gather you've got it working, Warren?

I'm afraid it will take me a while to remind myself how it works.

Bryan

Re: Noteworthy to ABC (ABCgen)

Reply #8
Welcome Back!

I got it working but haven't done too much with it yet.  This is what it produced:
Code: [Select · Download]
X:1
T:insert tune name here
M:4/4
L:1/8
Q:1/4=60
K:C
(^g4-gg) ((3g/a/g/^^f/g/)|(3a^c=d (3^e^fa (^c'=c') ({b/}{^c'/} b)a|^g2(g2-g3/2g/) (g3/2g/)|^g2(g2-g3/2g/) g3/2(g/|_a3/2a/) (a3/2a/) (a3/2=g/) (a3/2_b/)|(_a3/2g/) (a3/2_b/) (3_d'_c'b (3ag_g|(3f_ef (3_afa (3_c'ac' (3_e'c'e'|f'z Lb2Lb2Lb2
and the attachment shows the original NWC (created to avoid an awkward page turn) as well as my conversion back to NWC.  My page can't handle tenutos yet, it missed a triplet and interpreted the ( as the beginning of a slur.  Time for me to get tinkering again.

Please check out this thread if you haven't already.

Again, welcome back.
Since 1998