-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsmfIO.cpp
147 lines (124 loc) · 3.51 KB
/
smfIO.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#define _CRT_SECURE_NO_WARNINGS
#include "smfIO.h"
#include "stdio.h"
#include <string.h>
smfIO::smfIO() {
int check = 1;
if (*(char *)&check) IsLittleEndian = true;
else IsLittleEndian = false;
header.type.c[0] = 'M'; header.type.c[1] = 'T'; header.type.c[2] = 'h'; header.type.c[3] = 'd';
header.size.i = 6;
header.format.i = 1;
header.track.i = 18; // ここ注意
header.division.i = 480;
}
void smfIO::ConvertEndian(UIntInByte& input, size_t s) {
char *tmp;
tmp = new char[s];
for (int i = 0; i < s; ++i) {
tmp[i] = input.c[i];
}
for (int i = 1; i <= s; ++i) {
input.c[i - 1] = tmp[s - i];
}
delete[] tmp;
}
unsigned char* smfIO::getTrackData(int t) {
return track[t].data;
}
int smfIO::getTrackSize(int t) {
return track[t].size.i;
}
int smfIO::read(char* fileName) {
FILE* fp;
if ((fp = fopen(fileName, "rb")) == NULL) {
return -1;
}
// ヘッダチャンク読み取り
fread(&header.type, 4, 1, fp);
fread(&header.size, 4, 1, fp);
fread(&header.format, 2, 1, fp);
fread(&header.track, 2, 1, fp);
fread(&header.division, 2, 1, fp);
if (IsLittleEndian) {
ConvertEndian(header.size, 4);
ConvertEndian(header.format, 2);
ConvertEndian(header.track, 2);
ConvertEndian(header.division, 2);
}
// トラックチャンク読み取り
if (track != NULL) delete[] track;
track = new TrackChunk[header.track.i];
for (int i = 0; i < header.track.i; ++i) {
fread(&track[i].type, 4, 1, fp);
fread(&track[i].size, 4, 1, fp);
if (IsLittleEndian) {
ConvertEndian(track[i].size, 4);
}
// TODO メモリリークのおそれ
// if (track[i].data != NULL) delete[] track[i].data;
track[i].data = new unsigned char[track[i].size.i];
fread(track[i].data, track[i].size.i, sizeof(char), fp);
}
fclose(fp);
return 0;
}
int smfIO::getTrackNum() {
return header.track.i;
}
void smfIO::kakikomi(FILE* fp, UIntInByte& input, int size, bool convertFlag) {
if (IsLittleEndian && convertFlag) {
for (int i = size - 1; i >= 0; --i) {
fputc(input.c[i], fp);
}
}
else fwrite(&input, size, 1, fp);
}
int smfIO::write(char* fileName, unsigned char* data, int size) {
FILE* fp;
if ((fp = fopen(fileName, "wb")) == NULL) {
return -1;
}
// ヘッダチャンク書き込み
kakikomi(fp, header.type, 4, false);
kakikomi(fp, header.size, 4);
kakikomi(fp, header.format, 2);
kakikomi(fp, header.track, 2);
kakikomi(fp, header.division, 2);
// トラックチャンク書き込み
for (int i = 0; i < header.track.i; ++i) {
if (i == 3) {
// 引数からサイズとデータのアドレスを受け取る
track[i].size.i = size;
//track[i].data = new char[size];
track[i].data = data;
}
// ここ書き込んだ後にもう一回track[i].sizeが必要になるから2回ConvertEndianが必要なんだなあ
fwrite(&track[i].type, 4, 1, fp);
if (IsLittleEndian) {
ConvertEndian(track[i].size, 4);
}
fwrite(&track[i].size, 4, 1, fp);
if (IsLittleEndian) {
ConvertEndian(track[i].size, 4);
}
// データ書き込み
fwrite(track[i].data, 1, track[i].size.i, fp);
}
fclose(fp);
return 0;
}
void smfIO::draw() {
printfDx("ヘッダチャンク情報\n");
printfDx("タイプ:%c%c%c%c", header.type.c[0], header.type.c[1], header.type.c[2], header.type.c[3]);
printfDx(", サイズ:%d", header.size.i);
printfDx(", フォーマット:%d", header.format.i);
printfDx(", トラック数:%d", header.track.i);
printfDx(", 分解能:%d\n", header.division.i);
for (int i = 0; i < header.track.i; ++i) {
printfDx("トラック[%02d]", i);
printfDx(", タイプ:%c%c%c%c", track[i].type.c[0], track[i].type.c[1], track[i].type.c[2], track[i].type.c[3]);
printfDx(", サイズ:%d", track[i].size.i);
printfDx("\n");
}
}