1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
<HTML>
<HEAD>
<TITLE>The Synthesis ToolKit in C++ (STK)</TITLE>
<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER>
<img src="princeton.gif"> <img src="ccrma.gif"><P>
<a class="qindex" href="index.html">Home</a> <a class="qindex" href="information.html">Information</a> <a class="qindex" href="classes.html">Classes</a> <a class="qindex" href="download.html">Download</a> <a class="qindex" href="usage.html">Usage</a> <a class="qindex" href="maillist.html">Mail List</a> <a class="qindex" href="system.html">Requirements</a> <a class="qindex" href="links.html">Links</a> <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
<HR>
<!-- Generated by Doxygen 1.3-rc3 -->
<h1>MidiFileIn.cpp</h1><div class="fragment"><pre>00001 <span class="comment">/**********************************************************************/</span>
00016 <span class="comment">/**********************************************************************/</span>
00017
00018 <span class="preprocessor">#include "MidiFileIn.h"</span>
00019 <span class="preprocessor">#include <iostream></span>
00020
<a name="l00021"></a><a class="code" href="classMidiFileIn.html#a0">00021</a> <a class="code" href="classMidiFileIn.html#a0">MidiFileIn :: MidiFileIn</a>( std::string fileName )
00022 {
00023 <span class="comment">// Attempt to open the file.</span>
00024 file_.open( fileName.c_str(), std::ios::in );
00025 <span class="keywordflow">if</span> ( !file_ ) {
00026 errorString_ << <span class="stringliteral">"MidiFileIn: error opening or finding file ("</span> << fileName << <span class="stringliteral">")."</span>;
00027 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_NOT_FOUND );
00028 }
00029
00030 <span class="comment">// Parse header info.</span>
00031 <span class="keywordtype">char</span> chunkType[4];
00032 <span class="keywordtype">char</span> buffer[4];
00033 SINT32 *length;
00034 <span class="keywordflow">if</span> ( !file_.read( chunkType, 4 ) ) <span class="keywordflow">goto</span> error;
00035 <span class="keywordflow">if</span> ( !file_.read( buffer, 4 ) ) <span class="keywordflow">goto</span> error;
00036 length = (SINT32 *) &buffer;
00037 <span class="keywordflow">if</span> ( strncmp( chunkType, <span class="stringliteral">"MThd"</span>, 4 ) || ( *length != 6 ) ) {
00038 errorString_ << <span class="stringliteral">"MidiFileIn: file ("</span> << fileName << <span class="stringliteral">") does not appear to be a MIDI file!"</span>;
00039 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_UNKNOWN_FORMAT );
00040 }
00041
00042 <span class="comment">// Read the MIDI file format.</span>
00043 SINT16 *data;
00044 <span class="keywordflow">if</span> ( !file_.read( buffer, 2 ) ) <span class="keywordflow">goto</span> error;
00045 data = (SINT16 *) &buffer;
00046 <span class="keywordflow">if</span> ( *data < 0 || *data > 2 ) {
00047 errorString_ << <span class="stringliteral">"MidiFileIn: the file ("</span> << fileName << <span class="stringliteral">") format is invalid!"</span>;
00048 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_ERROR );
00049 }
00050 format_ = *data;
00051
00052 <span class="comment">// Read the number of tracks.</span>
00053 <span class="keywordflow">if</span> ( !file_.read( buffer, 2 ) ) <span class="keywordflow">goto</span> error;
00054 <span class="keywordflow">if</span> ( format_ == 0 && *data != 1 ) {
00055 errorString_ << <span class="stringliteral">"MidiFileIn: invalid number of tracks (>1) for a file format = 0!"</span>;
00056 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_ERROR );
00057 }
00058 nTracks_ = *data;
00059
00060 <span class="comment">// Read the beat division.</span>
00061 <span class="keywordflow">if</span> ( !file_.read( buffer, 2 ) ) <span class="keywordflow">goto</span> error;
00062 division_ = (int) *data;
00063 <span class="keywordtype">double</span> tickrate;
00064 usingTimeCode_ = <span class="keyword">false</span>;
00065 <span class="keywordflow">if</span> ( *data & 0x8000 ) {
00066 <span class="comment">// Determine ticks per second from time-code formats.</span>
00067 tickrate = (double) -(*data & 0x7F00);
00068 <span class="comment">// If frames per second value is 29, it really should be 29.97.</span>
00069 <span class="keywordflow">if</span> ( tickrate == 29.0 ) tickrate = 29.97;
00070 tickrate *= (*data & 0x00FF);
00071 usingTimeCode_ = <span class="keyword">true</span>;
00072 }
00073 <span class="keywordflow">else</span> {
00074 tickrate = (double) (*data & 0x7FFF); <span class="comment">// ticks per quarter note</span>
00075 }
00076
00077 <span class="comment">// Now locate the track offsets and lengths. If not using time</span>
00078 <span class="comment">// code, we can initialize the "tick time" using a default tempo of</span>
00079 <span class="comment">// 120 beats per minute. We will then check for tempo meta-events</span>
00080 <span class="comment">// afterward.</span>
00081 <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i<nTracks_; i++ ) {
00082 <span class="keywordflow">if</span> ( !file_.read( chunkType, 4 ) ) <span class="keywordflow">goto</span> error;
00083 <span class="keywordflow">if</span> ( strncmp( chunkType, <span class="stringliteral">"MTrk"</span>, 4 ) ) <span class="keywordflow">goto</span> error;
00084 <span class="keywordflow">if</span> ( !file_.read( buffer, 4 ) ) <span class="keywordflow">goto</span> error;
00085 length = (SINT32 *) &buffer;
00086 trackLengths_.push_back( *length );
00087 trackOffsets_.push_back( file_.tellg() );
00088 trackPointers_.push_back( file_.tellg() );
00089 trackStatus_.push_back( 0 );
00090 file_.seekg( *length, std::ios_base::cur );
00091 <span class="keywordflow">if</span> ( usingTimeCode_ ) tickSeconds_.push_back( (<span class="keywordtype">double</span>) (1.0 / tickrate) );
00092 <span class="keywordflow">else</span> tickSeconds_.push_back( (<span class="keywordtype">double</span>) (0.5 / tickrate) );
00093 }
00094
00095 <span class="comment">// Save the initial tickSeconds parameter.</span>
00096 TempoChange tempoEvent;
00097 tempoEvent.count = 0;
00098 tempoEvent.tickSeconds = tickSeconds_[0];
00099 tempoEvents_.push_back( tempoEvent );
00100
00101 <span class="comment">// If format 1 and not using time code, parse and save the tempo map</span>
00102 <span class="comment">// on track 0.</span>
00103 <span class="keywordflow">if</span> ( format_ == 1 && !usingTimeCode_ ) {
00104 std::vector<unsigned char> event;
00105 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> value, count;
00106
00107 <span class="comment">// We need to temporarily change the usingTimeCode_ value here so</span>
00108 <span class="comment">// that the getNextEvent() function doesn't try to check the tempo</span>
00109 <span class="comment">// map (which we're creating here).</span>
00110 usingTimeCode_ = <span class="keyword">true</span>;
00111 count = <a class="code" href="classMidiFileIn.html#a7">getNextEvent</a>( &event, 0 );
00112 <span class="keywordflow">while</span> ( event.size() ) {
00113 <span class="keywordflow">if</span> ( ( event.size() == 6 ) && ( event[0] == 0xff ) &&
00114 ( event[1] == 0x51 ) && ( event[2] == 0x03 ) ) {
00115 tempoEvent.count = count;
00116 value = ( event[3] << 16 ) + ( event[4] << 8 ) + event[5];
00117 tempoEvent.tickSeconds = (double) (0.000001 * value / tickrate);
00118 <span class="keywordflow">if</span> ( count > tempoEvents_.back().count )
00119 tempoEvents_.push_back( tempoEvent );
00120 <span class="keywordflow">else</span>
00121 tempoEvents_.back() = tempoEvent;
00122 }
00123 count += <a class="code" href="classMidiFileIn.html#a7">getNextEvent</a>( &event, 0 );
00124 }
00125 <a class="code" href="classMidiFileIn.html#a5">rewindTrack</a>( 0 );
00126 <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i<nTracks_; i++ ) {
00127 trackCounters_.push_back( 0 );
00128 trackTempoIndex_.push_back( 0 );
00129 }
00130 <span class="comment">// Change the time code flag back!</span>
00131 usingTimeCode_ = <span class="keyword">false</span>;
00132 }
00133
00134 <span class="keywordflow">return</span>;
00135
00136 error:
00137 errorString_ << <span class="stringliteral">"MidiFileIn: error reading from file ("</span> << fileName << <span class="stringliteral">")."</span>;
00138 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_ERROR );
00139 }
00140
<a name="l00141"></a><a class="code" href="classMidiFileIn.html#a1">00141</a> <a class="code" href="classMidiFileIn.html#a1">MidiFileIn :: ~MidiFileIn</a>()
00142 {
00143 <span class="comment">// An ifstream object implicitly closes itself during destruction</span>
00144 <span class="comment">// but we'll make an explicit call to "close" anyway.</span>
00145 file_.close();
00146 }
00147
<a name="l00148"></a><a class="code" href="classMidiFileIn.html#a2">00148</a> <span class="keywordtype">int</span> <a class="code" href="classMidiFileIn.html#a2">MidiFileIn :: getFileFormat</a>()<span class="keyword"> const</span>
00149 <span class="keyword"></span>{
00150 <span class="keywordflow">return</span> format_;
00151 }
00152
<a name="l00153"></a><a class="code" href="classMidiFileIn.html#a3">00153</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classMidiFileIn.html#a3">MidiFileIn :: getNumberOfTracks</a>()<span class="keyword"> const</span>
00154 <span class="keyword"></span>{
00155 <span class="keywordflow">return</span> nTracks_;
00156 }
00157
<a name="l00158"></a><a class="code" href="classMidiFileIn.html#a4">00158</a> <span class="keywordtype">int</span> <a class="code" href="classMidiFileIn.html#a4">MidiFileIn :: getDivision</a>()<span class="keyword"> const</span>
00159 <span class="keyword"></span>{
00160 <span class="keywordflow">return</span> division_;
00161 }
00162
<a name="l00163"></a><a class="code" href="classMidiFileIn.html#a5">00163</a> <span class="keywordtype">void</span> <a class="code" href="classMidiFileIn.html#a5">MidiFileIn :: rewindTrack</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> track )
00164 {
00165 <span class="keywordflow">if</span> ( track >= nTracks_ ) {
00166 errorString_ << <span class="stringliteral">"MidiFileIn::getNextEvent: invalid track argument ("</span> << track << <span class="stringliteral">")."</span>;
00167 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FUNCTION_ARGUMENT );
00168 }
00169
00170 trackPointers_[track] = trackOffsets_[track];
00171 trackStatus_[track] = 0;
00172 tickSeconds_[track] = tempoEvents_[0].tickSeconds;
00173 }
00174
<a name="l00175"></a><a class="code" href="classMidiFileIn.html#a6">00175</a> <span class="keywordtype">double</span> <a class="code" href="classMidiFileIn.html#a6">MidiFileIn :: getTickSeconds</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> track )
00176 {
00177 <span class="comment">// Return the current tick value in seconds for the given track.</span>
00178 <span class="keywordflow">if</span> ( track >= nTracks_ ) {
00179 errorString_ << <span class="stringliteral">"MidiFileIn::getTickSeconds: invalid track argument ("</span> << track << <span class="stringliteral">")."</span>;
00180 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FUNCTION_ARGUMENT );
00181 }
00182
00183 <span class="keywordflow">return</span> tickSeconds_[track];
00184 }
00185
<a name="l00186"></a><a class="code" href="classMidiFileIn.html#a7">00186</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <a class="code" href="classMidiFileIn.html#a7">MidiFileIn :: getNextEvent</a>( std::vector<unsigned char> *event, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> track )
00187 {
00188 <span class="comment">// Fill the user-provided vector with the next event in the</span>
00189 <span class="comment">// specified track (default = 0) and return the event delta time in</span>
00190 <span class="comment">// ticks. This function assumes that the stored track pointer is</span>
00191 <span class="comment">// positioned at the start of a track event. If the track has</span>
00192 <span class="comment">// reached its end, the event vector size will be zero.</span>
00193 <span class="comment">//</span>
00194 <span class="comment">// If we have a format 0 or 2 file and we're not using timecode, we</span>
00195 <span class="comment">// should check every meta-event for tempo changes and make</span>
00196 <span class="comment">// appropriate updates to the tickSeconds_ parameter if so.</span>
00197 <span class="comment">//</span>
00198 <span class="comment">// If we have a format 1 file and we're not using timecode, keep a</span>
00199 <span class="comment">// running sum of ticks for each track and update the tickSeconds_</span>
00200 <span class="comment">// parameter as needed based on the stored tempo map.</span>
00201
00202 <span class="keywordflow">if</span> ( track >= nTracks_ ) {
00203 errorString_ << <span class="stringliteral">"MidiFileIn::getNextEvent: invalid track argument ("</span> << track << <span class="stringliteral">")."</span>;
00204 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FUNCTION_ARGUMENT );
00205 }
00206
00207 event->clear();
00208 <span class="comment">// Check for the end of the track.</span>
00209 <span class="keywordflow">if</span> ( (trackPointers_[track] - trackOffsets_[track]) >= trackLengths_[track] )
00210 <span class="keywordflow">return</span> 0;
00211
00212 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> ticks = 0, bytes = 0;
00213 <span class="keywordtype">bool</span> isTempoEvent = <span class="keyword">false</span>;
00214
00215 <span class="comment">// Read the event delta time.</span>
00216 file_.seekg( trackPointers_[track], std::ios_base::beg );
00217 <span class="keywordflow">if</span> ( !readVariableLength( &ticks ) ) <span class="keywordflow">goto</span> error;
00218
00219 <span class="comment">// Parse the event stream to determine the event length.</span>
00220 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> c;
00221 <span class="keywordflow">if</span> ( !file_.read( (<span class="keywordtype">char</span> *)&c, 1 ) ) <span class="keywordflow">goto</span> error;
00222 <span class="keywordflow">switch</span> ( c ) {
00223
00224 <span class="keywordflow">case</span> 0xFF: <span class="comment">// A Meta-Event</span>
00225 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> position;
00226 trackStatus_[track] = 0;
00227 event->push_back( c );
00228 <span class="keywordflow">if</span> ( !file_.read( (<span class="keywordtype">char</span> *)&c, 1 ) ) <span class="keywordflow">goto</span> error;
00229 event->push_back( c );
00230 <span class="keywordflow">if</span> ( format_ != 1 && ( c == 0x51 ) ) isTempoEvent = <span class="keyword">true</span>;
00231 position = file_.tellg();
00232 <span class="keywordflow">if</span> ( !readVariableLength( &bytes ) ) <span class="keywordflow">goto</span> error;
00233 bytes += ( (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)file_.tellg() - position );
00234 file_.seekg( position, std::ios_base::beg );
00235 <span class="keywordflow">break</span>;
00236
00237 <span class="keywordflow">case</span> 0xF0 || 0xF7: <span class="comment">// The start or continuation of a Sysex event</span>
00238 trackStatus_[track] = 0;
00239 event->push_back( c );
00240 position = file_.tellg();
00241 <span class="keywordflow">if</span> ( !readVariableLength( &bytes ) ) <span class="keywordflow">goto</span> error;
00242 bytes += ( (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)file_.tellg() - position );
00243 file_.seekg( position, std::ios_base::beg );
00244 <span class="keywordflow">break</span>;
00245
00246 <span class="keywordflow">default</span>: <span class="comment">// Should be a MIDI channel event</span>
00247 <span class="keywordflow">if</span> ( c & 0x80 ) { <span class="comment">// MIDI status byte</span>
00248 <span class="keywordflow">if</span> ( c > 0xF0 ) <span class="keywordflow">goto</span> error;
00249 trackStatus_[track] = c;
00250 event->push_back( c );
00251 c &= 0xF0;
00252 <span class="keywordflow">if</span> ( (c == 0xC0) || (c == 0xD0) ) bytes = 1;
00253 <span class="keywordflow">else</span> bytes = 2;
00254 }
00255 <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( trackStatus_[track] & 0x80 ) { <span class="comment">// Running status</span>
00256 event->push_back( trackStatus_[track] );
00257 event->push_back( c );
00258 c = trackStatus_[track] & 0xF0;
00259 <span class="keywordflow">if</span> ( (c != 0xC0) && (c != 0xD0) ) bytes = 1;
00260 }
00261 <span class="keywordflow">else</span> <span class="keywordflow">goto</span> error;
00262
00263 }
00264
00265 <span class="comment">// Read the rest of the event into the event vector.</span>
00266 <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> i=0; i<bytes; i++ ) {
00267 <span class="keywordflow">if</span> ( !file_.read( (<span class="keywordtype">char</span> *)&c, 1 ) ) <span class="keywordflow">goto</span> error;
00268 event->push_back( c );
00269 }
00270
00271 <span class="keywordflow">if</span> ( !usingTimeCode_ ) {
00272 <span class="keywordflow">if</span> ( isTempoEvent ) {
00273 <span class="comment">// Parse the tempo event and update tickSeconds_[track].</span>
00274 <span class="keywordtype">double</span> tickrate = (double) (division_ & 0x7FFF);
00275 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> value = ( event->at(3) << 16 ) + ( event->at(4) << 8 ) + event->at(5);
00276 tickSeconds_[track] = (double) (0.000001 * value / tickrate);
00277 }
00278
00279 <span class="keywordflow">if</span> ( format_ == 1 ) {
00280 <span class="comment">// Update track counter and check the tempo map.</span>
00281 trackCounters_[track] += ticks;
00282 TempoChange tempoEvent = tempoEvents_[ trackTempoIndex_[track] ];
00283 <span class="keywordflow">if</span> ( trackCounters_[track] >= tempoEvent.count ) {
00284 trackTempoIndex_[track]++;
00285 tickSeconds_[track] = tempoEvent.tickSeconds;
00286 }
00287 }
00288 }
00289
00290 <span class="comment">// Save the current track pointer value.</span>
00291 trackPointers_[track] = file_.tellg();
00292
00293 <span class="keywordflow">return</span> ticks;
00294
00295 error:
00296 errorString_ << <span class="stringliteral">"MidiFileIn::getNextEvent: file read error!"</span>;
00297 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FILE_ERROR );
00298 <span class="keywordflow">return</span> 0;
00299 }
00300
<a name="l00301"></a><a class="code" href="classMidiFileIn.html#a8">00301</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <a class="code" href="classMidiFileIn.html#a8">MidiFileIn :: getNextMidiEvent</a>( std::vector<unsigned char> *midiEvent, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> track )
00302 {
00303 <span class="comment">// Fill the user-provided vector with the next MIDI event in the</span>
00304 <span class="comment">// specified track (default = 0) and return the event delta time in</span>
00305 <span class="comment">// ticks. Meta-Events preceeding this event are skipped and ignored.</span>
00306 <span class="keywordflow">if</span> ( track >= nTracks_ ) {
00307 errorString_ << <span class="stringliteral">"MidiFileIn::getNextMidiEvent: invalid track argument ("</span> << track << <span class="stringliteral">")."</span>;
00308 <a class="code" href="classStk.html#e0">handleError</a>( errorString_.str(), StkError::FUNCTION_ARGUMENT );
00309 }
00310
00311 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> ticks = <a class="code" href="classMidiFileIn.html#a7">getNextEvent</a>( midiEvent, track );
00312 <span class="keywordflow">while</span> ( midiEvent->size() && ( midiEvent->at(0) >= 0xF0 ) ) {
00313 <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i<midiEvent->size(); i++ )
00314 std::cout << <span class="stringliteral">"event byte = "</span> << i << <span class="stringliteral">", value = "</span> << (int)midiEvent->at(i) << std::endl;
00315 ticks = <a class="code" href="classMidiFileIn.html#a7">getNextEvent</a>( midiEvent, track );
00316 }
00317
00318 <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i<midiEvent->size(); i++ )
00319 std::cout << <span class="stringliteral">"event byte = "</span> << i << <span class="stringliteral">", value = "</span> << (int)midiEvent->at(i) << std::endl;
00320
00321 <span class="keywordflow">return</span> ticks;
00322 }
00323
00324 <span class="keywordtype">bool</span> MidiFileIn :: readVariableLength( <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> *value )
00325 {
00326 <span class="comment">// It is assumed that this function is called with the file read</span>
00327 <span class="comment">// pointer positioned at the start of a variable-length value. The</span>
00328 <span class="comment">// function returns "true" if the value is successfully parsed and</span>
00329 <span class="comment">// "false" otherwise.</span>
00330 *value = 0;
00331 <span class="keywordtype">char</span> c;
00332
00333 <span class="keywordflow">if</span> ( !file_.read( &c, 1 ) ) <span class="keywordflow">return</span> <span class="keyword">false</span>;
00334 *value = (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) c;
00335 <span class="keywordflow">if</span> ( *value & 0x80 ) {
00336 *value &= 0x7f;
00337 <span class="keywordflow">do</span> {
00338 <span class="keywordflow">if</span> ( !file_.read( &c, 1 ) ) <span class="keywordflow">return</span> <span class="keyword">false</span>;
00339 *value = ( *value << 7 ) + ( c & 0x7f );
00340 } <span class="keywordflow">while</span> ( c & 0x80 );
00341 }
00342
00343 <span class="keywordflow">return</span> <span class="keyword">true</span>;
00344 }
</pre></div><HR>
<table>
<tr><td><A HREF="http://www-ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
<tr><td>©1995-2002 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
</table>
</BODY>
</HTML>
|