1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/hubzilla_ynh.git synced 2024-09-03 19:26:21 +02:00
hubzilla_ynh/sources/addons/chords/chord-generator.cpp

1134 lines
25 KiB
C++
Raw Normal View History

//
// I have been messing around with this program now for a couple weeks
// and thought it might be useful to someone. Given a chord by name,
// it generates all possible ways to play that chord on a guitar and
// scores them based on things like finger span, root as bass note,
// number of open strings, etc (see below). Then it prints the top
// 50 it found (or more, you can set it). The program is pretty
// configurable if you can stand to read the stuff at the top where
// all the #define's are. Currently it prints out the score, and the
// pieces that made up the score...you may want to get rid of the
// extra info, but I found it interesting.
//
// It generates some wild chords and some interesting versions that
// I have NEVER seen before. Probably a great program to find inversions
// and stuff (especially if you lower the score given for having a root
// note 1st). The program could easily be modified to do Drop D tuning
// or any other alternate tuning, and I think it could do other instruments
// without much change, but I have not tried.
//
// I have been having fun playing with this, if you make a changes or
// fixes I would appreciate a copy. Other than that, this is public
// domain, have a party. Oh yeah, the code is C++...
//
// Thanks,
// Rick Eesley
// re@warren.mentorg.com
//
//
//
// Chords can be built like: | = seperate fields, [ ... ] = range of values
// <> = nothing
//
// [<--optional--->]
// [<--repeating-->]
// [A...G] | <> | <> | <> | # |
// | # | min | maj | |
// | b | m | add | |
// | | sus2 | aug | |
// | | sus4 | dim | |
// | | dim | + | |
// | | aug | - | |
// | | | # |
// | | | b |
// | | | / |
//
// Legal chord names: A A7 Amaj7 Amaj9 Ammaj7 Aadd4 Asus2Add4 E7b13b11 ...
// Does not do: C/G which is a c chord with a g root, just find a c
// chord and pick out a g root you like for those...
// Does not do: E5 (that's not a chord, just 2 notes)
//
//
#undef DEBUG
int lefty = 0;
//////////////////////////////////////////////////////////////////////
// Scoring a chord is influenced by these multipliers, change them around
// to your own preferences
//////////////////////////////////////////////////////////////////////
//
// Score for where this lands on the fretboard (Lower is better)
// score += (15 - AverageFret) * POSITION_SCORE;
#define POSITION_SCORE 20
// Score for minimal span (ie: chord covering from fret 2 to fret 4 has
// a span of 2. Open strings do NOT count in span, this is a measure
// of whether a chord is playable
// The maximum span allowed is set by the #define MAXSPAN
// score += (MAXSPAN - span) * SPAN_SCORE;
#define SPAN_SCORE 12
// This score is for total Span (ie: includes open strings, which span
// does not.
// score += (15 - tspan) * TSPAN_SCORE;
#define TSPAN_SCORE 3
// This score is for number of open strings (I like them).
// score += numberOfOpens * OPENS_SCORE
#define OPENS_SCORE 10
// This score multiplier is the score to add if the most bass string
// is the root note
// score += ROOT_SCORE
#define ROOT_SCORE 50
// This score multipier is used to penalize for adjacent notes
// score += ADJ_SCORE * (5-adjNotes)
// THe five is the max number of adjacent strings possible (duh...)
#define ADJ_SCORE 9
// This is the maximum finger reach, if this is bumped up to five or
// more you get a zillion more fingers (mainly 'cause 5 takes you to
// the notes on the next string...so leave it probably
#define MAXSPAN 4
// This is number of top scores to keep, something < 20 leaves out
// too much, 100 is a lot to look at...but I am going with it...
#define CHORDSTACK 250
//
// These are different types of scores, NUMSCORETYPES MUST be set to the
// number of these types, so if any are added change it TOO!
// Add any new scores onto the end, the total MUST be the 0th element
//
#define NUMSCORETYPES 7
#define SCORE_TOTAL 0
#define SCORE_SPAN 1
#define SCORE_TOTALSPAN 2
#define SCORE_OPENSTRINGS 3
#define SCORE_FIRSTROOT 4
#define SCORE_LOWONNECK 5
#define SCORE_ADJNOTES 6
// Just in case someone wants to port this to banjo or mandolin or something
#define NUM_STRINGS 6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* A A# B C C# D D# E F F# G G# */
/* A Bb B C Db D Eb E F Gb G Ab */
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
/* STRINGS ARE: E=0, A=1, D=2, G=3, B=4, E=5 IN ORDER */
// This can be reset for alternate tunings, this is EADGBE tuning
// here:
int openStrings[NUM_STRINGS] = { 7, 0, 5, 10, 2, 7 };
static char *strNotes[] = { "A ", "A#", "B ", "C ", "C#", "D ",
"D#", "E ", "F ", "F#", "G ", "G#" };
//
// This class contains a decode chord, and can take a string and turn
// it into a chord. A chord is a triad or greater here. The code is
// decoded from a string into notes in the c array (notes: are A=0, A#=1,
// and so on. The longest chord you can possibly have is 12 notes which
// would be every note in an octave, since chords are typical 3 to 5
// notes, remaining notes in the c[] array are set to -1
//
class Chord
{
public:
// String set to last error
char errorStr[64];
// Notes that are in the chord -1 should be ignored
int notes[12];
// NOtes that are optional have a 1, otherwise a zero
int optional[12];
// ------------------ MEMBER FUNCTIONS ----------------------------
// Clears last chord
void clear();
// Decodes input string into notes[] array, return error string
int findChord(char *s);
// Print last error message from chord parse
void printError();
// Prints out notes[] array to screen
void print(char *chordName);
// Is the note note in the chord
int inChord(int note);
// Is this chord covered by the array of notes (ie: Does the
// array contain all the notes of the chord
int covered(int *noteArray);
// Return the root note of the chord
int getRoot() { return notes[0]; }
// Given a chord string, return the note that starts it (and recognize
// sharps and flats (b and #)
int get_base(char *s);
// Get a note offset from another...
int note_offset(int base, int offset) {
if((! base) && (offset == (-1)))
return(11);
return ((base + offset) % 12);
}
} ;
//
// This class holds a fingering for a chord, as well as a score for that
// fingering. This class also keeps the CHORDSTACK (ie: 100) best version
// of that chord to print out in sorted order (best score 1st).
//
class Fretboard
{
public:
// Score of current chord, held in an array so we can track the
// components of the score (see the SCORE_ defines in the begining
// of this file
int score[NUMSCORETYPES];
// Fretboard of the current chord, fretboard[0] is the low (bass) E
// string. A fretboard value of 0 is an open string, -1 is an
// X'ed out string (not strung)
int fretboard[NUM_STRINGS];
// Notes of the current fretboard fingering for a chord
int notes[NUM_STRINGS];
// The best fret layouts so far based on score
int bestFrets[CHORDSTACK][NUM_STRINGS];
// The best fret layout note sets so far based on score
int bestNotes[CHORDSTACK][NUM_STRINGS];
// The best scores
int bestScores[CHORDSTACK][NUMSCORETYPES];
// Keep track of stack sDepth to speed it up!
int sDepth;
// ------------------ MEMBER FUNCTIONS ----------------------------
// Construct one
Fretboard();
// Given a chord (and the current fretboard state) score this doggie
// and leave the score value in score
void getScore(Chord &chord);
// Print the current Fretboard state (not the stack)
void print();
// Print the fretboard stack
void printStack();
// Iterate over different fretboard variations for a chord
void iterate(Chord &chord);
// Take the current fretboard state and put it into the stack
void addToBest();
// Get the span of the current chord, excluding open string
int getSpan();
// Get the span of the current chord, INCLUDING open string
int getTotalSpan();
};
//
// Before building a chord, clear the notes and optional arrays
//
void
Chord::clear()
{
for (int i = 0; i < 12; i++)
{
notes[i] = -1;
optional[i] = 0;
}
}
//
// Print out the last error string
//
void
Chord::printError()
{
printf("Error: %s\n", errorStr);
}
//
// I dunno, our C++ compiler at work did not have strupr, so heres mine
//
void
myStrupr(char *s)
{
while (*s)
{
if (islower(*s))
*s = toupper(*s);
s++;
}
}
//
// Decodes input string into notes[] array, return error string
// always: 0 = root, 1 = 3rd, 2 = 5th
// Also sets the optional array in parallel with the notes[]
//
int
Chord::findChord(char *s)
{
clear();
// up case the string
myStrupr(s);
// DECODE ROOT NOTE : A - G
notes[0] = get_base(s);
s++;
// CHECK FOR SHARP OR FLAT ROOT NOTE
if (*s == '#') s++;
if (*s == 'B') s++;
// MODIFY THE ROOT BY M, MIN, SUS2, SUS4, or diminished
if (!strncmp(s, "MIN", 3 ))
{
notes[1] = note_offset(notes[0], 3);
s += 3;
optional[2] = 1;
}
else if (!strncmp(s, "MAJ", 3))
{
// Do nothing, but stops program from seeing the
// first m in maj as a minor (see next line)...so give a normal 3rd
notes[1] = note_offset(notes[0], 4);
optional[2] = 1;
}
else if (!strncmp(s, "M", 1))
{
notes[1] = note_offset(notes[0], 3);
s += 1;
optional[2] = 1;
}
else if (!strncmp(s, "SUS", 1))
{
s += 3; // go past sus
if (*s == '2')
notes[1] = note_offset(notes[0], 2);
else if (*s == '4')
notes[1] = note_offset(notes[0], 5);
else
{
strcpy(errorStr, "sus must be followed by 2 or 4");
return 1;
}
s++; // Go past 2 or 4
optional[2] = 1;
}
else if ((!strncmp(s, "DIM", 3 )) && (!isdigit(s[3])))
{
// If it is diminished, just return (no other stuff allowed)/
notes[1] = note_offset(notes[0], 3);
notes[2] = note_offset(notes[0], 6);
notes[3] = note_offset(notes[0], 9);
return 0;
}
else if ((!strncmp(s, "AUG", 3 )) && (!isdigit(s[3])))
{
// If it is diminished, just return (no other stuff allowed)/
notes[1] = note_offset(notes[0], 4);
notes[2] = note_offset(notes[0], 8);
return 0;
}
else
{
notes[1] = note_offset(notes[0], 4);
// optional[1] = 1;
// optional[2] = 1;
}
notes[2] = note_offset(notes[0], 7);
// At this point, the 1,3,5 triad or variant is built, now add onto
// it until the string end is reached...
// Next note to add is index = 3...
int index = 3;
enum homeboy { NORMAL, MAJ, ADD, AUG, DIM } mtype ;
char lbuf[10];
while (*s)
{
// FIrst, check the mtype of modifier, ie: Aug, Maj, etc...
mtype = NORMAL;
if (!strncmp(s, "MAJ", 3))
{
mtype = MAJ;
s += 3;
}
else if (!strncmp(s, "ADD", 3))
{
mtype = ADD;
s += 3;
}
else if (!strncmp(s, "AUG", 3))
{
mtype = AUG ;
s += 3;
}
else if (!strncmp(s, "DIM", 3))
{
mtype = DIM;
s += 3;
}
else if ( *s == '+' )
{
mtype = AUG;
s += 1;
}
else if ( *s == '-' )
{
mtype = DIM;
s += 1;
}
else if ( *s == '#' )
{
mtype = AUG;
s += 1;
}
else if ( *s == 'B' )
{
mtype = DIM;
s += 1;
}
else if ( *s == '/' )
{
mtype = ADD;
s += 1;
}
// Now find the number...
if (isdigit(*s))
{
lbuf[0] = *s++;
lbuf[1] = '\0';
}
else
{
sprintf(errorStr, "Expecting number, got %s", s);
return 1;
}
// 2nd digit?
if (isdigit(*s))
{
lbuf[1] = *s++;
lbuf[2] = '\0';
}
int number = atoi(lbuf);
switch (number)
{
case 7 :
notes[index] = note_offset(notes[0], 10);
break;
case 9 :
notes[index] = note_offset(notes[0], 2);
// put the 7th in 2nd so it can be maj'ed if need be...
if ((mtype == NORMAL) || (mtype == MAJ))
{
index++;
notes[index] = note_offset(notes[0], 10);
optional[index] = 1; // 7th is optional, unless it is maj!
}
break;
case 11 :
notes[index] = note_offset(notes[0], 5);
// put the 7th in 2nd so it can be maj'ed if need be...
if ((mtype == NORMAL) || (mtype == MAJ))
{
index++;
notes[index] = note_offset(notes[0], 10);
optional[index] = 1; // 7th is optional, unless it is maj!
}
break;
case 13 :
notes[index] = note_offset(notes[0], 9);
index++;
notes[index] = note_offset(notes[0], 5);
optional[index] = 1; // 7th is optional, unless it is maj!
index++;
notes[index] = note_offset(notes[0], 2);
optional[index] = 1; // 7th is optional, unless it is maj!
// put the 7th in 2nd so it can be maj'ed if need be...
if ((mtype == NORMAL) || (mtype == MAJ))
{
index++;
notes[index] = note_offset(notes[0], 10);
optional[index] = 1; // 7th is optional, unless it is maj!
}
break;
case 2:
notes[index] = note_offset(notes[0], 2);
break;
case 4:
notes[index] = note_offset(notes[0], 5);
break;
case 6:
notes[index] = note_offset(notes[0], 9);
break;
case 5:
notes[index] = note_offset(notes[0], 7);
break;
default:
sprintf(errorStr, "Cannot do number: %d\n", number);
return 1;
}
switch (mtype)
{
case DIM:
notes[index] = note_offset(notes[index], -1);
break;
case MAJ:
// It is a major, so not optional
optional[index] = 0;
case AUG :
notes[index] = note_offset(notes[index], 1);
break;
case NORMAL:
case ADD:
break;
default:
break;
}
index++;
}
return 0;
}
//
// Print out chord by name
//
void
Chord::print(char *cname)
{
printf("Notes for chord '%s': ", cname);
for (int i = 0; i < 12; i++)
{
if (notes[i] != -1)
printf("%s ", strNotes[notes[i]]);
}
printf("\n\n");
}
//
// Are all the notes in this chord covered by the notes in the
// noteArray, it is not necessary to cover the notes in the optional
// array of the chord
//
int
Chord::covered(int *noteArray)
{
// noteArray is an array of notes this chord has, it is NUM_STRINGS notes
// long (like a guitar fretboard dude...unused notes may be set
// to -1 (which wont compare since -1 is tossed...
for (int i = 0; i < 12; i++)
{
if (notes[i] != -1)
{
int gotIt = 0;
for (int j = 0; j < NUM_STRINGS; j++)
{
if (noteArray[j] == notes[i])
{
gotIt = 1;
break;
}
}
// If it was not found, and it is NOT optional, then it is
// not covered
if ((gotIt == 0) && (optional[i] == 0))
return 0;
}
}
return 1;
}
//
// Is the given note in the chord
//
int
Chord::inChord(int note)
{
for (int i = 0; i < 12; i++)
{
// Check if we are off the end of the notes set
if (notes[i] == -1)
return 0;
// Check if the note was found
if (note == notes[i])
return 1;
}
// Did not find out, return 0
return 0;
}
//
// Given a chord string, pick off the root (either C or C# or Cb)...and
// return that integer value (A = 0)
//
int
Chord::get_base(char *s)
{
static int halfsteps[] = { 0, 2, 3, 5, 7, 8, 10 };
if ((*s < 'A') || (*s > 'G'))
return 0;
if (s[1] == '#')
return ( note_offset(halfsteps[s[0] - 'A'], 1));
else if (s[1] == 'B')
return ( note_offset(halfsteps[s[0] - 'A'], -1));
else
return ( halfsteps[s[0] - 'A']);
}
//
// Print out the current fretboard
//
void
Fretboard::print()
{
printf("SCORE: %3d ", score[SCORE_TOTAL]);
printf(
" SPN: %2d TSPN: %2d OS: %2d ROOT: %2d LOW %2d ADJ %2d",
score[SCORE_SPAN], score[SCORE_TOTALSPAN], score[SCORE_OPENSTRINGS],
score[SCORE_FIRSTROOT], score[SCORE_LOWONNECK],
score[SCORE_ADJNOTES]);
printf(" FB: ");
for (int i = 0; i < NUM_STRINGS; i++)
{
if (fretboard[i] != -1)
printf(" %2d", fretboard[i]);
else
printf(" X");
}
printf(" NT: ");
for (int i = 0; i < NUM_STRINGS; i++)
if (notes[i] != -1)
printf(" %s", strNotes[notes[i]]);
else
printf(" X ");
printf("\n");
}
//
// Construct a fretboard -- reset to the openStrings, clear the stack
// and reset all the bestScores to -1
//
Fretboard::Fretboard()
{
sDepth = 0;
score[0] = 0;
for (int i = 0; i < NUM_STRINGS; i++)
{
notes[i] = openStrings[i];
fretboard[i] = 0;
}
for (int i = 0; i < CHORDSTACK; i++)
{
bestScores[i][0] = -1;
}
}
//
// Get the span of this chord, don't count open strings
//
int
Fretboard::getSpan()
{
int min = 100, max = 0;
for (int i = 0; i < NUM_STRINGS; i++)
{
// Dont count X strings or open strings
if (fretboard[i] <= 0)
continue;
if (fretboard[i] > max) max = fretboard[i];
if (fretboard[i] < min) min = fretboard[i];
}
if (min == 100)
// All open strings, took awhile to catch this bug
return 0;
else
return (max - min);
}
//
// Get the span of this chord, DO count open strings
//
int
Fretboard::getTotalSpan()
{
int min = 100, max = 0;
for (int i = 0; i < NUM_STRINGS; i++)
{
// Dont count X strings
if (fretboard[i] < 0)
continue;
if (fretboard[i] > max) max = fretboard[i];
if (fretboard[i] < min) min = fretboard[i];
}
if (min == -1)
min = 0;
return (max - min);
}
//
// Add this chord to the best (if there is room in the stack)
//
void
Fretboard::addToBest()
{
// CHORDSTACK is the sDepth of keepers...
#ifdef DEBUG
printf("ATB: ");
this->print();
#endif
int i;
// NOTE: at the start, bestScores is full of -1's, so any reall
// real score will be better (worst score is 0)
for (i = 0; i < sDepth; i++)
{
if (score[0] > bestScores[i][0])
break;
}
// If score was not better than any in the stack just return
if (i >= CHORDSTACK)
return ;
// MOve down old guys to make room for the new guy
for (int j = CHORDSTACK - 1; j >= i; j--)
{
for (int q = 0; q < NUM_STRINGS; q++)
{
bestFrets[j][q] = bestFrets[j - 1][q];
bestNotes[j][q] = bestNotes[j - 1][q];
}
for (int q = 0; q < NUMSCORETYPES; q++)
bestScores[j][q] = bestScores[j - 1][q];
}
for (int q = 0; q < NUM_STRINGS; q++)
{
bestFrets[i][q] = fretboard[q];
bestNotes[i][q] = notes[q];
}
for (int q = 0; q < NUMSCORETYPES; q++)
bestScores[i][q] = score[q];
sDepth++;
if (sDepth > CHORDSTACK)
sDepth--;
}
//
// Print out the stack to the screen
//
void
Fretboard::printStack()
{
static char *strNotes[] = { "A ", "A#", "B ", "C ", "C#", "D ",
"D#", "E ", "F ", "F#", "G ", "G#" };
for (int f = 0; f < sDepth; f++)
{
printf("\n\n ");
if(lefty) {
for (int i = NUM_STRINGS - 1; i >= 0; i--)
if (bestNotes[f][i] != -1)
printf(" %s", strNotes[bestNotes[f][i]]);
else
printf(" X ");
}
else {
for (int i = 0; i < NUM_STRINGS; i++)
if (bestNotes[f][i] != -1)
printf(" %s", strNotes[bestNotes[f][i]]);
else
printf(" X ");
}
printf("\n");
if(lefty) {
for (int i = NUM_STRINGS - 1; i >= 0; i--)
if (bestFrets[f][i] != -1)
printf(" %2d", bestFrets[f][i]);
else
printf(" X");
}
else {
for (int i = 0; i < NUM_STRINGS; i++)
if (bestFrets[f][i] != -1)
printf(" %2d", bestFrets[f][i]);
else
printf(" X");
}
printf("\n\n");
int highest = 0;
for(int i = 0; i < NUM_STRINGS; i++)
if(bestFrets[f][i] > highest)
highest = bestFrets[f][i];
printf("\n");
for(int i = 0; i <= (highest + 1); i ++) {
if(lefty) {
for (int x = NUM_STRINGS-1; x >= 0; x--) {
if(i == 0) {
if(bestFrets[f][x] == -1)
printf(" X");
else
if(bestFrets[f][x] == 0)
printf(" 0");
else
printf(" ");
}
else {
if(bestFrets[f][x] == i)
printf(" *");
else
printf(" |");
}
}
}
else {
for (int x = 0; x < NUM_STRINGS; x++) {
if(i == 0) {
if(bestFrets[f][x] == -1)
printf(" X");
else
if(bestFrets[f][x] == 0)
printf(" 0");
else
printf(" ");
}
else {
if(bestFrets[f][x] == i)
printf(" *");
else
printf(" |");
}
}
}
printf("\n ---------------- %2d\n",i);
}
}
}
//
// Get the score for this chord
//
void
Fretboard::getScore(Chord &chord)
{
// First, points for small span (excluding opens)
score[SCORE_SPAN] = (MAXSPAN - getSpan()) * SPAN_SCORE;
// Then, points for small total span
score[SCORE_TOTALSPAN] = (15 - getTotalSpan()) * 3;
score[SCORE_OPENSTRINGS] = 0;
// Points for open strings
for (int i = 0; i < NUM_STRINGS; i++)
{
if (fretboard[i] == 0)
{
score[SCORE_OPENSTRINGS] += OPENS_SCORE;
}
}
// Points for first string being the root ...
score[SCORE_FIRSTROOT] = 0;
int i;
for (i = 0; (fretboard[i] == -1) && (i < NUM_STRINGS) ; i++)
;
if (notes[i] == chord.getRoot())
{
score[SCORE_FIRSTROOT] = ROOT_SCORE;
}
// Points for being low on the neck...
int sum = 0, cnt = 0;
for (i = 0; i < NUM_STRINGS; i++)
{
// Don't count X strings or open strings
if (fretboard[i] > 0)
{
sum += fretboard[i];
cnt++;
}
}
if (cnt)
score[SCORE_LOWONNECK] = (int)(15 - ((double) sum / (double) cnt))
* POSITION_SCORE;
else
score[SCORE_LOWONNECK] = 15 * POSITION_SCORE;
int adjNotes = 0;
for (i = 0; i < 5; i++)
{
if ((notes[i] != -1) && (notes[i] == notes[i + 1]))
adjNotes++;
}
score[SCORE_ADJNOTES] = (ADJ_SCORE * (5 - adjNotes));
// FInally, total up the score
score[SCORE_TOTAL] = 0;
for (i = 1; i < NUMSCORETYPES; i++)
score[SCORE_TOTAL] += score[i];
}
//
// Iterate over all fretboard config's for this chord, call addToBest
// with any good ones (ie: < span, etc etc...)
//
void
Fretboard::iterate(Chord &chord)
{
int string = 0;
// Start notes setup, increment up the neck for each string until
// you find a note that is in this chord (may be an open note)
for (int i = 0; i < NUM_STRINGS; i++)
{
while (! chord.inChord(notes[i]))
{
fretboard[i]++;
notes[i] = ( notes[i] + 1 ) % 12;
}
}
// Back up the first note one...so the loop will work
fretboard[0] = -1;
// While we are still on the fretboard!
while (string < NUM_STRINGS)
{
// increment the current string
fretboard[string]++;
if (fretboard[string] == 0)
notes[string] = openStrings[string];
else
notes[string] = ( notes[string] + 1 ) % 12;
while (! chord.inChord(notes[string]))
{
fretboard[string]++;
notes[string] = ( notes[string] + 1 ) % 12;
}
if (fretboard[string] > 15)
{
// Before turning over the 3rd string from the bass, try
// to make a chord with the bass string, and 2nd from
// bass string X'ed out...(ie: set to -1)
if (string == 0)
{
notes[0] = fretboard[0] = -1;
int span = getSpan();
if ((span < MAXSPAN) && chord.covered(notes))
{
getScore(chord);
addToBest();
}
}
if (string == 1)
{
int store = notes[0];
int fstore = fretboard[0];
notes[1] = fretboard[1] = -1;
notes[0] = fretboard[0] = -1;
int span = getSpan();
if ((span < MAXSPAN) && chord.covered(notes))
{
getScore(chord);
addToBest();
}
// Restore the notes you X'ed out
notes[0] = store;
fretboard[0] = fstore;
}
fretboard[string] = 0;
notes[string] = openStrings[string];
while (! chord.inChord(notes[string]))
{
fretboard[string]++;
notes[string] = chord.note_offset(notes[string], 1);
}
string++;
continue;
}
#ifdef DEBUG
printf("TRY: "); this->print();
#endif
string = 0;
int span = getSpan();
if (span >= MAXSPAN)
{
#ifdef DEBUG
printf("Rejected for span\n");
#endif
continue;
}
if (!chord.covered(notes))
{
#ifdef DEBUG
printf("Rejected for coverage\n");
#endif
continue;
}
getScore(chord);
addToBest();
}
}
//
// uh, main
//
int main(int argc, char **argv)
{
char buf[256], buf2[256];
if(argc > 1)
{
strcpy(buf, argv[1]);
if(argc > 3) {
if(! strcmp(argv[3],"lefty")) {
lefty = 1;
}
}
if(argc > 2) {
if(! strcmp(argv[2],"dadgad")) {
openStrings[0] = 5;
openStrings[1] = 0;
openStrings[2] = 5;
openStrings[3] = 10;
openStrings[4] = 0;
openStrings[5] = 5;
}
if(! strcmp(argv[2],"openg")) {
openStrings[0] = 5;
openStrings[1] = 10;
openStrings[2] = 5;
openStrings[3] = 10;
openStrings[4] = 2;
openStrings[5] = 5;
}
if(! strcmp(argv[2],"opene")) {
openStrings[0] = 7;
openStrings[1] = 2;
openStrings[2] = 7;
openStrings[3] = 11;
openStrings[4] = 2;
openStrings[5] = 7;
}
if(! strcmp(argv[2],"lefty")) {
lefty = 1;
}
}
// Allocate it for DOS/WINDOWS, to avoid stack overflow (weak)
Fretboard *fb = new Fretboard; ;
Chord chord;
// findChord upppercases the input string, so save a copy
strcpy(buf2, buf);
if (chord.findChord(buf))
{
chord.printError();
}
else {
chord.print(buf2);
fb->iterate(chord);
fb->printStack();
}
delete fb;
}
return 0;
}