Skip to main content

Show Posts

This section allows you to view all Show Posts made by this member. Note that you can only see Show Posts made in areas you currently have access to.

Messages - Bryan Creer

2
User Tools / Swing
Inspired by Eric's Unjazzify tool and these threads -

https://forum.noteworthycomposer.com/?topic=2335.msg12893#msg12893
https://forum.noteworthycomposer.com/?topic=6032.0
https://forum.noteworthycomposer.com/?topic=5806
https://forum.noteworthycomposer.com/?topic=5590

I have written a tool to apply a variable amount of swing to tunes.

Code: [Select · Download]
<?php
/*******************************************************************************
kbsc_Swing.php Version 1.00

This script creates a tempo staff

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

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

function help_msg_and_exit()
{
echo 'Called as:

php\php.exe scripts\kbsc_Swing.php "/swing=<PROMPT:Swing as percentage:=*help>"

This User Tool creates a tempo staff to apply "swing" to a melody.
The amount of time applied to two notes adding up to one crotchet (quarter note) is split between the two notes according to a parameter specifying the percentage of the time to be applied to the first note.
The result is the same regardless of whether the notes are pair of quavers (eighth notes) or a dotted crotchet + a semi-quaver.
Triplets are left unchanged.

The tool works for tunes in 2/2, 4/4, 6/8, 9/8 and 12/8. In compound time, the process is applied to the first two quavers (eighth notes) of each set of three, the third remaining unchanged.

IMPORTANT - the process overwrites the melody. Create a copy of the melody in a new staff and apply the tool to that.' ;
exit(NWC2RC_REPORT) ;
}

function error_msg_and_exit_1($a)
{
echo "Error - $a. Number in range 5 to 95 required";
exit(NWC2RC_REPORT) ;
}
function error_msg_and_exit_2($a)
{
if ($a=="") {
echo "Error - Need a Time Signature. 2/2. 4/4, 6/8, 9/8 and 12/8 only";
} else {
echo "Error - Can't process Time Signature  $a. - 2/2, 4/4, 6/8, 9/8 and 12/8 only";
}
exit(NWC2RC_REPORT) ;
}

define("QUARTER", 16);
define("EIGHTH", 8);
define("SIXTEENTH", 4);

$noteTypes = array ("Note", "Rest", "Chord", "RestChord"); //Items to process
$durArray = array ( "Whole" => 64, "Half" => 32, "4th" => 16, "8th" => 8, "16th" => 4, "32nd" => 2, "64th" => 1) ;
$durArray2 = array_flip ($durArray);
$partBarNotes = array ();
$tempo=120;
$beatLen=0;
$barDuration=0;
$beatsPerBar = 0;
$leadingNotes = TRUE;
$compound = FALSE;
$timeSig="";

function getDuration ($dur) {
//Given a Dur array, returns the duration of the note in sixteenth notes. e.g. crotchet (quarter note) = 16, dotted crotchet = 24
global $durArray;

$noteFactor=1;
$noteBase=1;
foreach ($dur as $key => $val) {
switch ($key) {
case "Triplet":
break;
case "Grace":
$noteBase=$durArray[$key];
break;
case "Dotted":
$noteFactor=3/2;
break;
case "DblDotted":
$noteFactor=7/4;
break;
case "Staccato":
break;
case "Tenuto":
break;
case "Accent":
break;
case "Slur":
break;
default:
$noteBase=$durArray[$key];
break;
}
}
$noteDuration=$noteBase*$noteFactor;

return $noteDuration;
}

function getBar (&$clipItems) {
/*******************************************************************************
Return an array of durations of notes from the current position up to the next bar line.
Quaver triplets are output as a single note with crotchet duration.
Notes longer than a crotchet are broken up as if they were built up of tied notes with maximum duration a crotchet.
Notes shorter than a quaver are combined into quavers
*******************************************************************************/
global $tempo, $beatLen, $barDuration,  $beatsPerBar, $leadingNotes, $noteTypes;

$notesInBeat = array ();
$barDuration = 0;
$tripletDur = 0;
$item=current($clipItems);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
while  ($item && $oType!="Bar") {
if ($oType=="Tempo") {
$tempo = $o->GetTaggedOpt("Tempo");
} elseif ($oType=="Ending") {
$leadingNotes = FALSE;
echo $item;
} elseif (in_array($oType, $noteTypes)) {
$opts = $o->GetOpts();
if (isset($opts["Dur"]["Triplet"])) {
$m=getDuration ($opts["Dur"]);
$tripletDur+=$m;
if ($opts["Dur"]["Triplet"]=="End") {
$tripletDur=$tripletDur * 2 / 3;
if ($tripletDur==$beatLen*2) { //crotchet triplet split into two crotchets
$notesInBeat[] = $beatLen;
$notesInBeat[] = $beatLen;
$barDuration+=$beatLen*2;
} else {
$notesInBeat[] = $tripletDur;
$barDuration+=$tripletDur;
}
$tripletDur = 0;
}
} else {
$duration=getDuration ($opts["Dur"]);
if ($duration<$beatLen/4) {
$littleNotesDur=$duration;
while ($littleNotesDur<$beatLen/2) {
$item=next($clipItems);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
if (in_array($oType, $noteTypes)) {
$opts = $o->GetOpts();
$duration=getDuration ($opts["Dur"]);
$littleNotesDur+=$duration;
}
$notesInBeat[] = $littleNotesDur;
$barDuration +=  $littleNotesDur;
}
} else {
while ($duration>$beatLen) {
$notesInBeat[] = $beatLen;
$barDuration +=  $beatLen;
$duration -= $beatLen;
}
$notesInBeat[] = $duration;
$barDuration += $duration;
}
}
}

$item=next($clipItems);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
}

return $notesInBeat;
}

function createMPC($pBN,$pc) {
global $tempo, $beatLen;
$MCPstr="|MPC|Controller:tempo|Style:Absolute|TimeRes:Sixteenth|SweepRes:1";
$offset = 0;
$Pt = 1;
$note =  array_shift ($pBN);
if ($note>=QUARTER) {
$MCPstr.="|Pt$Pt:$offset,$tempo";
} else {
if ($note>0) {
$N=round(100 * $note * $tempo / (QUARTER * $pc));
$MCPstr.="|Pt$Pt:$offset,$N";
$Pt += 1;
$offset = $note / 4;
}
$pc = 100 - $pc;

$note =  array_shift ($pBN);
if (isset($note)) {
if ($note>0) {
$N=round(100 * $note * $tempo / (QUARTER * $pc));
$MCPstr.="|Pt$Pt:$offset,$N";
$Pt += 1;
$offset = $note / 4;
}

$note =  array_shift ($pBN);
if (isset($note)) {
$MCPstr.="|Pt$Pt:$offset,$tempo";
}
}
}

$MCPstr.="|Pos:-5|Wide:N|Justify:Left|Placement:BestFit|Color:0|Visibility:Default";
return $MCPstr;
}

function createRest($dur) {
global $durArray2;
if ($dur % 7) { //not divisible by 7 therefore not DblDotted
if ($dur % 3) { //not divisible by 3 therefore not Dotted
$durCode="";
} else { // Dotted
$durCode=",Dotted";
$dur=$dur * 2 / 3;
}
} else {
$durCode=",DblDotted";
$dur=$dur * 4 / 7;
}
$durCode=$durArray2[$dur] . $durCode;


$RestStr="|Rest|Dur:" . $durCode . "|Color:0|Visibility:Default";
return $RestStr;
}

function createBeat (&$barNotes, $partLength, $percentage) {
global $barDuration;
$partBarNotes = array ();
$partDur=0;
$j=0;
while ($partDur<$partLength && $j < 10) {
$noteDur=array_shift($barNotes);
$partBarNotes[] = $noteDur;
$partDur += $noteDur;
$j+=1;
}
$barDuration -= $partDur;
echo createMPC($partBarNotes, $percentage) . "\n";
echo createRest($partDur) . "\n";
}

//Get parameters

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

array_shift($argv) ; // get rid of the first arg (script name)
foreach ($argv as $arg) {
if ($arg == "help") help_msg_and_exit() ;
if (preg_match('/^(\d+)$/',$arg,$m)) {
$percentage = $m[1];
if ($percentage > 95 || $percentage < 5) {
error_msg_and_exit_1($percentage);
}
} else {
error_msg_and_exit_1($arg);
}
}

//Start of main processing

echo $clip->GetClipHeader()."\n";

//Read stuff before first note (clef, key, time sig etc.) and write it back to Noteworthy
$tempo=120;
$item=current($clip->Items);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
while  ($item && !in_array($oType, $noteTypes)) {
if ($oType=="TimeSig") {
$timeSig = trim($o->GetTaggedOpt("Signature"));
if ($timeSig=="Common") {
$timeSig = "4/4";
} else {
if ($timeSig=="AllaBreve") {
$timeSig = "2/2";
}
}
if (preg_match('/^(\d+)\/(\d+)$/',$timeSig,$m)) {
$timeSigNum = $m[1];
$timeSigDen = $m[2];
$barLength=$timeSigNum * (64 / $timeSigDen);
}
}
if ($oType=="Tempo") {
$tempo = $o->GetTaggedOpt("Tempo");
}

echo $item;

$item=next($clip->Items);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
}

//Current Item is the first 'note' of the tune

if ($timeSig=="4/4" || $timeSig=="2/2") {
$beatsPerBar = 4;
$beatLen=16;
} elseif ($timeSig=="6/8") {
$beatsPerBar = 2;
$beatLen=24;
} elseif ($timeSig=="9/8") {
$beatsPerBar = 3;
$beatLen=24;
} elseif ($timeSig=="12/8") {
$beatsPerBar = 4;
$beatLen=24;
} else {
error_msg_and_exit_2($timeSig);
}

$barNotes=getBar($clip->Items);

$i=0;
while ($barDuration && $i < 100) {
if ($barDuration<$beatLen*$beatsPerBar) { //incomplete bar
if ($leadingNotes) {
if ($barDuration % $beatLen) { //the first note isn't on the beat
array_unshift($barNotes, 0);
if ($beatLen==24 && $barDuration % $beatLen==EIGHTH) {
array_unshift($barNotes, 0);
$PL=$barDuration % $beatLen;
}
createBeat ($barNotes, $barDuration % $beatLen, $percentage);
}
$k=0;
while ($barDuration && $k<10) {
createBeat ($barNotes, $beatLen, $percentage);
$k += 1;
}
$leadingNotes = FALSE;
} else {
$k=0;
while ($barDuration >= $beatLen && $k<10) {
createBeat ($barNotes, $beatLen, $percentage);
$k += 1;
}
if ($barDuration) {
createBeat ($barNotes, $barDuration, $percentage);
}
$leadingNotes = TRUE;
}
} else { //complete bar
$k=0;
while ($barDuration && $k<10) {
createBeat ($barNotes, $beatLen, $percentage);
$k += 1;
}
}
$item=current($clip->Items);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
while  ($oType=="Bar") {
echo $item;
$item=next($clip->Items);
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();
}
$barNotes=getBar($clip->Items);
$i+=1;
}

echo NWC2_ENDCLIP."\n";

exit(NWC2RC_SUCCESS);
?>

Let me know what you think.

Bryan Creer
3
User Tools / Re: Change Clef
Just done some more testing and if I take out the if (isset($o->Opts[$p])) { test, I get -

Note: [in C:\Program Files\NoteWorthy Composer 2\scripts\kbsc_Clef_Change.php, at line 86]
--> Undefined index:  Pos

on Restchords and the same with Pos2 on Notes and same duration chords. Split duration chords work.

Dontcha just love inconsistent errors?

Bryan
4
User Tools / Re: Change Clef
NWC has a legacy of some 15 years. Things that seem strange now made perfect sense then. Ever since custom noteheads were added, it has been obvious to me that a 'Rest' is better described as a note that is always muted and has a custom notehead. Before RestChords and split duration Chords, it probably made sense to distinguish between notes and chords.

I wasn't suggesting radical changes to NWC, just that NWC2ClipItem should return Pos as an array of 1 from Note.

count($o->Opts["Pos"]); seems to get upset if Pos isn't there so I had to put in an isset.

From my background in IT, readability is a high priority. The code may next be amended by someone else 5 years later so it needs to be obvious what it does and why. It's even worse when it's yourself five years later. "Who wrote this rubbish? Oh!"

Bryan
5
User Tools / Re: Change Clef
Here's the new version

Code: [Select · Download]
<?php
/*******************************************************************************
kbsc_Clef_Change.php Version 1.00

This script changes the Clef and adjusts the positions of the notes on the stave to keep the same note values

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

HISTORY:
================================================================================
[2009-01-21] Version 1.01: Improvements to code as suggested by Rick G and Lawrie Pardy
[2009-01-19] Version 1.00: Initial release
*******************************************************************************/
require_once("lib/nwc2clips.inc");

function help_msg_and_exit()
{
echo 'Called as:
php\php.exe scripts\kbsc_Clef_Change.php "/clef=<PROMPT: Select Clef:=|help|Treble|Bass|Alto|Tenor|Percussion|>" "/octave=<PROMPT:Select Octave Shift:=|None|Octave Up|Octave Down|>"

Notes are defined in Noteworthy by their position on the stave.
If the Clef is changed, the notes remain in the same position and hence represent different note values.
This User Tool changes the Clef and adjusts the positions of the notes to keep the same note values.

The first clef symbol in the selection (or the whole tune if no selection is made) is changed and all subsequent
notes are adjusted up to the next clef symbol or the end of the tune, whichever comes first.' ;
exit(NWC2RC_REPORT) ;
}

$noteTypes = array ("Note", "Chord", "RestChord"); //Items to process
$clefShift = array ("Treble" => -6, "Alto" => 0, "Tenor" => 2, "Bass" => 6, "Percussion" => 6); //Position of middle C
$octaveShift = array ("None" => 0 , "Octave Up" => -7 , "Octave Down" => 7); //Position of octaves

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

$arg = array('clef' => 'Treble','octave' => 'None');
foreach ($argv as $k => $v) {
if (!$k) continue;

if (preg_match('/^\/([a-z]+)\=(.*)$/',$v,$m)) {
$argname = $m[1];
$argvalue = $m[2];
$arg[strtolower($argname)] = $argvalue;
}
}
if ($arg["clef"] == "help") help_msg_and_exit() ;

echo $clip->GetClipHeader()."\n";
//
$firstClefFound=FALSE;
$secondClefFound=FALSE;
$shiftPos = 0;
foreach ($clip->Items as $item) {
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();

if ($secondClefFound) { //After the second clef write everything back unchanged
echo $item;
continue;
}
if ($oType=="Clef") {
if ($firstClefFound) { //You've found a second clef. Stop adjusting
echo $item;
$secondClefFound=TRUE;
} else { //Calculate the amount to shift notes by
$startPos = $clefShift[$o->Opts['Type']]; //
$endPos = $clefShift[$arg['clef']]; //For change of clef
if (isset($o->Opts['OctaveShift'])) {
$startOctave = $octaveShift[$o->Opts['OctaveShift']]; //
} else { //
$startOctave = 0; //For change of octave
} //
$endOctave = $octaveShift[$arg['octave']]; //
$shiftPos = $endPos - $startPos + $endOctave - $startOctave;
$o->Opts['Type'] = $arg['clef']; //Set new clef symbol
$o->Opts['OctaveShift'] = $arg['octave']; //  and octave shift
echo $o->ReconstructClipText()."\n";
$firstClefFound=TRUE;
}
} else {
if ($shiftPos) { //Only if there is a non zero position shift
if (in_array($oType, $noteTypes)) {
if ($oType=="Note") settype($o->Opts["Pos"], "array"); //Note "Pos" is a string, others are array
foreach (array("Pos", "Pos2") as $p) {
if (isset($o->Opts[$p])) {
for ($i = 0; $i < count($o->Opts[$p]); $i++) {
$notepitchObj = new NWC2NotePitchPos($o->Opts[$p][$i]);
$notepitchObj->Position += $shiftPos;
$o->Opts[$p][$i] = $notepitchObj->ReconstructClipText();
}
}
}
echo $o->ReconstructClipText()."\n";
} else {
echo $item;
}
} else {
echo $item;
}
}
}

echo NWC2_ENDCLIP."\n";
exit(NWC2RC_SUCCESS);
?>

And this is the command line courtesy of Lawrie -

php\php.exe scripts\kbsc_Clef_Change.php "/clef=<PROMPT: Select Clef:=|help|Treble|Bass|Alto|Tenor|Percussion|>" "/octave=<PROMPT:Select Octave Shift:=|None|Octave Up|Octave Down|>"

Bryan
6
User Tools / Re: Change Clef
Ooops! Sorry Lawrie. It seems my genius rating is slipping. I must have edited an existing help_msg_and_exit knicked from someone else and then knicked a command line to make mine. Yours is spot on. You could have saved yourself some trouble by posting and asking "What the £%$@ are you on about?".  Bear with me, I'm on a learning curve.

Rick.  Thinking about it, you are obviously right. ReconstructClipText should be able to cope with string or array for Pos because it already does depending on whether it comes from a Note or a Chord. I'm fighting ingrained cultural ideas from an older style of programming (not all of which need to be thrown out).

I agree with you that it would make more sense for Pos to be returned as an array of one from Note. The syntax of the clip text is the same - e.g. Pos:-2 for a Note and Pos:-2,0,2 for a Chord. Do you think we can work on Eric?

I'll try and implement your suggestion. I'm a bit confused by the test for [Dur]. Is that intended as a way of identifying Note, Chord and RestChord by a common property? If so, Rest has [Dur] as well and lots of things have [Pos] so you can't use that either. I would prefer to be explicit.

Flurmy. Watch this space. New version along soon although not really functionally any different. I might remember to put a few comments in to make it easier to understand (for me as well when I comme back to it in six months).

Perhaps it's worth me saying why I felt the need for this.  I play in a concertina band. Generally, each of us plays a single melody or harmony line.  The baritone instrument that plays the bottom line has exactly the same fingering as the treble and comes out an octave lower so it is easier for them to play from a treble clef than a bass clef. Sometimes the middle line will fit more comfortably, with fewer leger lines, on a tenor clef. On the other hand, we usually get stuff in standard treble and bass arrangements and it's easier to see like that when writing arrangements on Noteworthy as well so converting between clefs comes in handy. Maybe not much use to a lot of people but that's what User Tools are about.

Bryan
7
User Tools / Re: Change Clef
Hi Rick

I was beginning to feel that my work of genius was going to pass unmarked by an ungrateful world. It's interesting that Views on the threads reach the thousands but Replies rarely get out of single figures. Perhaps Noteworthy is so good that it doesn't need any User Tools. I happened to find something that was useful for me but I've no idea if it will be of the slightest interest to anyone else. Are Restchords now deprecated? Any debate is before my time.

The repeated code was, indeed, deeply unsatisfactory. It wasn't the array/not array problem that was worrying me. I've tackled the same problem in my ABCgen tool using an idea knicked from one of Andrew Purdam's scripts along the lines of $a= array($a) but that was on a copy of Opts["Pos"] not the real thing. My concern was about how to have common code updating the item object. Your solution is very neat but I'd be a bit concerned about changing the format of the actual object so that it won't be what the code in ReconstructClipText is expecting. Maybe it copes, but I don't KNOW that it will cope.

Took me a while but I'm with you on $shiftPos. Before you hit the first clef, it will be zero and if you're moving between Bass and Percussion, likewise. As an old COBOL programmer, the idea of testing a data field to be true or false makes me feel a little uncomfortable. My instinct would be to test ($shiftPos==0).  Can't get used to these modern ways.

Now if I can just work out how to read a multi-line input file, I can get started on the ABC to Noteworthy converter.

Bryan
8
User Tools / Change Clef
My second effort at a User Tool.

While it is easy enough to change the Clef symbol, the notes stay in the same position on the stave and hence become different notes. This tool changes the clef and adjust all the notes and chords so that they sound the same.

Code: [Select · Download]
<?php
/*******************************************************************************
kbsc_Clef_Change.php Version 1.00

This script changes the Clef and adjusts the positions of the notes on the stave to keep the same note values

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

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

function help_msg_and_exit()
{
echo "Called as:
php kbsc_Clef_Change.php <clef>=|help|Treble|Bass|Alto|Tenor|Percussion| <octave>=|None|Octave Up|Octave Down|

Notes are defined in Noteworthy by their position on the stave.
If the Clef is changed, the notes remain in the same position and hence represent different note values.
This User Tool changes the Clef and adjusts the positions of the notes to keep the same note values.

The first clef symbol in the selection (or the whole tune if no selection is made) is changed and all subsequent
notes are adjusted up to the next clef symbol or the end of the tune, whichver comes first." ;
exit(NWC2RC_REPORT) ;
}

$noteTypes = array ("Note", "Chord", "RestChord");
$clefShift = array ("Treble" => -6, "Alto" => 0, "Tenor" => 2, "Bass" => 6, "Percussion" => 6);
$octaveShift = array ("None" => 0 , "Octave Up" => -7 , "Octave Down" => 7);

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

$arg = array('clef' => 'Treble','octave' => 'None');
foreach ($argv as $k => $v) {
if (!$k) continue;

if (preg_match('/^\/([a-z]+)\=(.*)$/',$v,$m)) {
$argname = $m[1];
$argvalue = $m[2];
$arg[strtolower($argname)] = $argvalue;
}
}
if ($arg["clef"] == "help") help_msg_and_exit() ;

echo $clip->GetClipHeader()."\n";
//
$firstClefFound=FALSE;
$secondClefFound=FALSE;
foreach ($clip->Items as $item) {
$o = new NWC2ClipItem($item);
$oType = $o->GetObjType();

if ($secondClefFound) {
echo $item;
continue;
}
if ($oType=="Clef") {
if ($firstClefFound) {
echo $item;
$secondClefFound=TRUE;
} else {
$startPos = $clefShift[$o->Opts['Type']];
$endPos = $clefShift[$arg['clef']];
if (isset($o->Opts['OctaveShift'])) {
$startOctave = $octaveShift[$o->Opts['OctaveShift']];
} else {
$startOctave = 0;
}
$endOctave = $octaveShift[$arg['octave']];
$shiftPos = $endPos - $startPos + $endOctave - $startOctave;
$o->Opts['Type'] = $arg['clef'];
$o->Opts['OctaveShift'] = $arg['octave'];
echo $o->ReconstructClipText()."\n";
$firstClefFound=TRUE;
}
} else {
if ($firstClefFound) {
if (in_array($oType, $noteTypes)) {
if ($oType=="Note") {
$notepitchObj = new NWC2NotePitchPos($o->Opts["Pos"]);
$notepitchObj->Position += $shiftPos;
$o->Opts["Pos"] = $notepitchObj->ReconstructClipText();
echo $o->ReconstructClipText()."\n";
} else {
if (isset($o->Opts["Pos"])) {
$c=count($o->Opts["Pos"]);
for ($i = 0; $i < $c; $i++) {
$notepitchObj = new NWC2NotePitchPos($o->Opts["Pos"][$i]);
$notepitchObj->Position += $shiftPos;
$o->Opts["Pos"][$i] = $notepitchObj->ReconstructClipText();
}
}
if (isset($o->Opts["Pos2"])) {
$c=count($o->Opts["Pos2"]);
for ($i = 0; $i < $c; $i++) {
$notepitchObj = new NWC2NotePitchPos($o->Opts["Pos2"][$i]);
$notepitchObj->Position += $shiftPos;
$o->Opts["Pos2"][$i] = $notepitchObj->ReconstructClipText();
}
}
echo $o->ReconstructClipText()."\n";
}
} else {
echo $item;
}
} else {
echo $item;
}
}
}

echo NWC2_ENDCLIP."\n";
exit(NWC2RC_SUCCESS);
?>

All feedback welcome.

Bryan
9
General Discussion / Re: abc to nwc conversion again
I have returned!

I have, in response to interest on various internet lists, reinstated the website at http://www.abacusmusic.co.uk/ from where abc2nwc can be downloaded. It is now rather out of date and only works on V 1.75 Uncompressed files. Unfortunately, the V 1.75 file that can be exported from V 2 is compressed.

I'm looking into updating it using the .nwctxt files as input. In the meantime, I have run up a User Tool to generate ABC. See thread "Noteworthy to ABC (ABCgen)" on the User Tools list.

Bryan
10
User Tools / 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