-
Notifications
You must be signed in to change notification settings - Fork 1
MIDIビジュアライザー
Reputeless edited this page Mar 14, 2017
·
3 revisions
# include <Siv3D.hpp>
struct Note
{
uint32 ch;
uint32 noteNumber;
int32 startMillisec;
int32 lengthMillisec;
double alpha;
bool barPassed;
bool onBar;
};
void Main()
{
Window::Resize(1280, 720);
Midi::Open(Dialog::GetOpenMidi().value());
const auto score = Midi::GetScore();
Array<Note> noteRects;
uint32 minPitch = 127, maxPitch = 0;
for (auto ch : step(static_cast<uint32>(score.size())))
{
for (const auto& note : score[ch])
{
noteRects.push_back({ ch, note.noteNumber, note.startMillisec, note.lengthMillisec, 1.0, false, false });
minPitch = Min(minPitch, note.noteNumber);
maxPitch = Max(maxPitch, note.noteNumber);
}
}
while (System::Update())
{
const double scale = 0.2;
const int32 offset = 160;
const int32 offsetMillisec = static_cast<int32>(offset / scale);
const RectF line(offset - 1, 0, 6, Window::Height());
const double blockHeight = static_cast<double>(Window::Height()) / (maxPitch - minPitch + 1);
if (!Midi::IsPlaying())
{
for (auto& note : noteRects)
{
note.alpha = 1.0;
note.barPassed = false;
note.onBar = false;
}
}
if (Input::MouseL.clicked)
{
Midi::Play();
}
const double pos = (Midi::GetPosSec() * 1000 - 100)* scale;
const int32 bar = static_cast<int32>(Midi::GetPosSec() * 1000 - 100);
const int32 left = bar - offsetMillisec;
const int32 right = static_cast<int32>(left + Window::Width() / scale);
Array<size_t> visibleNoteIndices;
size_t index = 0;
for (auto& note : noteRects)
{
if (right < note.startMillisec || (note.startMillisec + note.lengthMillisec) < left)
{
++index;
continue;
}
note.onBar = note.startMillisec <= bar && bar <= (note.startMillisec + note.lengthMillisec);
note.barPassed = note.startMillisec <= bar;
if (note.barPassed)
{
note.alpha *= note.onBar ? 0.98 : 0.85;
}
visibleNoteIndices.push_back(index++);
}
Graphics2D::SetBlendState(BlendState::Default);
for (auto& i : visibleNoteIndices)
{
const auto& note = noteRects[i];
if (!note.barPassed)
{
const RectF r(note.startMillisec * scale + offset - pos, (maxPitch - note.noteNumber) * blockHeight, note.lengthMillisec * scale, blockHeight);
RoundRect(r, 4).draw(ColorF(0.2, 0.25, 0.3));
}
}
Graphics2D::SetBlendState(BlendState::Additive);
for (auto& i : visibleNoteIndices)
{
const auto& note = noteRects[i];
if (note.barPassed)
{
const RectF r(note.startMillisec * scale + offset - pos, (maxPitch - note.noteNumber) * blockHeight, note.lengthMillisec * scale, blockHeight);
RoundRect(r, 5).drawShadow({ 0, 0 }, 12 + note.alpha * 8, 2 + note.alpha * 8, HSV(30 + note.ch * 100, 0.5, 1).toColorF(note.alpha*0.4));
}
}
for (auto& i : visibleNoteIndices)
{
const auto& note = noteRects[i];
if (note.barPassed)
{
const RectF r(note.startMillisec * scale + offset - pos, (maxPitch - note.noteNumber) * blockHeight, note.lengthMillisec * scale, blockHeight);
RoundRect(r, 4).draw(HSV(30 + note.ch * 100, 1, 1).toColorF(note.alpha));
}
}
line.draw(Alpha(20));
}
}
- Siv3D の基本
- 図形を描く
- テクスチャを描く
- テキストを描く
- 文字列と数値の変換
- キーボード入力
- マウス入力
- サウンドの再生
- MIDI の再生
- ウィンドウと背景
- 図形のあたり判定
- 乱数
- ダイアログ
- ドラッグ & ドロップ
- アプリの状態
- テキストファイル
- INI, CSV, JSON
- バイナリファイル
- GUI
- アセット管理
- 画像編集
- Web カメラ
- マイク入力
- 経過時間の測定
- HSV カラー
- ファイルダウンロード
- 3D 描画
- 2D のレンダーステート
- 3D のレンダーステート
- パーティクル
- スクリーンショット
- アプリケーションの公開
- さらに学ぶには
- アプリランチャーを作ろう
- 音楽プレイヤーを作ろう
- 横スクロールゲームを作ろう
- ドット絵エディタを作ろう
- シーン遷移をサポートする SceneManager の使い方
- Siv3D ミニサンプル集
- タスクシステムを使う
- スケッチ
- 画像ビューアー
- オーディオスペクトラム
- マイク入力スペクトラム
- 文字色の反転
- 天気予報
- ドットお絵かき
- 15パズル
- ブロックくずし
- 時計
- 音楽プレイヤー
- ピアノ
- ライフゲーム
- シーン管理
- 地球
- 3Dシーン
- 3D交差判定
- Wooden Mirror
- シューティングゲーム
- Image to Polygon
- Sketch to Polygon
- 軌跡
- Plot3D
- テンポとピッチの変更
- 長方形の影
- Twitterクライアント
- Polygon to Mesh
- 3Dテキスト
- アプリ終了の確認
- 地形の生成
- アーカイブファイル
- GUIのアニメーション
- Aero Glassエフェクト
- Glitch
- リンクテキスト
- 付箋
- シーン切り替え(シルエット)
- MIDIシーケンサー
- 数つなぎ
- 画面を揺らす
- 対称定規
- aobench
- MIDIビジュアライザー
- 電卓
- 手書き文字認識
- 顔検出
- 音声合成
- Image to PhysicsBody