virtual void handleNote(uint8_t note, uint8_t duration) { int octave = noteOctave(note); if(channel < 8) { if(curOctave != octave) { if(curOctave == -1 || curOctave - octave > 1 || octave - curOctave > 1) { mmlf("o%d", octave); } else if(curOctave == octave + 1) { mmlf("<"); } else if(curOctave == octave - 1) { mmlf(">"); } } curOctave = octave; } if(duration > 0) { int mmlDuration; bool dot = false, percent = false; if(192 % duration == 0) { mmlDuration = 192 / duration; } else if(192 % (duration * 2 / 3) == 0 && (duration * 2) % 3 == 0) { dot = true; mmlDuration = 192 * 3 / duration / 2; } else { percent = true; } char buf[100]; if(channel < 8) { sprintf(buf, "%s", noteName(note)); } else { sprintf(buf, "n%d,", note); } if(percent) sprintf(buf + strlen(buf), "%%%d", duration); else sprintf(buf + strlen(buf), "%d", mmlDuration); if(dot) strcat(buf, "."); if(nextKeyOff) strcat(buf, "&"); if(nextPortamento) { int nextNote = note + (nextPortamento * duration + (nextPortamento < 0 ? -16383 : 16383)) / 16384; int nextOctave = noteOctave(nextNote); strcat(buf, "_"); if(nextOctave != octave) sprintf(buf + strlen(buf), "o%d", nextOctave); curOctave = nextOctave; sprintf(buf + strlen(buf), "%s", noteName(nextNote)); } mmlf("%s", buf); } nextKeyOff = false; nextPortamento = 0; }
void Tuner::draw(double time) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); text.print(noteName(notes[currentNote]), 960 - 140, 540 - 16, 32); float level = d.rms(); // scale to 0 .. 1 level = (level - o.noiseRMS) / (o.signalRMS - o.noiseRMS); d.analyze(); float detectedFrequency = d.result(); float cents = centDifference(detectedFrequency, targetFrequency); char textBuf[64]; sprintf(textBuf, "%.0f", cents); text.print(textBuf, 960 - 100, 540 - 16, 32); sprintf(textBuf, "%.2f", level); text.print(textBuf, 960 - 400, 540 - 16, 32); glUseProgram(programId); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId); drawBackground(); glUniform3f(uniformTintId, level, level, level); // clamp to -50 .. +50 float clamped = std::min(std::max(cents, -50.0f), 50.0f); // scale to -45° .. +45° float angle = clamped / 50 * PI / 4; gaugeVertices[2] = 960 + needleLength * cosf(angle); gaugeVertices[3] = gaugePositions[currentNote] + needleLength * sin(angle); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * gaugeVertices.size(), gaugeVertices.data(), GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays(GL_LINES, 0, 2); glDisableVertexAttribArray(0); if (!hit && fabs(cents) < o.precisionCentDelta) { hit = true; hitStart = time; } if (hit && fabs(cents) > o.precisionCentDelta) { hit = false; } if (hit && time - hitStart > o.precisionHoldTime) { nextNote(); } }
//------------------------------------------------------------------------------ const char* noteName(const double & pitch) { return noteName(toInt(pitch)); }