MIDIデータを読み込んで、それを楽譜の模範演奏として表示したいと考えています。
この質問のひとつ前に質問をした時のちょうちょ(音はピアノ)を楽譜で表示すると画像のようになります。
c++
1#include <windows.h> 2#include <iostream> 3#include <fstream> 4#include <iomanip> 5#include <stdio.h> 6#include <time.h> 7#include <process.h> 8 9#include "MIDIIO.h" 10#include "MIDIData.h" 11#include "MIDIClock.h" 12#include <opencv2/opencv.hpp> 13 14SYSTEMTIME stTime; /* 現在時刻獲得用変数 */ 15static char strTime[128]; /* 現在時刻表示用の文字列 */ 16double cur_time; /* 現在時刻の,当日午前0時からの秒数 */ 17 18 19#define SHEET_GAP 20 //楽譜の表示位置の初期の値 20#define NOTE_GAP 60 //音符の表示位置の初期の値 21 22#define NOTE_H 12 //四分音符の表示する高さの初期の値 23#define NOTE_W (NOTE_H * 1.05) //二分音符の表示する高さの初期の値 24#define NOTE_ANGLE (-20) //音符の大きさ 25 26#define SHEET_W (SHEET_GAP * 2 + NOTE_GAP * 4 * 4) //楽譜の横の長さ 27#define SHEET_H (SHEET_GAP * 2 + NOTE_H * 4 + SHEET_GAP * 2) //楽譜の縦の長さ 28 29#define NOTE_OFFSET (12 * 3) //音符表示できる数 30 31#define USE_KEYBOARD 1 //0ならキーボード不使用、1ならキーボード使用 32 33char* winname = "Sheet"; 34 35bool g_bContinue = true; 36 37MIDIIn* pMIDIIn; //MIDIの初期化 38MIDIOut* pMIDIOut; 39 40HANDLE hGetNotesMutex; //ミューテックスのハンドル 41HANDLE hNoteXMutex; 42 43int note_x; 44int note_x_by_midi; 45int note_y[11]; 46int flag[2] = { 1, 1 }; // [0] for midi input, [1] for keyboard input 47 48cv::Mat sheet_base; 49cv::Mat sheet_note; 50cv::Mat sheet_draw; 51cv::Mat sheet_base2[4]; 52 53 54int current_x = SHEET_GAP; 55 56std::vector<int> note_correct_x; 57std::vector<int> note_correct_y; 58 59std::vector<int> note_player_x; 60std::vector<int> note_player_y; 61 62int hitcount = 0; 63double avelen = 0.0; 64double avelen2[4] = { 0.0, 0.0, 0.0, 0.0 }; 65 66void pseudoColor(double index, unsigned char& B, unsigned char& G, unsigned char& R) { //擬似カラーの設定 67 // 0.0 <= index <= 1.0 68 if (0.0 <= index && index <= 0.25) { 69 B = 255; 70 R = 0; 71 G = (int)(256.0 / 64.0 * index * 255.0); 72 } 73 else if (0.25 < index && index <= 0.5) { 74 G = 255; 75 R = 0; 76 B = (int)(-256.0 / 64.0 * index * 255.0 + 511.0); 77 78 } 79 else if (0.5 < index && index <= 0.75) { 80 B = 0; 81 G = 255; 82 R = (int)(256.0 / 64.0 * index * 255.0 - 511.0); 83 } 84 else if (0.75 < index && index <= 1.0) { 85 R = 255; 86 B = 0; 87 G = (int)(-256.0 / 64.0 * index * 255.0 + 256 * 3 - 1); 88 } 89 else { 90 // Error 91 } 92} 93 94void PutNote(cv::Mat& sheet, unsigned char status, unsigned char data1, unsigned char data2, long duration, cv::Scalar color, int note_x, int& index) { //音符の配置 95 96 if ((status & 0xF0) == 0x90 && data2 != 0x00) { 97 98 if (data1 == (0x18 + NOTE_OFFSET)) { // Do C 99 index = 0; 100 } 101 else if (data1 == (0x26 + NOTE_OFFSET)) { // Re D 102 index = 1; 103 } 104 else if (data1 == (0x1C + NOTE_OFFSET)) { // Mi E 105 index = 2; 106 } 107 else if (data1 == (0x1D + NOTE_OFFSET)) { // Fa F 108 index = 3; 109 } 110 else if (data1 == (0x1F + NOTE_OFFSET)) { // So G 111 index = 4; 112 } 113 else if (data1 == (0x21 + NOTE_OFFSET)) { // Ra 114 index = 5; 115 } 116 else if (data1 == (0x23 + NOTE_OFFSET)) { //Shi 117 index = 6; 118 } 119 else if (data1 == (0x24 + NOTE_OFFSET)) { // Do 120 index = 7; 121 } 122 else if (data1 == (0x1A + NOTE_OFFSET)) { // Re 123 index = 8; 124 } 125 else if (data1 == (0x28 + NOTE_OFFSET)) { 126 index = 9; 127 } 128 else if (data1 == (0x19 + NOTE_OFFSET)) { 129 index = 10; 130 } 131 if (index != -1) { 132 if (duration == 120) { 133 cv::ellipse(sheet, cv::Point(note_x, note_y[index]), cv::Size(NOTE_W, NOTE_H / 2), NOTE_ANGLE, 0, 360, color, -1); 134 } 135 else if (duration == 240) { 136 cv::ellipse(sheet, cv::Point(note_x, note_y[index]), cv::Size(NOTE_W, NOTE_H / 2), NOTE_ANGLE, 0, 360, color, 2); 137 } 138 else { 139 } 140 } 141 } 142 else if (status == 0x80 || data2 == 0x00) { 143 } 144} 145 146void PutNoteData(int mode, cv::Mat& sheet, unsigned char status, unsigned char data1, unsigned char data2, long duration, cv::Scalar color, int note_x) { 147 int index = -1; 148 PutNote(sheet, status, data1, data2, duration, color, note_x, index); 149 if (mode == 0) { // 楽譜構築モード 150 note_correct_x.push_back(note_x); 151 note_correct_y.push_back(index); 152 } 153 else if (mode == 1) { // ユーザによる演奏音符反映モード 154 note_player_x.push_back(note_x); 155 note_player_y.push_back(index); 156 } 157 else { 158 // mode == -1 // 時刻に対応する音符反映モード 159 } 160} 161 162unsigned __stdcall GetNotesThread(void *p) 163{ 164 165 long lLen; 166 unsigned char byMessage[256]; 167 168 /* MIDIメッセージの取得ループ */ 169 while (g_bContinue) { 170 WaitForSingleObject(hGetNotesMutex, INFINITE); //mutex 間は他のスレッドから変数を変更できない 171 lLen = MIDIIn_GetMIDIMessage(pMIDIIn, byMessage, 256); 172 ReleaseMutex(hGetNotesMutex); 173 174 /* MIDIメッセージを取得した */ 175 if (lLen > 0) { 176 177 /* スレッド */ 178 WaitForSingleObject(hGetNotesMutex, INFINITE); 179 MIDIOut_PutMIDIMessage(pMIDIOut, byMessage, lLen); 180 for (int i = 0; i < lLen; i++) { 181 std::cerr << "0x" << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)byMessage[i] << " "; 182 } 183 std::cerr << "/ ";; 184 ReleaseMutex(hGetNotesMutex); 185 186 unsigned char status = byMessage[0]; 187 unsigned char data1 = byMessage[1]; 188 unsigned char data2 = byMessage[2]; 189 if ((status & 0xF0) == 0x99 && data2 != 0x00) { 190 hitcount++; 191 192 WaitForSingleObject(hNoteXMutex, INFINITE); //mutex 間は他のスレッドから変数を変更できない 193 PutNoteData(1, sheet_base2[0], status, data1, data2, 120, cv::Scalar(127, 127, 127), current_x); 194 195 int key_x = note_player_x[note_player_x.size() - 1]; 196 int key_y = note_player_y[note_player_y.size() - 1]; 197 198 int nearest_index = 0; 199 int nearest_length = 99999; 200 201 for (int i = 0; i < note_correct_x.size(); i++) { 202 if (abs(note_correct_x[i] - key_x) < nearest_length) { 203 nearest_index = i; 204 nearest_length = abs(note_correct_x[i] - key_x); 205 } 206 } 207 208 int near_x = note_correct_x[nearest_index]; 209 int near_y = note_correct_y[nearest_index]; 210 double diff; 211 212 // CalcPseudoColor 213 unsigned char b, g, r; 214 215 //ずれ情報なし 216 diff = 0.0; 217 pseudoColor(diff, b, g, r); 218 PutNoteData(-1, sheet_base2[0], status, data1, data2, 120, cv::Scalar(b, g, r), current_x); 219 avelen2[0] += diff; 220 221 //時間のずれ 222 diff = abs(key_x - near_x) / 30.0; // 0 ~ 30 223 if (diff > 1.0) { 224 diff = 1.0; 225 } 226 pseudoColor(diff, b, g, r); 227 PutNoteData(-1, sheet_base2[1], status, data1, data2, 120, cv::Scalar(b, g, r), current_x); 228 avelen2[1] += diff; 229 230 //音程のずれ 231 diff = abs((double)key_y - (double)near_y) / 4.0; //高さのindexの差 232 fprintf(stderr, "diff0 = %f\n", diff); 233 if (diff > 1.0) { 234 diff = 1.0; 235 } 236 pseudoColor(diff, b, g, r); 237 PutNoteData(-1, sheet_base2[2], status, data1, data2, 120, cv::Scalar(b, g, r), current_x); 238 avelen2[2] += diff; 239 fprintf(stderr, "diff = %f\n", diff); 240 fprintf(stderr, "hitcount = %d\n", hitcount); 241 242 //音程と時間両方のずれ 243 double diff0 = abs(key_x - near_x) / 30.0; 244 double diff1 = abs((double)key_y - (double)near_y) / 4.0; 245 diff = sqrt(diff0 * diff0 + diff1 * diff1) / sqrt(2.0); 246 if (diff > 1.0) { 247 diff = 1.0; 248 } 249 pseudoColor(diff, b, g, r); 250 PutNoteData(-1, sheet_base2[3], status, data1, data2, 120, cv::Scalar(b, g, r), current_x); 251 avelen2[3] += diff; 252 253 ReleaseMutex(hNoteXMutex); 254 } 255 } 256 /* MIDIメッセージを取得しなかった */ 257 else { 258 /* スリープ処理 */ 259 Sleep(1); 260 } 261 } 262 263 _endthreadex(0); 264 265 return 0; //コンパイラの警告を殺す 266}
これをドラムの音でも同じように楽譜に表示させたいと思うんですが、0x00を0x09に変え、スネアドラムは16進数で0x26なので、ドの0x18を0x26に変えて実行したところ、何も表示されませんでした。midiの音も鳴っていないので、midiの読み込みから失敗しているのでしょうか。ピアノの音のmidiは鳴っています。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/21 14:04
2017/12/21 14:09
2017/12/21 14:29
2017/12/21 14:31
2017/12/21 14:42
2017/12/21 15:18
2017/12/21 15:19 編集
2017/12/21 15:22
2017/12/21 15:23
2017/12/21 15:48
2017/12/21 16:05
2017/12/22 00:58
2017/12/22 02:16
2017/12/22 02:19
2017/12/22 02:29
2017/12/22 02:31 編集
2017/12/22 03:36
2017/12/22 03:39
2018/01/10 07:17