]> git.donarmstrong.com Git - lilypond.git/blob - src/midi-event.cc
release: 0.0.36
[lilypond.git] / src / midi-event.cc
1 //
2 // midi-event.cc -- implement Midi_event
3 //
4 // copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
5
6 #include <assert.h>
7 #include "proto.hh"
8
9 #include "plist.hh"      // all for midi-main.hh
10 #include "string.hh"
11 #include "source.hh"
12 #include "sourcefile.hh"
13 #include "midi-main.hh"  // *tors
14
15 #include "moment.hh"
16 #include "midi-event.hh"
17
18 Midi_event::Midi_event()
19 {
20 }
21
22 Midi_event::~Midi_event()
23 {
24 }
25
26 String
27 Midi_event::mudela_str()
28 {
29         return mudela_str_;
30 }
31
32 Midi_key::Midi_key( int accidentals_i, int minor_i )
33 {
34         accidentals_i_ = accidentals_i;
35         minor_i_ = minor_i;
36         if ( !minor_i_ )
37                 key_i_ = ( ( accidentals_i % 7 )[ "cgdaebf" ] - 'a' + 2 ) % 7;
38         else
39                 key_i_ = ( ( -accidentals_i % 7 )[ "fbeadg" ] - 'a' + 2 ) % 7;
40         mudela_str_ = String( "\\key\\" );
41         if ( !minor_i_ ) 
42                 mudela_str_ += String( (char)( key_i_ - 2 + 'A'  ) );
43         else
44                 mudela_str_ += String( (char)( key_i_ - 2 + 'a'  ) );
45 }
46
47 String
48 Midi_key::notename_str( int pitch_i )
49 {
50         // this may seem very smart,
51         // but it-s only an excuse not to read a notename table
52
53         // major scale: do-do
54         // minor scale: la-la ( = + 5 )
55         static int notename_i_a[ 12 ] = { 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 };
56         int notename_i = notename_i_a[ ( minor_i_ * 5 + pitch_i ) % 12 ];
57         
58         static int accidentals_i_a[ 12 ] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };
59         int accidental_i = accidentals_i_a[ minor_i_ * 5 + pitch_i % 12 ];
60         if ( accidentals_i_ < 0 ) {
61                 accidental_i = - accidental_i;
62                 notename_i = ( notename_i + 1 ) % 7;
63         }
64
65         String notename_str = (char)( ( ( notename_i + key_i_ - 2 ) % 7 ) + 'a' );
66         while ( accidental_i-- > 0 )
67                 notename_str += "is";
68         accidental_i++;
69         while ( accidental_i++ < 0 )
70                 if ( ( notename_str == "a" ) || ( notename_str == "e" ) )
71                         notename_str += "s";
72                 else
73                         notename_str += "es";
74         accidental_i--;
75         return notename_str;
76 }
77
78 Midi_key::~Midi_key()
79 {
80 }
81
82 Midi_note::Midi_note( Midi_key* midi_key_l, Midi_time* midi_time_l, int clocks_per_whole_i, int pitch_i, Real delta_time_f )
83 {
84         mudela_str_ = midi_key_l->notename_str( pitch_i );
85         mudela_str_ += midi_time_l->duration_str( clocks_per_whole_i, delta_time_f );
86 }
87
88 Midi_note::~Midi_note()
89 {
90 }
91
92 Midi_tempo::Midi_tempo( int useconds_per_4_i )
93 {
94         useconds_per_4_i_ = useconds_per_4_i;
95         seconds_per_1_f_ = (Real)useconds_per_4_i_ * 4 / 1e6;
96         mudela_str_ = "\\Tempo: ";
97         mudela_str_ += String( useconds_per_4_i_ );
98         mudela_str_ += String( ": " ) 
99                 + String( get_tempo_i( Moment( 1, 4 ) ) )
100                 + String( " 4 per minute" );
101 }
102
103 Midi_tempo::~Midi_tempo()
104 {
105 }
106
107 int
108 Midi_tempo::get_tempo_i( Moment moment )
109 {
110         return Moment( 60 ) / moment / Moment( seconds_per_1_f_ );
111 }
112
113 Midi_time::Midi_time( int num_i, int den_i, int clocks_i, int count_32_i )
114 {
115 //      we should warn, at least!
116 //      assert( count_32_i == 8 );
117         if ( count_32_i != 8 )
118                 warning( String( "#32 in quarter: " ) + String( count_32_i ), 0 );
119         num_i_ = num_i;
120         den_i_ = 2 << den_i;
121         // huh?, see midiitem.cc; reasonably for fugue1.midi
122 //      whole_clocks_i_ = clocks_i * 4 * 10; 
123         whole_clocks_i_ = clocks_i * 4; 
124 //      whole_clocks_i_ = clocks_i; 
125         mudela_str_ = "\\Time: ";
126         mudela_str_ += String( num_i_ ) + "/" + String( den_i_ )
127                 + ", " + String( whole_clocks_i_ )
128                 + ": " + String( count_32_i );
129 }
130
131 Midi_time::~Midi_time()
132 {
133 }
134
135 String
136 Midi_time::duration_str( int clocks_per_whole_i, Real delta_time_f )
137 {
138         dtor << "(" << delta_time_f;
139         String str;
140
141         Moment delta_time_moment = 1.0;
142         if ( delta_time_f ) {
143                 // 288/96*.25 = .75
144                 // 96/96*.25 = .25
145                 // 24/96*.25 = 0.0625
146 //              delta_time_moment = Moment( delta_time_f ) / Moment( whole_clocks_i() );
147                 if ( clocks_per_whole_i > 0 )
148                         delta_time_moment = Moment( delta_time_f ) / Moment( clocks_per_whole_i );
149                 else 
150                         delta_time_moment = Moment( -clocks_per_whole_i ) / Moment( delta_time_f );
151         }               
152
153         dtor << ", " << (Real)delta_time_moment << "): ";
154
155         static Real sync_f = 1;
156         delta_time_moment = delta_time_moment / sync_f;
157
158         double dummy_f;
159         if ( ( sync_f == 1 ) 
160                 && ( abs( modf( (Real)delta_time_moment / ( (Real)1 / 64 / 3 ), &dummy_f ) ) ) > 1e-6 ) {
161                 sync_f = (Real)delta_time_moment / 0.125;
162                 delta_time_moment = (Real)delta_time_moment / sync_f;
163                 mtor << "\nsyncing: " << sync_f << ", "
164 //                      << (Real)sync_f / usecond24th_per_clock_i << endl;
165                         << (Real)whole_clocks_i() << endl;
166         }
167
168         static bool must_resync_bo = false;
169         if ( ( (Real)delta_time_moment / 0.125 > 16 )
170                 || ( (Real)delta_time_moment / 0.125 < ( (Real)1 / 16 ) ) ) 
171                 must_resync_bo = true;
172         
173         if ( must_resync_bo ) {
174                 must_resync_bo = false;
175                 delta_time_moment = delta_time_moment * sync_f;
176                 sync_f = (Real)delta_time_moment / 0.125;
177                 delta_time_moment = (Real)delta_time_moment / sync_f;
178                 mtor << "\nresyncing: " << sync_f << ", "
179 //                      << (Real)sync_f / usecond24th_per_clock_i << endl;
180                         << (Real)whole_clocks_i() << endl;
181         }
182
183         if ( !delta_time_moment ) 
184                 return "0";
185
186         // output of modf: double 
187         double duration_f = 0;
188         Real rest_f = modf( ( Moment( 1 ) / delta_time_moment ), &duration_f );
189         int dots_i = 0;
190         int plet_type_i = 0;
191         if ( rest_f ) {
192                 // output of modf: double 
193                 double dots_f = 0;
194                 Real dots_rest_f = modf( rest_f * 3, &dots_f );
195                 if ( !dots_rest_f )
196                         dots_i = (int)rint( dots_f );
197                 else if ( abs( dots_rest_f - rint( dots_rest_f ) ) < 1e-8 )
198                         dots_i = (int)rint( dots_rest_f );
199                 // try 3plet
200                 else if ( !modf( (Real)3 * delta_time_moment / 2, &duration_f ) )
201                         plet_type_i = 3;
202                 // try 6plet
203                 else if ( !modf( (Real)6 * delta_time_moment / 2, &duration_f ) )
204                         plet_type_i = 6;
205                 else {
206 //                      str += String( "\n*" ) + String( (int)( 1 / rest_f ) );
207                         str += String( "\n*" ) + String( rest_f );
208                         must_resync_bo = true;
209                 }
210         }
211
212         if ( dots_i ) {
213                 for ( int i = dots_i; i ; i-- )
214                         delta_time_moment *= (Real)2 / 3;
215                 modf( ( Moment( 1 ) / delta_time_moment ), &duration_f );
216         }
217
218         str += String( (int)( duration_f ) );
219         if ( dots_i )
220                 str += String( '.', dots_i );
221         if ( plet_type_i )
222                 str += String( "/" ) + String( plet_type_i );
223
224         return str;
225 }
226
227 int
228 Midi_time::whole_clocks_i()
229 {
230         return whole_clocks_i_;
231 }
232