スペクトログラム解析VST3プラグインに拍の表示を追加した。
処理方法
Processorで、IProcessContextRequirementsをインプリメントすることで、拍の情報を受け取ることができる。
ホストから受け取るtempo、timeSigDenominator、timeSigNumerator、projectTimeMusic、barPositionMusicと、サンプリング周波数から現在のブロックが拍の位置か、小節内の何拍目かを計算する必要がある。
ややこしいので、GPT-5で生成したコードをそのまま使った。
uint8_t VstCqtProcessor::computeBeatClass (const Vst::ProcessData& data, int sampleIndexInBlock) const { using namespace Steinberg::Vst; const ProcessContext* ctx = data.processContext; if (!ctx) return 0; const double tempo = ctx->tempo; // assume host provides valid fields when non-null if (!(tempo > 0.0)) return 0; const int den = (std::max)(1, static_cast<int> (ctx->timeSigDenominator)); const int num = (std::max)(1, static_cast<int> (ctx->timeSigNumerator)); const double beatLenQN = 4.0 / static_cast<double> (den); // length of one beat in quarter notes const double barLenQN = beatLenQN * static_cast<double> (num); const double qnPerSample = tempo / (60.0 * (std::max)(1.0, sampleRate_)); const double dq = static_cast<double> (sampleIndexInBlock) * qnPerSample; const double qNotesIntoBar = (ctx->projectTimeMusic + dq) - ctx->barPositionMusic; // wrap to [0, period) auto wrapMod = [] (double x, double p) -> double { double k = std::floor (x / p); x -= k * p; if (x < 0.0) x += p; return x; }; const double qnBeatMod = wrapMod (qNotesIntoBar, beatLenQN); const double qnBarMod = wrapMod (qNotesIntoBar, barLenQN); // tolerance: half of the quarter-notes advanced between analysis columns const double qnPerColumn = tempo / (60.0 * ANALYZE_FPS); const double eps = (std::max)(1e-4, qnPerColumn * 0.5); bool atBeat = (qnBeatMod <= eps) || ((beatLenQN - qnBeatMod) <= eps); bool atBar = (qnBarMod <= eps) || ((barLenQN - qnBarMod) <= eps); if (atBar) return 2; // thick line if (atBeat) return 1; // thin line return 0; }
まとめ
スペクトログラムに拍の位置を表示するようにした。
次は、基本周波数解析を実装したい。
