質問編集履歴

1

プログラムのint mainまでの部分を追記しました。

2017/12/21 14:30

投稿

zakky79
zakky79

スコア23

test CHANGED
File without changes
test CHANGED
@@ -4,95 +4,281 @@
4
4
 
5
5
  ```c++
6
6
 
7
+ #include <windows.h>
8
+
9
+ #include <iostream>
10
+
11
+ #include <fstream>
12
+
13
+ #include <iomanip>
14
+
15
+ #include <stdio.h>
16
+
17
+ #include <time.h>
18
+
19
+ #include <process.h>
20
+
21
+
22
+
23
+ #include "MIDIIO.h"
24
+
25
+ #include "MIDIData.h"
26
+
27
+ #include "MIDIClock.h"
28
+
29
+ #include <opencv2/opencv.hpp>
30
+
31
+
32
+
33
+ SYSTEMTIME stTime; /* 現在時刻獲得用変数 */
34
+
35
+ static char strTime[128]; /* 現在時刻表示用の文字列 */
36
+
37
+ double cur_time; /* 現在時刻の,当日午前0時からの秒数 */
38
+
39
+
40
+
41
+
42
+
43
+ #define SHEET_GAP 20 //楽譜の表示位置の初期の値
44
+
45
+ #define NOTE_GAP 60 //音符の表示位置の初期の値
46
+
47
+
48
+
49
+ #define NOTE_H 12 //四分音符の表示する高さの初期の値
50
+
51
+ #define NOTE_W (NOTE_H * 1.05) //二分音符の表示する高さの初期の値
52
+
53
+ #define NOTE_ANGLE (-20) //音符の大きさ
54
+
55
+
56
+
57
+ #define SHEET_W (SHEET_GAP * 2 + NOTE_GAP * 4 * 4) //楽譜の横の長さ
58
+
59
+ #define SHEET_H (SHEET_GAP * 2 + NOTE_H * 4 + SHEET_GAP * 2) //楽譜の縦の長さ
60
+
61
+
62
+
63
+ #define NOTE_OFFSET (12 * 3) //音符表示できる数
64
+
65
+
66
+
67
+ #define USE_KEYBOARD 1 //0ならキーボード不使用、1ならキーボード使用
68
+
69
+
70
+
71
+ char* winname = "Sheet";
72
+
73
+
74
+
75
+ bool g_bContinue = true;
76
+
77
+
78
+
79
+ MIDIIn* pMIDIIn; //MIDIの初期化
80
+
81
+ MIDIOut* pMIDIOut;
82
+
83
+
84
+
85
+ HANDLE hGetNotesMutex; //ミューテックスのハンドル
86
+
87
+ HANDLE hNoteXMutex;
88
+
89
+
90
+
91
+ int note_x;
92
+
93
+ int note_x_by_midi;
94
+
95
+ int note_y[11];
96
+
97
+ int flag[2] = { 1, 1 }; // [0] for midi input, [1] for keyboard input
98
+
99
+
100
+
101
+ cv::Mat sheet_base;
102
+
103
+ cv::Mat sheet_note;
104
+
105
+ cv::Mat sheet_draw;
106
+
107
+ cv::Mat sheet_base2[4];
108
+
109
+
110
+
111
+
112
+
113
+ int current_x = SHEET_GAP;
114
+
115
+
116
+
117
+ std::vector<int> note_correct_x;
118
+
119
+ std::vector<int> note_correct_y;
120
+
121
+
122
+
123
+ std::vector<int> note_player_x;
124
+
125
+ std::vector<int> note_player_y;
126
+
127
+
128
+
129
+ int hitcount = 0;
130
+
131
+ double avelen = 0.0;
132
+
133
+ double avelen2[4] = { 0.0, 0.0, 0.0, 0.0 };
134
+
135
+
136
+
137
+ void pseudoColor(double index, unsigned char& B, unsigned char& G, unsigned char& R) { //擬似カラーの設定
138
+
139
+ // 0.0 <= index <= 1.0
140
+
141
+ if (0.0 <= index && index <= 0.25) {
142
+
143
+ B = 255;
144
+
145
+ R = 0;
146
+
147
+ G = (int)(256.0 / 64.0 * index * 255.0);
148
+
149
+ }
150
+
151
+ else if (0.25 < index && index <= 0.5) {
152
+
153
+ G = 255;
154
+
155
+ R = 0;
156
+
157
+ B = (int)(-256.0 / 64.0 * index * 255.0 + 511.0);
158
+
159
+
160
+
161
+ }
162
+
163
+ else if (0.5 < index && index <= 0.75) {
164
+
165
+ B = 0;
166
+
167
+ G = 255;
168
+
169
+ R = (int)(256.0 / 64.0 * index * 255.0 - 511.0);
170
+
171
+ }
172
+
173
+ else if (0.75 < index && index <= 1.0) {
174
+
175
+ R = 255;
176
+
177
+ B = 0;
178
+
179
+ G = (int)(-256.0 / 64.0 * index * 255.0 + 256 * 3 - 1);
180
+
181
+ }
182
+
183
+ else {
184
+
185
+ // Error
186
+
187
+ }
188
+
189
+ }
190
+
191
+
192
+
7
- void PutNote(cv::Mat& sheet, unsigned char status, unsigned char data1, unsigned char data2, long duration, cv::Scalar color, int note_x, int& index){ //音符の配置
193
+ void PutNote(cv::Mat& sheet, unsigned char status, unsigned char data1, unsigned char data2, long duration, cv::Scalar color, int note_x, int& index) { //音符の配置
8
-
9
-
10
-
194
+
195
+
196
+
11
- if (status == 0x90 && data2 != 0x00){
197
+ if ((status & 0xF0) == 0x90 && data2 != 0x00) {
12
-
13
-
14
-
198
+
199
+
200
+
15
- if (data1 == (0x18 + NOTE_OFFSET)){ // Do C
201
+ if (data1 == (0x18 + NOTE_OFFSET)) { // Do C
16
202
 
17
203
  index = 0;
18
204
 
19
205
  }
20
206
 
21
- else if (data1 == (0x1A + NOTE_OFFSET)){ // Re D
207
+ else if (data1 == (0x26 + NOTE_OFFSET)) { // Re D
22
208
 
23
209
  index = 1;
24
210
 
25
211
  }
26
212
 
27
- else if (data1 == (0x1C + NOTE_OFFSET)){ // Mi E
213
+ else if (data1 == (0x1C + NOTE_OFFSET)) { // Mi E
28
214
 
29
215
  index = 2;
30
216
 
31
217
  }
32
218
 
33
- else if (data1 == (0x1D + NOTE_OFFSET)){ // Fa F
219
+ else if (data1 == (0x1D + NOTE_OFFSET)) { // Fa F
34
220
 
35
221
  index = 3;
36
222
 
37
223
  }
38
224
 
39
- else if (data1 == (0x1F + NOTE_OFFSET)){ // So G
225
+ else if (data1 == (0x1F + NOTE_OFFSET)) { // So G
40
226
 
41
227
  index = 4;
42
228
 
43
229
  }
44
230
 
45
- else if (data1 == (0x21 + NOTE_OFFSET)){ // Ra
231
+ else if (data1 == (0x21 + NOTE_OFFSET)) { // Ra
46
232
 
47
233
  index = 5;
48
234
 
49
235
  }
50
236
 
51
- else if (data1 == (0x23 + NOTE_OFFSET)){ //Shi
237
+ else if (data1 == (0x23 + NOTE_OFFSET)) { //Shi
52
238
 
53
239
  index = 6;
54
240
 
55
241
  }
56
242
 
57
- else if (data1 == (0x24 + NOTE_OFFSET)){ // Do
243
+ else if (data1 == (0x24 + NOTE_OFFSET)) { // Do
58
244
 
59
245
  index = 7;
60
246
 
61
247
  }
62
248
 
63
- else if (data1 == (0x26 + NOTE_OFFSET)){ // Re
249
+ else if (data1 == (0x1A + NOTE_OFFSET)) { // Re
64
250
 
65
251
  index = 8;
66
252
 
67
253
  }
68
254
 
69
- else if (data1 == (0x28 + NOTE_OFFSET)){
255
+ else if (data1 == (0x28 + NOTE_OFFSET)) {
70
256
 
71
257
  index = 9;
72
258
 
73
259
  }
74
260
 
75
- else if (data1 == (0x19 + NOTE_OFFSET)){
261
+ else if (data1 == (0x19 + NOTE_OFFSET)) {
76
262
 
77
263
  index = 10;
78
264
 
79
265
  }
80
266
 
81
- if (index != -1){
267
+ if (index != -1) {
82
-
268
+
83
- if (duration == 120){
269
+ if (duration == 120) {
84
270
 
85
271
  cv::ellipse(sheet, cv::Point(note_x, note_y[index]), cv::Size(NOTE_W, NOTE_H / 2), NOTE_ANGLE, 0, 360, color, -1);
86
272
 
87
273
  }
88
274
 
89
- else if (duration == 240){
275
+ else if (duration == 240) {
90
276
 
91
277
  cv::ellipse(sheet, cv::Point(note_x, note_y[index]), cv::Size(NOTE_W, NOTE_H / 2), NOTE_ANGLE, 0, 360, color, 2);
92
278
 
93
279
  }
94
280
 
95
- else{
281
+ else {
96
282
 
97
283
  }
98
284
 
@@ -100,7 +286,7 @@
100
286
 
101
287
  }
102
288
 
103
- else if (status == 0x80 || data2 == 0x00){
289
+ else if (status == 0x80 || data2 == 0x00) {
104
290
 
105
291
  }
106
292
 
@@ -108,6 +294,248 @@
108
294
 
109
295
 
110
296
 
297
+ void PutNoteData(int mode, cv::Mat& sheet, unsigned char status, unsigned char data1, unsigned char data2, long duration, cv::Scalar color, int note_x) {
298
+
299
+ int index = -1;
300
+
301
+ PutNote(sheet, status, data1, data2, duration, color, note_x, index);
302
+
303
+ if (mode == 0) { // 楽譜構築モード
304
+
305
+ note_correct_x.push_back(note_x);
306
+
307
+ note_correct_y.push_back(index);
308
+
309
+ }
310
+
311
+ else if (mode == 1) { // ユーザによる演奏音符反映モード
312
+
313
+ note_player_x.push_back(note_x);
314
+
315
+ note_player_y.push_back(index);
316
+
317
+ }
318
+
319
+ else {
320
+
321
+ // mode == -1 // 時刻に対応する音符反映モード
322
+
323
+ }
324
+
325
+ }
326
+
327
+
328
+
329
+ unsigned __stdcall GetNotesThread(void *p)
330
+
331
+ {
332
+
333
+
334
+
335
+ long lLen;
336
+
337
+ unsigned char byMessage[256];
338
+
339
+
340
+
341
+ /* MIDIメッセージの取得ループ */
342
+
343
+ while (g_bContinue) {
344
+
345
+ WaitForSingleObject(hGetNotesMutex, INFINITE); //mutex 間は他のスレッドから変数を変更できない
346
+
347
+ lLen = MIDIIn_GetMIDIMessage(pMIDIIn, byMessage, 256);
348
+
349
+ ReleaseMutex(hGetNotesMutex);
350
+
351
+
352
+
353
+ /* MIDIメッセージを取得した */
354
+
355
+ if (lLen > 0) {
356
+
357
+
358
+
359
+ /* スレッド */
360
+
361
+ WaitForSingleObject(hGetNotesMutex, INFINITE);
362
+
363
+ MIDIOut_PutMIDIMessage(pMIDIOut, byMessage, lLen);
364
+
365
+ for (int i = 0; i < lLen; i++) {
366
+
367
+ std::cerr << "0x" << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)byMessage[i] << " ";
368
+
369
+ }
370
+
371
+ std::cerr << "/ ";;
372
+
373
+ ReleaseMutex(hGetNotesMutex);
374
+
375
+
376
+
377
+ unsigned char status = byMessage[0];
378
+
379
+ unsigned char data1 = byMessage[1];
380
+
381
+ unsigned char data2 = byMessage[2];
382
+
383
+ if ((status & 0xF0) == 0x99 && data2 != 0x00) {
384
+
385
+ hitcount++;
386
+
387
+
388
+
389
+ WaitForSingleObject(hNoteXMutex, INFINITE); //mutex 間は他のスレッドから変数を変更できない
390
+
391
+ PutNoteData(1, sheet_base2[0], status, data1, data2, 120, cv::Scalar(127, 127, 127), current_x);
392
+
393
+
394
+
395
+ int key_x = note_player_x[note_player_x.size() - 1];
396
+
397
+ int key_y = note_player_y[note_player_y.size() - 1];
398
+
399
+
400
+
401
+ int nearest_index = 0;
402
+
403
+ int nearest_length = 99999;
404
+
405
+
406
+
407
+ for (int i = 0; i < note_correct_x.size(); i++) {
408
+
409
+ if (abs(note_correct_x[i] - key_x) < nearest_length) {
410
+
411
+ nearest_index = i;
412
+
413
+ nearest_length = abs(note_correct_x[i] - key_x);
414
+
415
+ }
416
+
417
+ }
418
+
419
+
420
+
421
+ int near_x = note_correct_x[nearest_index];
422
+
423
+ int near_y = note_correct_y[nearest_index];
424
+
425
+ double diff;
426
+
427
+
428
+
429
+ // CalcPseudoColor
430
+
431
+ unsigned char b, g, r;
432
+
433
+
434
+
435
+ //ずれ情報なし
436
+
437
+ diff = 0.0;
438
+
439
+ pseudoColor(diff, b, g, r);
440
+
441
+ PutNoteData(-1, sheet_base2[0], status, data1, data2, 120, cv::Scalar(b, g, r), current_x);
442
+
443
+ avelen2[0] += diff;
444
+
445
+
446
+
447
+ //時間のずれ
448
+
449
+ diff = abs(key_x - near_x) / 30.0; // 0 ~ 30
450
+
451
+ if (diff > 1.0) {
452
+
453
+ diff = 1.0;
454
+
455
+ }
456
+
457
+ pseudoColor(diff, b, g, r);
458
+
459
+ PutNoteData(-1, sheet_base2[1], status, data1, data2, 120, cv::Scalar(b, g, r), current_x);
460
+
461
+ avelen2[1] += diff;
462
+
463
+
464
+
465
+ //音程のずれ
466
+
467
+ diff = abs((double)key_y - (double)near_y) / 4.0; //高さのindexの差
468
+
469
+ fprintf(stderr, "diff0 = %f\n", diff);
470
+
471
+ if (diff > 1.0) {
472
+
473
+ diff = 1.0;
474
+
475
+ }
476
+
477
+ pseudoColor(diff, b, g, r);
478
+
479
+ PutNoteData(-1, sheet_base2[2], status, data1, data2, 120, cv::Scalar(b, g, r), current_x);
480
+
481
+ avelen2[2] += diff;
482
+
483
+ fprintf(stderr, "diff = %f\n", diff);
484
+
485
+ fprintf(stderr, "hitcount = %d\n", hitcount);
486
+
487
+
488
+
489
+ //音程と時間両方のずれ
490
+
491
+ double diff0 = abs(key_x - near_x) / 30.0;
492
+
493
+ double diff1 = abs((double)key_y - (double)near_y) / 4.0;
494
+
495
+ diff = sqrt(diff0 * diff0 + diff1 * diff1) / sqrt(2.0);
496
+
497
+ if (diff > 1.0) {
498
+
499
+ diff = 1.0;
500
+
501
+ }
502
+
503
+ pseudoColor(diff, b, g, r);
504
+
505
+ PutNoteData(-1, sheet_base2[3], status, data1, data2, 120, cv::Scalar(b, g, r), current_x);
506
+
507
+ avelen2[3] += diff;
508
+
509
+
510
+
511
+ ReleaseMutex(hNoteXMutex);
512
+
513
+ }
514
+
515
+ }
516
+
517
+ /* MIDIメッセージを取得しなかった */
518
+
519
+ else {
520
+
521
+ /* スリープ処理 */
522
+
523
+ Sleep(1);
524
+
525
+ }
526
+
527
+ }
528
+
529
+
530
+
531
+ _endthreadex(0);
532
+
533
+
534
+
535
+ return 0; //コンパイラの警告を殺す
536
+
537
+ }
538
+
111
539
  ```
112
540
 
113
541
  これをドラムの音でも同じように楽譜に表示させたいと思うんですが、0x00を0x09に変え、スネアドラムは16進数で0x26なので、ドの0x18を0x26に変えて実行したところ、何も表示されませんでした。midiの音も鳴っていないので、midiの読み込みから失敗しているのでしょうか。ピアノの音のmidiは鳴っています。