void Arpeggiator::process() { mopo_float frequency = input(kFrequency)->at(0); float min_gate = (MIN_VOICE_TIME + VOICE_KILL_TIME) * frequency; mopo_float gate = INTERPOLATE(min_gate, 1.0, input(kGate)->at(0)); mopo_float delta_phase = frequency / sample_rate_; mopo_float new_phase = phase_ + buffer_size_ * delta_phase; // If we're past the gate phase and we're playing a note, turn it off. if (new_phase >= gate && last_played_note_ >= 0) { int offset = CLAMP((gate - phase_) / delta_phase, 0, buffer_size_ - 1); note_handler_->noteOff(last_played_note_, offset); last_played_note_ = -1; } // Check if it's time to play the next note. if (getNumNotes() && new_phase >= 1) { int offset = CLAMP((1 - phase_) / delta_phase, 0, buffer_size_ - 1); std::pair<mopo_float, mopo_float> note = getNextNote(); note_handler_->noteOn(note.first, note.second, offset); last_played_note_ = note.first; phase_ = new_phase - 1.0; } else phase_ = new_phase; }
int Player_Mac::readBuffer(int16 *data, const int numSamples) { Common::StackLock lock(_mutex); memset(data, 0, numSamples * 2); if (_soundPlaying == -1) { return numSamples; } bool notesLeft = false; for (int i = 0; i < _numberOfChannels; i++) { if (!(_channelMask & (1 << i))) { continue; } uint samplesLeft = numSamples; int16 *ptr = data; while (samplesLeft > 0) { int generated; if (_channel[i]._remaining == 0) { uint32 samples; int pitchModifier; byte velocity; if (getNextNote(i, samples, pitchModifier, velocity)) { _channel[i]._remaining = samples; _channel[i]._pitchModifier = pitchModifier; _channel[i]._velocity = velocity; } else { _channel[i]._pitchModifier = 0; _channel[i]._velocity = 0; _channel[i]._remaining = samplesLeft; } } generated = MIN<uint32>(_channel[i]._remaining, samplesLeft); if (_channel[i]._velocity != 0) { _channel[i]._instrument.generateSamples(ptr, _channel[i]._pitchModifier, _channel[i]._velocity, generated, _channel[i]._remaining, _fadeNoteEnds); } ptr += generated; samplesLeft -= generated; _channel[i]._remaining -= generated; } if (_channel[i]._notesLeft) { notesLeft = true; } } if (!notesLeft) { stopAllSounds_Internal(); } return numSamples; }
bool hasNoteWithHammerOn(const Voice &voice, const Position &pos) { for (const Note ¬e : pos.getNotes()) { if (note.hasProperty(Note::HammerOnOrPullOff)) { const Note *nextNote = getNextNote(voice, pos.getPosition(), note.getString()); return nextNote && nextNote->getFretNumber() > note.getFretNumber(); } } return false; }
void OSUSTANDARD::genAccTimings(Play* _play) { accTimings.clear(); std::vector<osu::TIMING>().swap(accTimings); play = _play; const int KEYS = 2; std::tuple<long, int, int> frame; Hitobject *prevNotes, *currNotes, *nextNotes; // Frame vars int iFrame = -1; bool stop = false; // process each column individualy int iNote; // keep track where we are on the map bool nextNote; // whether to fetch next note on column or not std::vector<bool> pressStates; // which state we are expecting pressStates.resize(KEYS); // init vars for each column { iNote = -1; currNotes = getNextNote(&iNote); nextNotes = getNextNote(&iNote); nextNote = false; for (int key = 0; key < KEYS; key++) pressStates[key] = true; } // get first frame frame = getNextEvent(&iFrame); do // key press-release processor { int keyPresses = std::get<1>(frame); int keyReleases = std::get<2>(frame); for (int key = 0; key < KEYS; key++) { bool valid = (((keyPresses & (1 << key)) > 0) && (pressStates[key] == true)) || (((keyReleases & (1 << key)) > 0) && (pressStates[key] == false)); // if there is a key event on a column er are expecting if (valid) { int hitTiming = INT_MAX; int hitState = 1; if (currNotes != nullptr) { if (pressStates[key] == true) // if we are pressing the key { hitState = SCORE::getJudgment(std::get<0>(frame), currNotes->getTime(), pressStates[key]); hitTiming = std::get<0>(frame) - currNotes->getTime(); } else // if we are releasing the key { hitState = SCORE::getJudgment(std::get<0>(frame), currNotes->getEndTime(), pressStates[key]); hitTiming = std::get<0>(frame) - currNotes->getEndTime(); } SCORE::KeyInfo info = {}; info.hitTiming = hitTiming; info.key = key; info.nextNote = &nextNote; info.pressState = &pressStates; switch (hitState) { case 0: // hit SCORE::processHit(&accTimings, currNotes, info); break; case 1: // hit and miss SCORE::processMiss(&accTimings, currNotes, info); break; case 2: // never hit the note SCORE::processMiss(&accTimings, currNotes, info); // get next note if (nextNote == true) { prevNotes = currNotes; currNotes = nextNotes; nextNotes = getNextNote(&iNote); nextNote = false; } // redo this frame key--; continue; break; case 3: // no hit, no miss break; default: break; }; } } // get next note if (nextNote == true) { prevNotes = currNotes; currNotes = nextNotes; nextNotes = getNextNote(&iNote); nextNote = false; } } frame = getNextEvent(&iFrame); // get next press/release whatever column it is stop = !(iFrame < play->replay->getNumFrames()); // stop when we reached end of replay } while (!stop); std::sort(accTimings.begin(), accTimings.end(), sortAccTimings); }
void MusicPlayer::nextNote() { getNextNote(); startNoteTimer(); }
bool canHammerOnOrPullOff(const Voice &voice, int position, const Note ¬e) { const Note *nextNote = getNextNote(voice, position, note.getString()); return nextNote && nextNote->getFretNumber() != note.getFretNumber(); }
// fill buff int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) { ToneChan *tpcm; Tone toneNew; int fillSize; int retVal; tpcm = &_tchannel[chan]; retVal = -1; while (len > 0) { if (tpcm->noteCount <= 0) { // get new tone data toneNew.freqCount = 0; toneNew.atten = 0xF; toneNew.type = kGenTone; if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) { tpcm->atten = toneNew.atten; tpcm->freqCount = toneNew.freqCount; tpcm->genType = toneNew.type; // setup counters 'n stuff // SAMPLE_RATE samples per sec.. tone changes 60 times per sec tpcm->noteCount = SAMPLE_RATE / 60; retVal = 0; } else { // if it doesn't return an tpcm->genType = kGenSilence; tpcm->noteCount = len; tpcm->avail = 0; } } // write nothing if ((tpcm->freqCount == 0) || (tpcm->atten == 0xf)) { tpcm->genType = kGenSilence; } // find which is smaller.. the buffer or the fillSize = (tpcm->noteCount <= len) ? tpcm->noteCount : len; switch (tpcm->genType) { case kGenTone: fillSize = fillSquare(tpcm, stream, fillSize); break; case kGenPeriod: case kGenWhite: fillSize = fillNoise(tpcm, stream, fillSize); break; case kGenSilence: default: // fill with whitespace memset(stream, 0, fillSize * sizeof(int16)); break; } tpcm->noteCount -= fillSize; stream += fillSize; len -= fillSize; } return retVal; }