1 /* 2 Copyright (c) 2003-2006 yuno 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are met: 7 1. Redistributions of source code must retain the above copyright notice, 8 this list of conditions and the following disclaimer. 9 2. Redistributions in binary form must reproduce the above copyright notice, 10 this list of conditions and the following disclaimer in the documentation 11 and/or other materials provided with the distribution. 12 3. Neither the name of copyright holders nor the names of its contributors 13 may be used to endorse or promote products derived from this software 14 without specific prior written permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE 20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "system.h" 29 30 #include "midisequencer.h" 31 #include "output.h" 32 33 #include <cassert> 34 #include <algorithm> 35 36 using namespace std::chrono_literals; 37 38 namespace midisequencer{ read_variable_value(void * fp,int (* fgetc)(void *),uint_least32_t * track_length,const char * errtext)39 static uint_least32_t read_variable_value(void* fp, int(*fgetc)(void*), uint_least32_t* track_length, const char* errtext) 40 { 41 int ret = 0; 42 int d; 43 do{ 44 --*track_length; 45 d = fgetc(fp); 46 if(d == EOF){ 47 Output::Warning("Midi sequencer: {}", errtext); 48 } 49 ret <<= 7; 50 ret |= (d & 0x7F); 51 }while(d & 0x80); 52 return ret; 53 } 54 operator <(const midi_message & a,const midi_message & b)55 inline bool operator<(const midi_message& a, const midi_message& b) 56 { 57 return a.time < b.time; 58 } 59 sequencer()60 sequencer::sequencer(): 61 position(messages.begin()) 62 { 63 loop_position = position; 64 } clear()65 void sequencer::clear() 66 { 67 messages.clear(); 68 long_messages.clear(); 69 position = messages.begin(); 70 } rewind()71 void sequencer::rewind() 72 { 73 position = messages.begin(); 74 } 75 rewind_to_loop()76 std::vector<midi_message>::iterator sequencer::rewind_to_loop() 77 { 78 position = loop_position; 79 if (position != messages.begin()) { 80 position--; 81 } 82 return loop_position; 83 } 84 is_at_end()85 bool sequencer::is_at_end() 86 { 87 return position == messages.end(); 88 } load(void * fp,int (* fgetc)(void *))89 bool sequencer::load(void* fp, int(*fgetc)(void*)) 90 { 91 bool result = false; 92 clear(); 93 int b0 = fgetc(fp); 94 int b1 = fgetc(fp); 95 int b2 = fgetc(fp); 96 int b3 = fgetc(fp); 97 if(b0 == 0x4D && b1 == 0x54 && b2 == 0x68 && b3 == 0x64){ 98 load_smf(fp, fgetc); 99 result = true; 100 }else{ 101 Output::Warning("Midi sequencer: unsupported format"); 102 } 103 if(!result){ 104 clear(); 105 } 106 position = messages.begin(); 107 return result; 108 } fpfgetc(void * fp)109 static int fpfgetc(void* fp) 110 { 111 return getc(static_cast<std::FILE*>(fp)); 112 } is_loop_start(uint_least32_t msg)113 static bool is_loop_start(uint_least32_t msg) { 114 // If the message matches the de facto standard MIDI loop instruction: 115 // Which is a Control Change on any channel with Value 111 116 uint8_t event_type = (msg & 0x0000F0) >> 4; 117 uint8_t value1 = (msg & 0x00FF00) >> 8; 118 return event_type == 0b1011 && value1 == 111; 119 } load(std::FILE * fp)120 bool sequencer::load(std::FILE* fp) 121 { 122 return load(fp, fpfgetc); 123 } get_num_ports() const124 int sequencer::get_num_ports()const 125 { 126 int ret = 0; 127 for(const auto& message: messages){ 128 if(ret < message.port){ 129 ret = message.port; 130 } 131 } 132 return ret + 1; 133 } get_total_time() const134 std::chrono::microseconds sequencer::get_total_time()const 135 { 136 if(messages.empty()){ 137 return 0us; 138 }else{ 139 return messages.back().time; 140 } 141 } get_title() const142 std::string sequencer::get_title()const 143 { 144 for(const auto& message: messages){ 145 if(message.track == 0 && (message.message & 0xFF) == 0xFF){ 146 assert((message.message >> 8) < long_messages.size()); 147 const std::string& s = long_messages[message.message >> 8]; 148 if(s.size() > 1 && s[0] == 0x03){ 149 return s.substr(1); 150 } 151 } 152 } 153 return std::string(); 154 } get_copyright() const155 std::string sequencer::get_copyright()const 156 { 157 for(const auto& message: messages){ 158 if(message.track == 0 && (message.message & 0xFF) == 0xFF){ 159 assert((message.message >> 8) < long_messages.size()); 160 const std::string& s = long_messages[message.message >> 8]; 161 if(s.size() > 1 && s[0] == 0x02){ 162 return s.substr(1); 163 } 164 } 165 } 166 return std::string(); 167 } get_song() const168 std::string sequencer::get_song()const 169 { 170 std::string ret; 171 for(const auto& message: messages){ 172 if(message.track == 0 && (message.message & 0xFF) == 0xFF){ 173 assert((message.message >> 8) < long_messages.size()); 174 const std::string& s = long_messages[message.message >> 8]; 175 assert(s.size() >= 1); 176 if(s[0] == 0x05){ 177 ret += s.substr(1); 178 } 179 } 180 } 181 return ret; 182 } play(std::chrono::microseconds time,output * out)183 void sequencer::play(std::chrono::microseconds time, output* out) 184 { 185 if(position != messages.begin() && (position - 1)->time >= time){ 186 position = messages.begin(); 187 } 188 if(position == messages.begin() && position != messages.end() && position->time < time){ 189 out->reset(); 190 } 191 192 while(position != messages.end() && position->time < time){ 193 uint_least32_t message = position->message; 194 int port = position->port; 195 ++position; 196 197 switch(message & 0xFF){ 198 case 0xF0: 199 { 200 assert((message >> 8) < long_messages.size()); 201 const std::string& s = long_messages[static_cast<int>(message >> 8)]; 202 out->sysex_message(port, s.data(), s.size()); 203 } 204 break; 205 case 0xFF: 206 { 207 assert((message >> 8) < long_messages.size()); 208 const std::string& s = long_messages[static_cast<int>(message >> 8)]; 209 assert(s.size() >= 1); 210 out->meta_event(static_cast<unsigned char>(s[0]), s.data() + 1, s.size() - 1); 211 } 212 break; 213 default: 214 out->midi_message(port, message); 215 break; 216 } 217 } 218 } 219 set_time(std::chrono::microseconds time,output * out)220 void sequencer::set_time(std::chrono::microseconds time, output* out) 221 { 222 if(position != messages.begin() && (position - 1)->time >= time){ 223 position = messages.begin(); 224 } 225 if(position == messages.begin() && position != messages.end() && position->time < time){ 226 out->reset(); 227 } 228 229 if(position->time > time) 230 position = messages.begin(); 231 232 while(position != messages.end() && position->time < time){ 233 uint_least32_t message = position->message; 234 int port = position->port; 235 ++position; 236 237 switch(message & 0xFF){ 238 case 0xF0: 239 { 240 assert((message >> 8) < long_messages.size()); 241 const std::string& s = long_messages[static_cast<int>(message >> 8)]; 242 out->sysex_message(port, s.data(), s.size()); 243 } 244 break; 245 case 0xFF: 246 { 247 assert((message >> 8) < long_messages.size()); 248 const std::string& s = long_messages[static_cast<int>(message >> 8)]; 249 assert(s.size() >= 1); 250 out->meta_event(static_cast<unsigned char>(s[0]), s.data() + 1, s.size() - 1); 251 } 252 break; 253 default: 254 255 if((message & 0xF0) == 0x80 || (message & 0xF0) == 0x90) 256 { 257 out->meta_event(META_EVENT_ALL_NOTE_OFF, NULL, 0); 258 break; 259 } 260 261 out->midi_message(port, message); 262 break; 263 } 264 } 265 } 266 get_start_skipping_silence()267 std::chrono::microseconds sequencer::get_start_skipping_silence() { 268 std::vector<midi_message> m; 269 270 for (auto& msg: messages) { 271 // If we find Loop Start before the first NoteOn, just start there 272 if (is_loop_start(msg.message)) { 273 std::chrono::microseconds time = msg.time; 274 // RPG_RT always rewinds "a little" 275 // This amount is based on the tempo, and this 2100000 divisor 276 // I determined experimentally. 277 time = std::max(0us, std::chrono::microseconds(static_cast<int>(time.count() - (msg.tempo / 2.1f)))); 278 return time; 279 } else if ((msg.message & 0xFF) == 0xF0) { 280 // SysEx message. RPG_RT doesn't skip silence if there's a SysEx 281 // message in the beginning, so neither should we... 282 return 0us; 283 } else if ((msg.message & 0xF0) == 0x90) { 284 // NoteOn -- found the first note! 285 std::chrono::microseconds time = msg.time; 286 // RPG_RT always rewinds "a little" 287 // This amount is based on the tempo, and this 2100000 divisor 288 // I determined experimentally. 289 time = std::max(0us, std::chrono::microseconds(static_cast<int>(time.count() - (msg.tempo / 2.1f)))); 290 return time; 291 } 292 } 293 return 0us; 294 } 295 load_smf(void * fp,int (* fgetc)(void *))296 void sequencer::load_smf(void* fp, int(*fgetc)(void*)) 297 { 298 if(fgetc(fp) != 0 299 || fgetc(fp) != 0 300 || fgetc(fp) != 0 301 || fgetc(fp) != 6 302 || fgetc(fp) != 0){ 303 Output::Warning("Midi sequencer: invalid file header"); 304 } 305 int format = fgetc(fp); 306 if(format != 0 && format != 1){ 307 Output::Warning("Midi sequencer: unsupported format type"); 308 } 309 int t0 = fgetc(fp); 310 int t1 = fgetc(fp); 311 unsigned num_tracks = (t0 << 8) | t1; 312 int d0 = fgetc(fp); 313 int d1 = fgetc(fp); 314 division = (d0 << 8) | d1; 315 for(unsigned track = 0; track < num_tracks; ++track){ 316 if(fgetc(fp) != 0x4D || fgetc(fp) != 0x54 || fgetc(fp) != 0x72 || fgetc(fp) != 0x6B){ 317 Output::Warning("Midi sequencer: invalid track header"); 318 } 319 int l0 = fgetc(fp); 320 int l1 = fgetc(fp); 321 int l2 = fgetc(fp); 322 int l3 = fgetc(fp); 323 uint_least32_t track_length = (static_cast<uint_least32_t>(l0) << 24) 324 | (static_cast<uint_least32_t>(l1) << 16) 325 | (l2 << 8) 326 | l3; 327 int running_status = 0; 328 double time_offset = 0; 329 uint_least32_t time = 0; 330 midi_message msg; 331 msg.port = 0; 332 msg.track = track; 333 for(;;){ 334 if(track_length < 4){ 335 Output::Warning("Midi sequencer: unexpected EOF (track_length)"); 336 } 337 uint_least32_t delta = read_variable_value(fp, fgetc, &track_length, "unexpected EOF (deltatime)"); 338 time += delta; 339 if(division & 0x8000){ 340 int fps = ~(division >> 8) + 1; 341 int frames = division & 0xFF; 342 msg.time = std::chrono::microseconds(static_cast<int>(time / (frames * fps) + time_offset)); 343 }else{ 344 msg.time = std::chrono::microseconds(time); 345 } 346 int param = fgetc(fp); 347 --track_length; 348 switch(param){ 349 case 0xF0: 350 { 351 int n = read_variable_value(fp, fgetc, &track_length, "unexpected EOF (sysex length)"); 352 std::string s(n + 1, '\0'); 353 s[0] = static_cast<char>(0xF0); 354 for(int i = 1; i <= n; ++i){ 355 s[i] = static_cast<char>(fgetc(fp)); 356 } 357 if(s[n] != '\xF7'){ 358 Output::Debug("Midi sequencer: missing sysex terminator"); 359 s += static_cast<char>(0xF7); 360 } 361 track_length -= n; 362 msg.message = 0xF0 | (long_messages.size() << 8); 363 messages.push_back(msg); 364 long_messages.push_back(s); 365 } 366 break; 367 case 0xF7: 368 /* unsupported */ 369 /* 370 { 371 int n = read_variable_value(fp, fgetc, &track_length, "unexpected EOF (sysex-F7 length)"); 372 std::string s(n, '\0'); 373 for(int i = 0; i < n; ++i){ 374 s[i] = fgetc(fp); 375 } 376 track_length -= n; 377 msg.message = 0xF0 | (long_messages.size() << 8); 378 messages.push_back(msg); 379 long_messages.push_back(s); 380 } 381 */ 382 break; 383 case 0xFF: 384 { 385 int type = fgetc(fp); 386 --track_length; 387 int n = read_variable_value(fp, fgetc, &track_length, "unexpected EOF (metaevent)"); 388 std::string s(n + 1, '\0'); 389 s[0] = static_cast<char>(type); 390 for(int i = 1; i <= n; ++i){ 391 s[i] = static_cast<char>(fgetc(fp)); 392 } 393 track_length -= n; 394 msg.message = 0xFF | (long_messages.size() << 8); 395 messages.push_back(msg); 396 long_messages.push_back(s); 397 switch(type){ 398 case 0x21: 399 if(n == 1){ 400 msg.port = static_cast<unsigned char>(s[1]); 401 } 402 break; 403 case 0x2F: 404 goto next_track; 405 case 0x54: 406 if(n != 5){ 407 Output::Warning("Midi sequencer: invalid SMTPE offset metaevent length"); 408 } 409 if(msg.time == 0us && (division & 0x8000)){ 410 int hour = static_cast<unsigned char>(s[1]); 411 int min = static_cast<unsigned char>(s[2]); 412 int sec = static_cast<unsigned char>(s[3]); 413 int frame = static_cast<unsigned char>(s[4]); 414 int subframe = static_cast<unsigned char>(s[5]); 415 double fps; 416 switch(hour >> 5){ 417 default: // line added by nextvolume (2015-02-25) 418 case 0: 419 fps = 24; 420 break; 421 case 1: 422 fps = 25; 423 break; 424 case 2: 425 fps = 29.97; 426 break; 427 case 3: 428 fps = 30; 429 break; 430 } 431 time = 0; 432 time_offset = (hour & 0x1F) * 3600 + min * 60 + sec + (frame + subframe / 100.0) * fps; 433 } 434 break; 435 } 436 } 437 break; 438 default: 439 if(param & 0x80){ 440 running_status = param; 441 param = fgetc(fp); 442 --track_length; 443 } 444 switch(running_status & 0xF0){ 445 case 0xC0: 446 case 0xD0: 447 msg.message = running_status | (param << 8); 448 break; 449 case 0x80: 450 case 0x90: 451 case 0xA0: 452 case 0xB0: 453 case 0xE0: 454 msg.message = running_status | (param << 8) | (fgetc(fp) << 16); 455 --track_length; 456 break; 457 default: 458 Output::Warning("Midi sequencer: invalid midi message"); 459 } 460 messages.push_back(msg); 461 break; 462 } 463 } 464 next_track: 465 while(track_length > 0){ 466 if(fgetc(fp) == EOF){ 467 Output::Warning("Midi sequencer: unexpected EOF (tailer padding)"); 468 } 469 --track_length; 470 } 471 } 472 std::stable_sort(messages.begin(), messages.end()); 473 loop_position = messages.begin(); 474 if(!(division & 0x8000)){ 475 uint_least32_t tempo = 500000; 476 std::chrono::microseconds time_offset = 0us; 477 std::chrono::microseconds base = 0us; 478 for(auto i = messages.begin(); i != messages.end(); ++i){ 479 std::chrono::microseconds org_time = i->time; 480 i->time = std::chrono::microseconds(static_cast<int>(static_cast<double>((i->time.count() - base.count())) * tempo / division + time_offset.count())); 481 if((i->message & 0xFF) == 0xFF){ 482 assert((i->message >> 8) < long_messages.size()); 483 const std::string& s = long_messages[i->message >> 8]; 484 if(s.size() == 4 && s[0] == 0x51){ 485 tempo = (static_cast<uint_least32_t>(static_cast<unsigned char>(s[1])) << 16) 486 | (static_cast<unsigned char>(s[2]) << 8) 487 | static_cast<unsigned char>(s[3]); 488 base = org_time; 489 time_offset = i->time; 490 } 491 } 492 i->tempo = tempo; 493 if (is_loop_start(i->message)) { 494 // Loop backwards through the messages to find the first message with the same 495 // timestamp as the loop message 496 for (auto j = i; j != messages.begin() && j->time >= i->time; j--) { 497 loop_position = j; 498 } 499 } 500 } 501 } 502 } 503 get_division() const504 uint32_t sequencer::get_division() const { 505 return division; 506 } 507 } 508