]> git.donarmstrong.com Git - lilypond.git/blob - lily/scale.cc
Merge branch 'master' of carldsorensen@git.sv.gnu.org:/srv/git/lilypond into fret...
[lilypond.git] / lily / scale.cc
1 /* 
2   scale.cc -- implement Scale
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2006--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
7       2007--2008 Rune Zedeler
8       2008       Joe Neeman <joeneeman@gmail.com>
9 */
10
11 #include "scale.hh"
12
13 #include "ly-smobs.icc"
14
15 /*
16   todo: put string <-> pitch here too.
17
18 */
19 LY_DEFINE (ly_make_scale, "ly:make-scale",
20            1, 0, 0, (SCM steps),
21            "Create a scale."
22            "  The argument is a vector of rational numbers, each of which"
23            " represents the number of 200 cent tones of a pitch above the"
24            " tonic.")
25 {
26   bool type_ok = scm_is_vector (steps);
27
28   vector<Rational> tones; 
29   if (type_ok)
30     {
31       int len = scm_c_vector_length (steps);
32       for (int i = 0 ; i < len; i++)
33         {
34           SCM step = scm_c_vector_ref (steps, i);
35           type_ok = type_ok && scm_is_rational (step);
36           if (type_ok)
37             {
38               Rational from_c (scm_to_int (scm_numerator (step)),
39                                scm_to_int (scm_denominator (step)));
40               tones.push_back (from_c);
41             }
42         }
43     }
44   
45   
46   SCM_ASSERT_TYPE (type_ok, steps, SCM_ARG1, __FUNCTION__, "vector of rational");
47
48   Scale *s = new Scale (tones);
49
50   SCM retval =  s->self_scm ();
51   s->unprotect ();
52   
53   return retval;
54 }
55
56 LY_DEFINE (ly_default_scale, "ly:default-scale",
57            0, 0, 0, (),
58            "Get the global default scale.")
59 {
60   return default_global_scale
61     ? default_global_scale->self_scm ()
62     : SCM_BOOL_F;
63 }
64
65
66 Scale * default_global_scale = 0;
67
68 LY_DEFINE (ly_set_default_scale, "ly:set-default-scale",
69            1, 0, 0, (SCM scale),
70            "Set the global default scale. This determines the tuning of"
71            " pitches with no accidentals or key signatures.  The first"
72            " pitch is C. Alterations are calculated relative to this"
73            " scale.  The number of pitches in this scale determines the"
74            " number of scale steps that make up an octave.  Usually the"
75            " 7-note major scale.")
76 {
77   LY_ASSERT_SMOB (Scale, scale, 1);
78
79   Scale *s = Scale::unsmob (scale);
80   if (default_global_scale)
81     default_global_scale->unprotect ();
82   default_global_scale = s;
83   s->protect ();
84   
85   return SCM_UNSPECIFIED;
86 }
87
88 int
89 Scale::step_count () const
90 {
91   return step_tones_.size ();
92 }
93
94 Rational
95 Scale::tones_at_step (int step, int octave) const
96 {
97   int normalized_step = normalize_step (step);
98
99   octave += (step - normalized_step) / step_count ();
100
101   // There are 6 tones in an octave.
102   return step_tones_[normalized_step] + Rational (octave*6);
103 }
104
105 Rational
106 Scale::step_size (int step) const
107 {
108   int normalized_step = normalize_step (step);
109
110   // Wrap around if we are asked for the final note of the
111   // scale (6 is the number of tones of the octave above the
112   // first note).
113   if (normalized_step + 1 == step_count ())
114     return Rational(6) - step_tones_[normalized_step];
115
116   return step_tones_[normalized_step + 1] - step_tones_[normalized_step];
117 }
118
119 int
120 Scale::normalize_step (int step) const
121 {
122   int ret = step % step_count ();
123   if (ret < 0)
124     ret += step_count ();
125
126   return ret;
127 }
128
129 int
130 Scale::print_smob (SCM /* x */,
131                    SCM port,
132                    scm_print_state *)
133 {
134   scm_puts ("#<Scale>", port); 
135   return 1;
136 }
137
138 SCM
139 Scale::mark_smob (SCM)
140 {
141   return SCM_UNSPECIFIED;
142 }
143
144 Scale::Scale (vector<Rational> const &tones)
145 {
146   step_tones_ = tones;
147
148   smobify_self ();
149 }
150
151 Scale::Scale (Scale const &src)
152 {
153   step_tones_ = src.step_tones_;
154   smobify_self ();
155 }
156
157
158 Scale::~Scale ()
159 {
160 }
161
162 IMPLEMENT_SMOBS (Scale);
163 IMPLEMENT_DEFAULT_EQUAL_P (Scale);