Xref: utzoo rec.music.makers:6223 comp.music:578 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!srhqla!quad1!ttidca!philabs!fcg From: fcg@philabs.philips.com (Frank C. Guida) Newsgroups: rec.music.makers,comp.music Subject: Guitarist's Helper Keywords: fretboard diagrams Message-ID: <73020@philabs.Philips.Com> Date: 9 Jan 90 19:23:07 GMT Sender: news@philabs.Philips.Com Distribution: na Organization: Philips Laboratories, Briarcliff Manor, NY Lines: 364 Fellow guitarists/bassists: I wrote a program that prints a guitar fretboard diagram, and labels notes or patterns according command-line args. I found it helpful in learning and scales and patterns. The user can specify scale notes directly, or supply a root and formula for a scale. Positions on the fretboard diagram may be labled with a user-defined character if desired (this is good for learning patterns as opposed to actual note names). Here's a sample output: synapse /betty/b3/fcg 17> fretbd -i G# 2 2 1 2 2 2 Scale = G# A# C C# D# F G + + + + + + + + + + -||-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---| -||-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---| G||-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---| -||-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---| -||-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---| -||-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---| This is my first posting of code to the net; any comments or suggestions are welcome. Please use e-mail replies where appropriate. - Yours truly /* ********************************************************************** */ /* * FILE: fretbd.2.c * AUTHOR: Frank C. Guida Philips Laboratories * (fcg@philabs.philips.com) Briarcliff Manor, NY 10510 * * DATE: Fri Dec 22 10:49:29 1989 * * Please acknowledge the author in any reproduction or modification. * * SYNOPSIS: fretbd [-h] [-s] [-m char] * [-i root interval_list] | [-n note_list] * * DESCRIPTION: fretbd prints a guitar fretboard (20 frets) * and labels notes according to the command-line * args. Notes may be entered in upper or lower * case; use b or # to indicate accidentals. * * OPTION SUMMARY: (no args): print blank fretboard. * -h: print this message. * -s: use sharps instead of flats as the * dflt_note_type (use with -i option). * -m: use char to mark note positions as * opposed to letter names. * -i: construct scale using specified root * and intervals (in half-steps). * -n: construct scale using specified notes. * * EXAMPLE: to print the F#maj scale - * host> fretbd -i F# 2 2 1 2 2 2 * */ /* ********************************************************************** */ #include #include #include #define HELP_MESSAGE "\ Use: fretbd [-h] [-s] [-m char] [-i root interval_list] | [-n note_list]\n\n\ Option Summary: (no args): print blank fretboard.\n\ -h: print this message.\n\ -s: use sharps instead of flats as the\n\ dflt_note_type (use with -i option).\n\ -m: use char to mark note positions as\n\ opposed to letter names.\n\ -i: construct scale using specified root\n\ and intervals (in half-steps).\n\ -n: construct scale using specified notes.\n" #define OP_HELP "-h" #define OP_SHARPS "-s" #define OP_POS_MARK "-m" #define OP_INTERVALS "-i" #define OP_NOTES "-n" #define NUM_FRETS 20 /* numbered 0-19 */ #define NUM_STRINGS 6 /* numbered 1-6 */ #define MAX_NOTES 12 #define FLATS 0 #define SHARPS 1 #define NECK_INDEX "\ + + + + + + +\ + + +\n" /* Basic macros */ #define streq(s1, s2) (strcmp(s1, s2) == 0) #define not_option(arg) !(streq(arg, OP_HELP) ||\ streq(arg, OP_SHARPS) ||\ streq(arg, OP_POS_MARK) ||\ streq(arg, OP_INTERVALS) ||\ streq(arg, OP_NOTES)) /* function declarations */ char *get_note(); short note_index(); void error(); void print_fretbd(); void print_note(); /* global variables */ static char *chrom[2][12] = { /* 1 2 3 4 5 6 7 */ {"C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B"}, /* 0 1 2 3 4 5 6 7 8 9 10 11 */ {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"} }; char pos_mark_char = '\0'; unsigned short note_type; unsigned short num_notes = 0; /* ********************************************************************** */ main( argc, argv ) int argc; char *argv[]; { char *scale[MAX_NOTES]; short note_idx; unsigned short a, i, interval; unsigned short dflt_note_type = FLATS; for( i=0; i < MAX_NOTES; i++ ) /* initialize scale array */ scale[i] = "-"; /* Parse and verify command-line args. Args are checked for * consistency with any associated option flag (i.e. if the -i option * is given, the following arg should be a valid note name, and * subsequent args should be valid intervals or a new option flag). */ for( a=1; a < argc; a++ ) { if( streq(argv[a], OP_HELP) ) error( "", "" ); /* not really an error */ else if( streq(argv[a], OP_SHARPS) ) dflt_note_type = SHARPS; else if( streq(argv[a], OP_POS_MARK) ) { if( (a+1 < argc) && not_option(argv[a+1]) ) sscanf( argv[++a], "%c", &pos_mark_char ); else error( "", "Specify one character for position mark." ); } else if( streq(argv[a], OP_INTERVALS) ) { i = 0; while( (a+1 < argc) && not_option(argv[a+1]) ) { if( i == 0 ) /* first arg to -i option should be name of root */ { /* convert case if needed */ if( islower(*(argv[++a])) ) *(argv[a]) = toupper( *(argv[a]) ); if( (note_idx = note_index(argv[a])) >= 0 ) /* valid note? */ { scale[i++] = chrom[note_type][note_idx]; /* if root is an accidental, the scale should be */ /* formed from the same note type, i.e. bs or #s */ switch( note_idx ) { case 1: case 3: case 6: case 8: case 10: /* accidentals */ dflt_note_type = note_type; } } else error( argv[a], "is not a valid note!" ); } else /* subsequent args to -i option should be intervals */ { if( sscanf( argv[++a], "%hu", &interval ) == 1 ) { /* determine new note_idx from last note_idx */ note_idx = note_index(scale[i-1]) + (short)interval; while( note_idx > 11 ) /* correct any overflow */ note_idx =- 12; scale[i++] = chrom[dflt_note_type][note_idx]; } else error( argv[a], "is not a valid interval!" ); } } num_notes = i; } else if( streq(argv[a], OP_NOTES) ) { i = 0; while( (a+1 < argc) && not_option(argv[a+1]) ) { /* convert case if needed */ if( islower(*(argv[++a])) ) *(argv[a]) = toupper( *(argv[a]) ); if( note_index(argv[a]) >= 0 ) /* valid note? */ scale[i++] = argv[a]; else error( argv[a], "is not a valid note!" ); } num_notes = i; } } /* end of argc loop */ /* print scale */ printf( "Scale =" ); for( i=0; i < num_notes; i++ ) printf( " %s", scale[i] ); printf( " \n" ); print_fretbd( scale ); exit(0); } /* ********************************************************************** */ void error( item, message ) char *item, *message; /* Print error message, help message, and exit. */ { fprintf( stderr," %s %s\n", item, message ); fprintf( stderr, HELP_MESSAGE ); exit(-1); } /* ********************************************************************** */ short note_index( note ) char *note; /* Returns the chromatic scale index of note and sets note_type * if note is an accidental; returns -1 if note is not a member * of the chromatic scale. */ { short i; for( i=0; i < 12; i++ ) { note_type = FLATS; if( streq(note, chrom[note_type][i]) ) return(i); note_type = SHARPS; if( streq(note, chrom[note_type][i]) ) return(i); } return(-1); } /* ********************************************************************** */ void print_fretbd( scale ) char *scale[]; /* Print fretboard, labeling notes in scale[]. */ { char *note; register unsigned short string, fret_idx, fret; printf( NECK_INDEX ); for( string=1; string <= NUM_STRINGS; string++ ) { switch( string ) { case 2: fret_idx = 11; break; /* B */ case 3: fret_idx = 7; break; /* G */ case 4: fret_idx = 2; break; /* D */ case 5: fret_idx = 9; break; /* A */ default: fret_idx = 4; break; /* E */ } for( fret=0; fret < NUM_FRETS; fret++ ) { note = get_note( fret_idx, scale ); print_note( note, fret ); fret_idx++; while( fret_idx > 11 ) fret_idx -= 12; } printf( "\n" ); } } /* ********************************************************************** */ char *get_note( fret_idx, scale ) unsigned short fret_idx; char *scale[]; /* Returns note if chrom[][fret_idx] is a member of scale[]; * returns "-" if chrom[][fret_idx] is not a member of scale[]. */ { register unsigned short i; for( i=0; i < num_notes; i++ ) { if( streq( scale[i], chrom[FLATS][fret_idx] ) || streq( scale[i], chrom[SHARPS][fret_idx] ) ) return( scale[i] ); } return( "-" ); } /* ********************************************************************** */ void print_note( note, fret ) char *note; unsigned short fret; /* Prints note or specified pos_mark_char, then proper fill chars. */ { if( streq( note, "-" ) || (pos_mark_char == '\0') ) { printf( "%s", note ); /* if note is a single-char string, print "-" */ if( (fret > 0) && (*(note + 1) == '\0') ) printf( "-" ); } else { printf( "%c", pos_mark_char ); if( fret > 0 ) printf( "-" ); } switch( fret ) /* print fret indicators */ { case 0: printf( "||-" ); return; case 19: printf( "|" ); return; default: printf( "|-" ); return; } } /* ******************************* END ********************************** */ ______________________________________________________________________ Frank C. Guida Philips Laboratories fcg@philabs.philips.com Autonomous Systems Dept. (914)-945-6246 Briarcliff Manor, NY 10510