NoteWorthy Composer Forum

Forums => Tips & Tricks => User Tools => Topic started by: Bryan Creer on 2009-01-16 10:33 am

Title: Noteworthy to ABC (ABCgen)
Post by: Bryan Creer on 2009-01-16 10:33 am
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
Title: Re: Noteworthy to ABC (ABCgen)
Post by: voldemort1 on 2009-04-08 07:08 pm
Nice!
thanks!
[move]remember you are only as strong as your weakest link.[/move]
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Warren Porter on 2011-02-08 08:53 pm
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.
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Rick G. on 2011-02-08 09:40 pm
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.
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Warren Porter on 2011-02-08 11:20 pm
I got
Quote
Command process failed
when a radio button was preselected to STDERR.
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Rick G. on 2011-02-08 11:55 pm
Look at the User Tool Description 'Command:' field. It should start with: php\php.exe
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Warren Porter on 2011-02-09 01:40 am
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.
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Bryan Creer on 2011-02-10 03:26 pm
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
Title: Re: Noteworthy to ABC (ABCgen)
Post by: Warren Porter on 2011-02-10 06:01 pm
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 (https://forum.noteworthycomposer.com/?topic=7586.0) if you haven't already.

Again, welcome back.