1 /***************************************************/
3 \brief STK SKINI parsing class
5 This class parses SKINI formatted text
6 messages. It can be used to parse individual
7 messages or it can be passed an entire file.
8 The SKINI specification is Perry's and his
9 alone, but it's all text so it shouldn't be too
12 SKINI (Synthesis toolKit Instrument Network
13 Interface) is like MIDI, but allows for
14 floating-point control changes, note numbers,
15 etc. The following example causes a sharp
16 middle C to be played with a velocity of 111.132:
22 by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
24 /***************************************************/
27 //#include "SKINI.tbl"
37 bool Skini :: setFile( std::string fileName
)
39 if ( file_
.is_open() ) {
40 //errorString_ << "Skini::setFile: already reaading a file!";
41 //handleError( StkError::WARNING );
45 file_
.open( fileName
.c_str() );
47 // errorString_ << "Skini::setFile: unable to open file (" << fileName << ")";
48 // handleError( StkError::WARNING );
55 long Skini :: nextMessage( Message
& message
)
57 if ( !file_
.is_open() ) return 0;
62 // Read a line from the file and skip over invalid messages.
63 if ( std::getline( file_
, line
).eof() ) {
64 // errorString_ << "// End of Score. Thanks for using SKINI!!";
65 // handleError( StkError::STATUS );
70 else if ( parseString( line
, message
) > 0 ) done
= true;
77 bool Skini :: write_message( long type
, float time
, long channel
, float data1
, float data2
)
79 if( !file_
.is_open() ) return 0;
81 char messageString
[32];
82 char * message
= new char[64];
84 // find message string from type
86 while ( iSkini
< __SK_MaxMsgTypes_
) {
87 if ( type
== skini_msgs
[iSkini
].type
)
89 strcpy( messageString
, skini_msgs
[iSkini
].messageString
);
95 // make up some code that makes sense to you if not to the compiler
96 printf( message
, "%s %f %i %f %f\n", messageString
, time
, channel
, data1
, data2
);
97 file_
.write( message
, 64 * sizeof(char) );
102 void Skini :: close_file()
104 if( file_
.is_open() )
109 void Skini :: tokenize( const std::string
& str
,
110 std::vector
<std::string
>& tokens
,
111 const std::string
& delimiters
)
113 // Skip delimiters at beginning.
114 std::string::size_type lastPos
= str
.find_first_not_of(delimiters
, 0);
115 // Find first "non-delimiter".
116 std::string::size_type pos
= str
.find_first_of(delimiters
, lastPos
);
118 while (std::string::npos
!= pos
|| std::string::npos
!= lastPos
) {
119 // Found a token, add it to the vector.
120 tokens
.push_back(str
.substr(lastPos
, pos
- lastPos
));
121 // Skip delimiters. Note the "not_of"
122 lastPos
= str
.find_first_not_of(delimiters
, pos
);
123 // Find next "non-delimiter"
124 pos
= str
.find_first_of(delimiters
, lastPos
);
128 long Skini :: parseString( std::string
& line
, Message
& message
)
131 if ( line
.empty() ) return message
.type
;
133 // Check for comment lines.
134 std::string::size_type lastPos
= line
.find_first_not_of(" ,\t", 0);
135 std::string::size_type pos
= line
.find_first_of("/", lastPos
);
136 if ( std::string::npos
!= pos
) {
137 // errorString_ << "// Comment Line: " << line;
138 // handleError( StkError::STATUS );
142 // Tokenize the string.
143 std::vector
<std::string
> tokens
;
144 this->tokenize( line
, tokens
, " ,\t");
146 // Valid SKINI messages must have at least three fields (type, time,
148 if ( tokens
.size() < 3 ) return message
.type
;
150 // Determine message type.
152 while ( iSkini
< __SK_MaxMsgTypes_
) {
153 if ( tokens
[0] == skini_msgs
[iSkini
].messageString
) break;
157 if ( iSkini
>= __SK_MaxMsgTypes_
) {
158 // errorString_ << "Skini::parseString: couldn't parse this line:\n " << line;
159 // handleError( StkError::WARNING );
164 message
.type
= skini_msgs
[iSkini
].type
;
167 if ( tokens
[1][0] == '=' ) {
168 tokens
[1].erase( tokens
[1].begin() );
169 if ( tokens
[1].empty() ) {
170 // errorString_ << "Skini::parseString: couldn't parse time field in line:\n " << line;
171 // handleError( StkError::WARNING );
172 return message
.type
= 0;
174 message
.time
= (float) -atof( tokens
[1].c_str() );
177 message
.time
= (float) atof( tokens
[1].c_str() );
179 // Parse the channel field.
180 message
.channel
= atoi( tokens
[2].c_str() );
182 // Parse the remaining fields (maximum of 2 more).
184 long dataType
= skini_msgs
[iSkini
].data2
;
185 while ( dataType
!= NOPE
) {
187 if ( tokens
.size() <= (unsigned int) (iValue
+3) ) {
188 // errorString_ << "Skini::parseString: inconsistency between type table and parsed line:\n " << line;
189 // handleError( StkError::WARNING );
190 return message
.type
= 0;
193 switch ( dataType
) {
196 message
.intValues
[iValue
] = atoi( tokens
[iValue
+3].c_str() );
197 message
.floatValues
[iValue
] = (float) message
.intValues
[iValue
];
201 message
.floatValues
[iValue
] = atof( tokens
[iValue
+3].c_str() );
202 message
.intValues
[iValue
] = (long) message
.floatValues
[iValue
];
205 case SK_STR
: // Must be the last field.
206 message
.remainder
= tokens
[iValue
+3];
211 dataType
= skini_msgs
[iSkini
].data3
;
219 std::string
Skini :: whatsThisType(long type
)
221 std::string typeString
;
223 for ( int i
=0; i
<__SK_MaxMsgTypes_
; i
++ ) {
224 if ( type
== skini_msgs
[i
].type
) {
225 typeString
= skini_msgs
[i
].messageString
;
232 std::string
Skini :: whatsThisController( long number
)
234 std::string controller
;
236 for ( int i
=0; i
<__SK_MaxMsgTypes_
; i
++) {
237 if ( skini_msgs
[i
].type
== __SK_ControlChange_
&&
238 number
== skini_msgs
[i
].data2
) {
239 controller
= skini_msgs
[i
].messageString
;
247 struct SkiniSpec skini_msgs
[__SK_MaxMsgTypes_
] =
249 {"NoteOff" , __SK_NoteOff_
, SK_DBL
, SK_DBL
},
250 {"NoteOn" , __SK_NoteOn_
, SK_DBL
, SK_DBL
},
251 {"PolyPressure" , __SK_PolyPressure_
, SK_DBL
, SK_DBL
},
252 {"ControlChange" , __SK_ControlChange_
, SK_INT
, SK_DBL
},
253 {"ProgramChange" , __SK_ProgramChange_
, SK_DBL
, NOPE
},
254 {"AfterTouch" , __SK_AfterTouch_
, SK_DBL
, NOPE
},
255 {"ChannelPressure" ,__SK_ChannelPressure_
, SK_DBL
, NOPE
},
256 {"PitchWheel" , __SK_PitchWheel_
, SK_DBL
, NOPE
},
257 {"PitchBend" , __SK_PitchBend_
, SK_DBL
, NOPE
},
258 {"PitchChange" , __SK_PitchChange_
, SK_DBL
, NOPE
},
260 {"Clock" , __SK_Clock_
, NOPE
, NOPE
},
261 {"Undefined" , 249, NOPE
, NOPE
},
262 {"SongStart" , __SK_SongStart_
, NOPE
, NOPE
},
263 {"Continue" , __SK_Continue_
, NOPE
, NOPE
},
264 {"SongStop" , __SK_SongStop_
, NOPE
, NOPE
},
265 {"Undefined" , 253, NOPE
, NOPE
},
266 {"ActiveSensing" , __SK_ActiveSensing_
, NOPE
, NOPE
},
267 {"SystemReset" , __SK_SystemReset_
, NOPE
, NOPE
},
269 {"Volume" , __SK_ControlChange_
, __SK_Volume_
, SK_DBL
},
270 {"ModWheel" , __SK_ControlChange_
, __SK_ModWheel_
, SK_DBL
},
271 {"Modulation" , __SK_ControlChange_
, __SK_Modulation_
, SK_DBL
},
272 {"Breath" , __SK_ControlChange_
, __SK_Breath_
, SK_DBL
},
273 {"FootControl" , __SK_ControlChange_
, __SK_FootControl_
, SK_DBL
},
274 {"Portamento" , __SK_ControlChange_
, __SK_Portamento_
, SK_DBL
},
275 {"Balance" , __SK_ControlChange_
, __SK_Balance_
, SK_DBL
},
276 {"Pan" , __SK_ControlChange_
, __SK_Pan_
, SK_DBL
},
277 {"Sustain" , __SK_ControlChange_
, __SK_Sustain_
, SK_DBL
},
278 {"Damper" , __SK_ControlChange_
, __SK_Damper_
, SK_DBL
},
279 {"Expression" , __SK_ControlChange_
, __SK_Expression_
, SK_DBL
},
281 {"NoiseLevel" , __SK_ControlChange_
, __SK_NoiseLevel_
, SK_DBL
},
282 {"PickPosition" , __SK_ControlChange_
, __SK_PickPosition_
, SK_DBL
},
283 {"StringDamping" , __SK_ControlChange_
, __SK_StringDamping_
, SK_DBL
},
284 {"StringDetune" , __SK_ControlChange_
, __SK_StringDetune_
, SK_DBL
},
285 {"BodySize" , __SK_ControlChange_
, __SK_BodySize_
, SK_DBL
},
286 {"BowPressure" , __SK_ControlChange_
, __SK_BowPressure_
, SK_DBL
},
287 {"BowPosition" , __SK_ControlChange_
, __SK_BowPosition_
, SK_DBL
},
288 {"BowBeta" , __SK_ControlChange_
, __SK_BowBeta_
, SK_DBL
},
290 {"ReedStiffness" , __SK_ControlChange_
, __SK_ReedStiffness_
, SK_DBL
},
291 {"ReedRestPos" , __SK_ControlChange_
, __SK_ReedRestPos_
, SK_DBL
},
292 {"FluteEmbouchure" , __SK_ControlChange_
, __SK_FluteEmbouchure_
, SK_DBL
},
293 {"LipTension" , __SK_ControlChange_
, __SK_LipTension_
, SK_DBL
},
294 {"StrikePosition" , __SK_ControlChange_
, __SK_StrikePosition_
, SK_DBL
},
295 {"StickHardness" , __SK_ControlChange_
, __SK_StickHardness_
, SK_DBL
},
297 {"TrillDepth" , __SK_ControlChange_
, __SK_TrillDepth_
, SK_DBL
},
298 {"TrillSpeed" , __SK_ControlChange_
, __SK_TrillSpeed_
, SK_DBL
},
300 {"Strumming" , __SK_ControlChange_
, __SK_Strumming_
, 127 },
301 {"NotStrumming" , __SK_ControlChange_
, __SK_Strumming_
, 0 },
303 {"PlayerSkill" , __SK_ControlChange_
, __SK_PlayerSkill_
, SK_DBL
},
305 {"Chord" , __SK_Chord_
, SK_DBL
, SK_STR
},
306 {"ChordOff" , __SK_ChordOff_
, SK_DBL
, NOPE
},
308 {"ShakerInst" , __SK_ControlChange_
, __SK_ShakerInst_
, SK_DBL
},
309 {"Maraca" , __SK_ControlChange_
, __SK_ShakerInst_
, 0 },
310 {"Sekere" , __SK_ControlChange_
, __SK_ShakerInst_
, 1 },
311 {"Cabasa" , __SK_ControlChange_
, __SK_ShakerInst_
, 2 },
312 {"Bamboo" , __SK_ControlChange_
, __SK_ShakerInst_
, 3 },
313 {"Waterdrp" , __SK_ControlChange_
, __SK_ShakerInst_
, 4 },
314 {"Tambourn" , __SK_ControlChange_
, __SK_ShakerInst_
, 5 },
315 {"Sleighbl" , __SK_ControlChange_
, __SK_ShakerInst_
, 6 },
316 {"Guiro" , __SK_ControlChange_
, __SK_ShakerInst_
, 7 },
318 {"OpenFile" , 256, SK_STR
, NOPE
},
319 {"SetPath" , 257, SK_STR
, NOPE
},
321 {"FilePath" , __SK_SINGER_FilePath_
, SK_STR
, NOPE
},
322 {"Frequency" , __SK_SINGER_Frequency_
, SK_STR
, NOPE
},
323 {"NoteName" , __SK_SINGER_NoteName_
, SK_STR
, NOPE
},
324 {"VocalShape" , __SK_SINGER_Shape_
, SK_STR
, NOPE
},
325 {"Glottis" , __SK_SINGER_Glot_
, SK_STR
, NOPE
},
326 {"VoicedUnVoiced" , __SK_SINGER_VoicedUnVoiced_
, SK_DBL
, SK_STR
},
327 {"Synthesize" , __SK_SINGER_Synthesize_
, SK_STR
, NOPE
},
328 {"Silence" , __SK_SINGER_Silence_
, SK_STR
, NOPE
},
329 {"RndVibAmt" , __SK_SINGER_RndVibAmt_
, SK_STR
, NOPE
},
330 {"VibratoAmt" , __SK_ControlChange_
,__SK_SINGER_VibratoAmt_
,SK_DBL
},
331 {"VibFreq" , __SK_ControlChange_
,__SK_SINGER_VibFreq_
,SK_DBL
}