int main(int argc, char* argv[]) { char filename[] = "doom-e1m1.mid"; RtMidiOut *midiout = new RtMidiOut(); string portName; nPorts = midiout->getPortCount(); if(argc < 2) { if ( nPorts == 0 ) cout << "No ports available!\n"; for ( unsigned int i=0; i<nPorts; i++ ) { try { portName = midiout->getPortName(i); } catch (RtError &error) {error.printMessage(); } cout << " Output Port #" << i+1 << ": " << portName << '\n'; } }else{ int port = atoi(argv[1]); //midiout->openPort( port ); cout << "Opening midi" << endl; char *filef = argv[2]; if(argc == 3) parser.Open(filef); else parser.Open(filename); tickspersecond = ( (parser.bpm / 30.0) * ( parser.tpb)); cout << " Ticks per second: " << tickspersecond << endl; (void) signal(SIGINT, finish); tickcount = 0; Sequencer sequencers[parser.numtracks]; SequencerRunning = true; for(int i=0;i<parser.numtracks;i++) { sequencers[i].StartSequencer(i, &parser.mididata.tracks[i], port); sf::Sleep(0.01f); } sf::Sleep(1); timer.Reset(); while(run) { timecount = timer.GetElapsedTime(); tickcount += timecount * tickspersecond; timer.Reset(); //sf::Sleep(0.0001f); } } delete midiout; finish(0); return 0; }
void SoundGenMIDI::play(int resnum) { MIDISound *track; stop(); _isGM = true; track = (MIDISound *)_vm->_game.sounds[resnum]; // Convert AGI Sound data to MIDI int midiMusicSize = convertSND2MIDI(track->_data, &_midiData); MidiParser *parser = MidiParser::createParser_SMF(); if (parser->loadMusic(_midiData, midiMusicSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); _parser = parser; syncVolume(); _isPlaying = true; } else { delete parser; } }
void MidiMusicPlayer::playXMIDI(uint32 size, bool loop) { // It seems like not all music (the main menu music, for instance) set // all the instruments explicitly. That means the music will sound // different, depending on which music played before it. This appears // to be a genuine glitch in the original. For consistency, reset all // instruments to the default one (piano). for (int i = 0; i < 16; i++) { _driver->send(0xC0 | i, 0, 0); } // Load XMID resource data MidiParser *parser = MidiParser::createParser_XMIDI(); if (parser->loadMusic(g_midiBuffer.pDat, size)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _parser = parser; _isLooping = loop; _isPlaying = true; } else { delete parser; } }
void MusicPlayer::playSMF(int track, bool loop) { Common::StackLock lock(_mutex); if (_isPlaying && track == _track) { debugC(2, kDraciSoundDebugLevel, "Already plaing track %d", track); return; } stop(); _isGM = true; // Load MIDI resource data Common::File musicFile; Common::String musicFileName = Common::String::format(_pathMask.c_str(), track); musicFile.open(musicFileName.c_str()); if (!musicFile.isOpen()) { debugC(2, kDraciSoundDebugLevel, "Cannot open track %d", track); return; } int midiMusicSize = musicFile.size(); free(_midiData); _midiData = (byte *)malloc(midiMusicSize); musicFile.read(_midiData, midiMusicSize); musicFile.close(); MidiParser *parser = MidiParser::createParser_SMF(); if (parser->loadMusic(_midiData, midiMusicSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); _parser = parser; syncVolume(); _isLooping = loop; _isPlaying = true; _track = track; debugC(2, kDraciSoundDebugLevel, "Playing track %d", track); } else { debugC(2, kDraciSoundDebugLevel, "Cannot play track %d", track); delete parser; } }
TestExitStatus MidiTests::playMidiMusic() { Testsuite::clearScreen(); Common::String info = "Testing Midi Sound output.\n" "Here, We generate some Music by using the Midi Driver selected in the GUI.\n" "You should expect to hear that. The initialization may take some time.\n"; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : Play Midi Music\n"); return kTestSkipped; } MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); // Create a driver instance MidiDriver *driver = MidiDriver::createMidi(dev); // Create a SMF parser MidiParser *smfParser = MidiParser::createParser_SMF(); // Open the driver int errCode = driver->open(); if (errCode) { Common::String errMsg = driver->getErrorName(errCode); Testsuite::writeOnScreen(errMsg, Common::Point(0, 100)); Testsuite::logPrintf("Error! %s", errMsg.c_str()); return kTestFailed; } Testsuite::logDetailedPrintf("Info! Midi: Succesfully opened the driver\n"); Common::MemoryWriteStreamDynamic ws(DisposeAfterUse::YES); loadMusicInMemory(&ws); // start playing if (smfParser->loadMusic(ws.getData(), ws.size())) { smfParser->setTrack(0); smfParser->setMidiDriver(driver); smfParser->setTimerRate(driver->getBaseTempo()); driver->setTimerCallback(smfParser, MidiParser::timerCallback); Testsuite::logDetailedPrintf("Info! Midi: Parser Successfully loaded Music data.\n"); if (smfParser->isPlaying()) { Testsuite::writeOnScreen("Playing Midi Music, Click to end.", Common::Point(0, 100)); Testsuite::logDetailedPrintf("Info! Midi: Playing music!\n"); } } // Play until track ends or an exit is requested. waitForMusicToPlay(smfParser); // Done. Clean up. smfParser->unloadMusic(); driver->setTimerCallback(NULL, NULL); driver->close(); delete smfParser; delete driver; if (Testsuite::handleInteractiveInput("Were you able to hear the music as described?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Error! Midi: Can't play Music\n"); return kTestFailed; } return kTestPassed; }
void MidiMusicPlayer::playSEQ(uint32 size, bool loop) { // MIDI.DAT holds the file names in DW1 PSX Common::String baseName((char *)g_midiBuffer.pDat, size); Common::String seqName = baseName + ".SEQ"; // TODO: Load the instrument bank (<baseName>.VB and <baseName>.VH) Common::File seqFile; if (!seqFile.open(seqName)) error("Failed to open SEQ file '%s'", seqName.c_str()); if (seqFile.readUint32LE() != MKTAG('S', 'E', 'Q', 'p')) error("Failed to find SEQp tag"); // Make sure we don't have a SEP file (with multiple SEQ's inside) if (seqFile.readUint32BE() != 1) error("Can only play SEQ files, not SEP"); uint16 ppqn = seqFile.readUint16BE(); uint32 tempo = seqFile.readUint16BE() << 8; tempo |= seqFile.readByte(); /* uint16 beat = */ seqFile.readUint16BE(); // SEQ is directly based on SMF and we'll use that to our advantage here // and convert to SMF and then use the SMF MidiParser. // Calculate the SMF size we'll need uint32 dataSize = seqFile.size() - 15; uint32 actualSize = dataSize + 7 + 22; // Resize the buffer if necessary if (g_midiBuffer.size < actualSize) { g_midiBuffer.pDat = (byte *)realloc(g_midiBuffer.pDat, actualSize); assert(g_midiBuffer.pDat); } // Now construct the header WRITE_BE_UINT32(g_midiBuffer.pDat, MKTAG('M', 'T', 'h', 'd')); WRITE_BE_UINT32(g_midiBuffer.pDat + 4, 6); // header size WRITE_BE_UINT16(g_midiBuffer.pDat + 8, 0); // type 0 WRITE_BE_UINT16(g_midiBuffer.pDat + 10, 1); // one track WRITE_BE_UINT16(g_midiBuffer.pDat + 12, ppqn); WRITE_BE_UINT32(g_midiBuffer.pDat + 14, MKTAG('M', 'T', 'r', 'k')); WRITE_BE_UINT32(g_midiBuffer.pDat + 18, dataSize + 7); // SEQ data size + tempo change event size // Add in a fake tempo change event WRITE_BE_UINT32(g_midiBuffer.pDat + 22, 0x00FF5103); // no delta, meta event, tempo change, param size = 3 WRITE_BE_UINT16(g_midiBuffer.pDat + 26, tempo >> 8); g_midiBuffer.pDat[28] = tempo & 0xFF; // Now copy in the rest of the events seqFile.read(g_midiBuffer.pDat + 29, dataSize); seqFile.close(); MidiParser *parser = MidiParser::createParser_SMF(); if (parser->loadMusic(g_midiBuffer.pDat, actualSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _parser = parser; _isLooping = loop; _isPlaying = true; } else { delete parser; } }