void CTrackList::refresh() { int chan; int rowCount = 0; m_trackQtList.clear(); for (chan = 0; chan < MAX_MIDI_CHANNELS; chan++) { if (m_midiActiveChannels[chan] == true) { CTrackListItem trackItem; trackItem.midiChannel = chan; m_trackQtList.append(trackItem); rowCount++; } } if (pianoPartConvetionTest()) { if (CNote::bothHandsChan() == -2 ) // -2 for not set -1 for not used CNote::setChannelHands(CONVENTION_LEFT_HAND_CHANNEL, CONVENTION_RIGHT_HAND_CHANNEL); m_song->setActiveChannel(CNote::bothHandsChan()); ppLogInfo("Active both"); } else { if (m_trackQtList.count() > 0) { m_song->setActiveChannel(m_trackQtList[0].midiChannel); } } if (CStavePos::getKeySignature() == NOT_USED) CStavePos::setKeySignature(guessKeySignature(CNote::rightHandChan(),CNote::leftHandChan()), 0); // Find an unused channel that we can use for the keyboard m_song->reset(); int goodChan = findFreeChannel(0); int badChan = findFreeChannel(goodChan + 1); int spareChan = findFreeChannel(badChan +1 ); if (badChan == -1) { // As we have not found two we have not found to empty channels to use goodChan = 15 -1; badChan = 16-1; } m_song->setPianistChannels(goodChan,badChan); ppLogInfo("Using Pianist Channels %d + %d", goodChan +1, badChan +1); if (Cfg::keyboardLightsChan != -1 && spareChan != -1) m_song->mapTrack2Channel(Cfg::keyboardLightsChan, spareChan); }
void MusicPlayer::callback() { if (!_isPlaying) return; _musicTimer += _musicTicks; if (_musicTimer < _timerLimit) return; _musicTimer -= _timerLimit; --_nextEventTimer; if (_nextEventTimer) return; while (true) { uint8_t command = _file.at(_curOffset++); if (command == 0xFF) { command = _file.at(_curOffset++); if (command == 47) { // End of track _isPlaying = false; return; } else if (command == 88) { // This is proposedly a debug information insertion. The CMS // player code handles this differently, but is still using // the same resources... _curOffset += 5; } else if (command == 81) { uint16_t timing = _file.at(_curOffset + 2) | (_file.at(_curOffset + 1) << 8); _musicTicks = 0x73000 / timing; command = _file.at(_curOffset++); _curOffset += command; } else { command = _file.at(_curOffset++); _curOffset += command; } } else { if (command >= 0x90) { command -= 0x90; const uint16_t instrOffset = _instrumentOffset[command]; if (instrOffset) { if (_file.at(instrOffset + 13) != 0) { setupRhythm(_file[instrOffset + 13], instrOffset); } else { uint8_t channel = findFreeChannel(); if (channel != 0xFF) { noteOff(channel); setupChannel(channel, instrOffset); _channelLastEvent[channel] = command + 0x90; _channelFrequency[channel] = _file.at(_curOffset); setupFrequency(channel, _file[_curOffset]); } } } } else { const uint8_t note = _file.at(_curOffset); command += 0x10; uint8_t channel = 0xFF; for (uint8_t i = 0; i < _voiceChannels; ++i) { if (_channelFrequency[i] == note && _channelLastEvent[i] == command) { channel = i; break; } } if (channel != 0xFF) { noteOff(channel); } else { command -= 0x90; const uint16_t instrOffset = _instrumentOffset[command]; if (instrOffset && _file.at(instrOffset + 13) != 0) { const uint8_t rhythmInstr = _file[instrOffset + 13]; //if (rhythmInstr >= 6) // throw std::range_error("rhythmInstr >= 6"); if (rhythmInstr < 6) { _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF; writeReg(0xBD, _mdvdrState); } } } } _curOffset += 2; } if (_file.at(_curOffset) != 0) break; ++_curOffset; } _nextEventTimer = _file.at(_curOffset++); if (_nextEventTimer & 0x80) { _nextEventTimer -= 0x80; _nextEventTimer <<= 7; _nextEventTimer |= _file.at(_curOffset++); } _nextEventTimer >>= _isLoom ? 2 : 1; if (!_nextEventTimer) _nextEventTimer = 1; }