2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
/* Copyright (C) 2008 Jonathan Moore Liles */
|
|
|
|
/* */
|
|
|
|
/* This program is free software; you can redistribute it and/or modify it */
|
|
|
|
/* under the terms of the GNU General Public License as published by the */
|
|
|
|
/* Free Software Foundation; either version 2 of the License, or (at your */
|
|
|
|
/* option) any later version. */
|
|
|
|
/* */
|
|
|
|
/* This program is distributed in the hope that it will be useful, but WITHOUT */
|
|
|
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
|
|
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
|
|
|
|
/* more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public License along */
|
|
|
|
/* with This program; see the file COPYING. If not,write to the Free Software */
|
|
|
|
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
|
|
|
#include "scale.H"
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#include "stdlib.h"
|
|
|
|
|
|
|
|
/* Define some scales. These don't really need to be stored on
|
|
|
|
disk. Scales don't change that often. */
|
|
|
|
|
|
|
|
const char *Scale::chromatic_names[] =
|
|
|
|
/* { "A", */
|
|
|
|
/* "A#/Bb", */
|
|
|
|
/* "B", */
|
|
|
|
/* "C", */
|
|
|
|
/* "C#/Db", */
|
|
|
|
/* "D", */
|
|
|
|
/* "D#/Eb", */
|
|
|
|
/* "E", */
|
|
|
|
/* "F", */
|
|
|
|
/* "F#/Gb", */
|
|
|
|
/* "G", */
|
|
|
|
/* "G#/Ab" }; */
|
|
|
|
|
|
|
|
/* { "C", */
|
|
|
|
/* "C#/Db", */
|
|
|
|
/* "D", */
|
|
|
|
/* "D#/Eb", */
|
|
|
|
/* "E", */
|
|
|
|
/* "F", */
|
|
|
|
/* "F#/Gb", */
|
|
|
|
/* "G", */
|
|
|
|
/* "G#/Ab", */
|
|
|
|
/* "A", */
|
|
|
|
/* "A#/Bb", */
|
|
|
|
/* "B" }; */
|
|
|
|
|
|
|
|
|
|
|
|
{ "C",
|
|
|
|
"C#",
|
|
|
|
"D",
|
|
|
|
"D#",
|
|
|
|
"E",
|
|
|
|
"F",
|
|
|
|
"F#",
|
|
|
|
"G",
|
|
|
|
"G#",
|
|
|
|
"A",
|
|
|
|
"A#",
|
|
|
|
"B" };
|
|
|
|
|
|
|
|
|
|
|
|
Scale Scale::builtin_scales[] = {
|
|
|
|
{ "Major",
|
|
|
|
7,
|
|
|
|
{ 0, 2, 4, 5, 7, 9, 11 } },
|
|
|
|
{ "Natural Minor",
|
|
|
|
7,
|
|
|
|
{ 0, 2, 3, 5, 7, 8, 10 } },
|
|
|
|
{ "Harmonic Minor",
|
|
|
|
7,
|
|
|
|
{ 0, 2, 3, 5, 7, 8, 11 } },
|
|
|
|
{ "Melodic Minor",
|
|
|
|
7,
|
|
|
|
{ 0, 2, 3, 5, 7, 9, 11 } },
|
|
|
|
{ "Major Pentatonic",
|
|
|
|
5,
|
|
|
|
{ 0, 2, 4, 7, 9 } },
|
|
|
|
{ "Minor Pentatonic",
|
|
|
|
5,
|
|
|
|
{ 0, 3, 5, 7, 10 } },
|
|
|
|
{ "Chromatic",
|
|
|
|
12,
|
|
|
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* const Scale builtin_chords[] = { */
|
|
|
|
/* { "Major Triad", */
|
|
|
|
/* { 0, 4, 7, -1 } }, */
|
|
|
|
/* { "Major Sixth", */
|
|
|
|
/* { 0, 4, 7, 9, -1 } }, */
|
|
|
|
/* { "Major Seventh", */
|
|
|
|
/* { 0, 4, 7, 11, -1 } }, */
|
|
|
|
/* { "Major Ninth", */
|
|
|
|
/* { 0, 4, 7, 11, 14, -1 } }, */
|
|
|
|
/* { "Major 6/9", */
|
|
|
|
/* { 0, 4, 7, 9, 14, -1 } }, */
|
|
|
|
/* { "Major Eleventh", */
|
|
|
|
/* { 0, 4, 7, 11, 14, 17, -1 } }, */
|
|
|
|
/* { "Major Thirteenth", */
|
|
|
|
/* { 0, 4, 7, 11, 14, 17, 21, -1 } }, */
|
|
|
|
|
|
|
|
/* { "Minor Triad", */
|
|
|
|
/* { 0, 3, 7, -1 } }, */
|
|
|
|
/* { "Minor Sixth", */
|
|
|
|
/* { 0, 3, 7, 9, -1 } }, */
|
|
|
|
/* { "Minor Seventh", */
|
|
|
|
/* { 0, 3, 7, 10, -1 } }, */
|
|
|
|
/* { "Minor Ninth", */
|
|
|
|
/* { 0, 3, 7, 10, 14, -1 } }, */
|
|
|
|
/* { "Minor 6/9", */
|
|
|
|
/* { 0, 3, 7, 9, 14, -1 } }, */
|
|
|
|
/* { "Minor Eleventh", */
|
|
|
|
/* { 0, 3, 7, 10, 14, 17, -1 } }, */
|
|
|
|
/* { "Minor Thirteenth", */
|
|
|
|
/* { 0, 3, 7, 10, 14, 17, 21, -1 } }, */
|
|
|
|
|
|
|
|
/* { "Augmented Triad", */
|
|
|
|
/* { 0, 4, 8, -1 } }, */
|
|
|
|
/* { "Diminished Triad", */
|
|
|
|
/* { 0, 3, 6, -1 } } */
|
|
|
|
/* }; */
|
|
|
|
|
|
|
|
|
|
|
|
/* "Opens" a scale for compatibility with Instrument class */
|
|
|
|
Scale *
|
|
|
|
Scale::open ( const char *name )
|
|
|
|
{
|
|
|
|
for ( int i = elementsof( builtin_scales ) - 1; i >= 0; --i )
|
|
|
|
if ( 0 == strcmp( name, builtin_scales[i]._name ) )
|
|
|
|
return &builtin_scales[i];
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns a list of available scales */
|
|
|
|
char **
|
|
|
|
Scale::listing ( void )
|
|
|
|
{
|
|
|
|
char **sa;
|
|
|
|
|
|
|
|
int n = elementsof( builtin_scales );
|
|
|
|
|
|
|
|
sa = (char **)malloc( sizeof ( char * ) * ( n + 1 ) );
|
|
|
|
sa[n] = NULL;
|
|
|
|
|
|
|
|
while ( n-- )
|
|
|
|
sa[n] = strdup( builtin_scales[n]._name );
|
|
|
|
|
|
|
|
return sa;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
Scale::chromatic_name ( int n )
|
|
|
|
{
|
|
|
|
return chromatic_names[ n % 12 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Scale::octave ( int n )
|
|
|
|
{
|
|
|
|
return n / 12;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Scale::_degree ( int k, int n ) const
|
|
|
|
{
|
|
|
|
return k + _degrees[ n % _notes ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* translate NOTE event. Behavior is undefined for other event types */
|
2008-02-13 20:42:00 +01:00
|
|
|
bool
|
2007-12-18 05:09:02 +01:00
|
|
|
Scale::translate ( int k, midievent *e ) const
|
|
|
|
{
|
2008-02-13 20:42:00 +01:00
|
|
|
if ( ! note_name( k, e->note() ) )
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return true;
|
2007-12-18 05:09:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
Scale::note_name ( int k, int n ) const
|
|
|
|
{
|
|
|
|
/* all the magic is here */
|
|
|
|
|
|
|
|
n %= 12;
|
|
|
|
|
|
|
|
// FIXME: searching is not efficient!
|
|
|
|
for ( int i = _notes; i-- ; )
|
|
|
|
if ( n == (_degrees[ i ] + k) % 12 )
|
|
|
|
return chromatic_names[ n ];
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
Scale::name ( void ) const
|
|
|
|
{
|
|
|
|
return _name;
|
|
|
|
}
|