1 module pxtone.master;
2 // '12/03/03
3 
4 import pxtone.pxtn;
5 
6 import pxtone.descriptor;
7 import pxtone.error;
8 import pxtone.evelist;
9 import pxtone.util;
10 
11 /////////////////////////////////
12 // file io
13 /////////////////////////////////
14 
15 // master info(8byte) ================
16 struct _x4x_MASTER {
17 	ushort data_num; // data-num is 3 ( clock / status / volume )
18 	ushort rrr;
19 	uint event_num;
20 }
21 
22 struct pxtnMaster {
23 private:
24 	int _beat_num = EVENTDEFAULT_BEATNUM;
25 	float _beat_tempo = EVENTDEFAULT_BEATTEMPO;
26 	int _beat_clock = EVENTDEFAULT_BEATCLOCK;
27 	int _meas_num = 1;
28 	int _repeat_meas;
29 	int _last_meas;
30 	int _volume_;
31 
32 public:
33 	void Reset() nothrow @safe {
34 		_beat_num = EVENTDEFAULT_BEATNUM;
35 		_beat_tempo = EVENTDEFAULT_BEATTEMPO;
36 		_beat_clock = EVENTDEFAULT_BEATCLOCK;
37 		_meas_num = 1;
38 		_repeat_meas = 0;
39 		_last_meas = 0;
40 	}
41 
42 	void Set(int beat_num, float beat_tempo, int beat_clock) nothrow @safe {
43 		_beat_num = beat_num;
44 		_beat_tempo = beat_tempo;
45 		_beat_clock = beat_clock;
46 	}
47 
48 	void Get(int* p_beat_num, float* p_beat_tempo, int* p_beat_clock, int* p_meas_num) const nothrow @safe {
49 		if (p_beat_num) {
50 			*p_beat_num = _beat_num;
51 		}
52 		if (p_beat_tempo) {
53 			*p_beat_tempo = _beat_tempo;
54 		}
55 		if (p_beat_clock) {
56 			*p_beat_clock = _beat_clock;
57 		}
58 		if (p_meas_num) {
59 			*p_meas_num = _meas_num;
60 		}
61 	}
62 
63 	int get_beat_num() const nothrow @safe {
64 		return _beat_num;
65 	}
66 
67 	float get_beat_tempo() const nothrow @safe {
68 		return _beat_tempo;
69 	}
70 
71 	int get_beat_clock() const nothrow @safe {
72 		return _beat_clock;
73 	}
74 
75 	int get_meas_num() const nothrow @safe {
76 		return _meas_num;
77 	}
78 
79 	int get_repeat_meas() const nothrow @safe {
80 		return _repeat_meas;
81 	}
82 
83 	int get_last_meas() const nothrow @safe {
84 		return _last_meas;
85 	}
86 
87 	int get_last_clock() const nothrow @safe {
88 		return _last_meas * _beat_clock * _beat_num;
89 	}
90 
91 	int get_play_meas() const nothrow @safe {
92 		if (_last_meas) {
93 			return _last_meas;
94 		}
95 		return _meas_num;
96 	}
97 
98 	void set_meas_num(int meas_num) nothrow @safe {
99 		if (meas_num < 1) {
100 			meas_num = 1;
101 		}
102 		if (meas_num <= _repeat_meas) {
103 			meas_num = _repeat_meas + 1;
104 		}
105 		if (meas_num < _last_meas) {
106 			meas_num = _last_meas;
107 		}
108 		_meas_num = meas_num;
109 	}
110 
111 	void set_repeat_meas(int meas) nothrow @safe {
112 		if (meas < 0) {
113 			meas = 0;
114 		}
115 		_repeat_meas = meas;
116 	}
117 
118 	void set_last_meas(int meas) nothrow @safe {
119 		if (meas < 0) {
120 			meas = 0;
121 		}
122 		_last_meas = meas;
123 	}
124 
125 	void set_beat_clock(int beat_clock) nothrow @safe {
126 		if (beat_clock < 0) {
127 			beat_clock = 0;
128 		}
129 		_beat_clock = beat_clock;
130 	}
131 
132 	void AdjustMeasNum(int clock) nothrow @safe {
133 		int m_num;
134 		int b_num;
135 
136 		b_num = (clock + _beat_clock - 1) / _beat_clock;
137 		m_num = (b_num + _beat_num - 1) / _beat_num;
138 		if (_meas_num <= m_num) {
139 			_meas_num = m_num;
140 		}
141 		if (_repeat_meas >= _meas_num) {
142 			_repeat_meas = 0;
143 		}
144 		if (_last_meas > _meas_num) {
145 			_last_meas = _meas_num;
146 		}
147 	}
148 
149 	int get_this_clock(int meas, int beat, int clock) const nothrow @safe {
150 		return _beat_num * _beat_clock * meas + _beat_clock * beat + clock;
151 	}
152 
153 	void io_w_v5(ref pxtnDescriptor p_doc, int rough) const @safe {
154 
155 		uint size = 15;
156 		short bclock = cast(short)(_beat_clock / rough);
157 		int clock_repeat = bclock * _beat_num * get_repeat_meas();
158 		int clock_last = bclock * _beat_num * get_last_meas();
159 		byte bnum = cast(byte) _beat_num;
160 		float btempo = _beat_tempo;
161 		p_doc.w_asfile(size);
162 		p_doc.w_asfile(bclock);
163 		p_doc.w_asfile(bnum);
164 		p_doc.w_asfile(btempo);
165 		p_doc.w_asfile(clock_repeat);
166 		p_doc.w_asfile(clock_last);
167 	}
168 
169 	void io_r_v5(ref pxtnDescriptor p_doc) @safe {
170 		short beat_clock = 0;
171 		byte beat_num = 0;
172 		float beat_tempo = 0;
173 		int clock_repeat = 0;
174 		int clock_last = 0;
175 
176 		uint size = 0;
177 
178 		p_doc.r(size);
179 		if (size != 15) {
180 			throw new PxtoneException("fmt unknown");
181 		}
182 
183 		p_doc.r(beat_clock);
184 		p_doc.r(beat_num);
185 		p_doc.r(beat_tempo);
186 		p_doc.r(clock_repeat);
187 		p_doc.r(clock_last);
188 
189 		_beat_clock = beat_clock;
190 		_beat_num = beat_num;
191 		_beat_tempo = beat_tempo;
192 
193 		set_repeat_meas(clock_repeat / (beat_num * beat_clock));
194 		set_last_meas(clock_last / (beat_num * beat_clock));
195 	}
196 
197 	int io_r_v5_EventNum(ref pxtnDescriptor p_doc) @safe {
198 		uint size;
199 		p_doc.r(size);
200 		if (size != 15) {
201 			return 0;
202 		}
203 		byte[15] buf;
204 		p_doc.r(buf[]);
205 		return 5;
206 	}
207 
208 	void io_r_x4x(ref pxtnDescriptor p_doc) @safe {
209 		_x4x_MASTER mast;
210 		int size = 0;
211 		int e = 0;
212 		int status = 0;
213 		int clock = 0;
214 		int volume = 0;
215 		int absolute = 0;
216 
217 		int beat_clock, beat_num, repeat_clock, last_clock;
218 		float beat_tempo = 0;
219 
220 		p_doc.r(size);
221 		p_doc.r(mast);
222 
223 		// unknown format
224 		if (mast.data_num != 3) {
225 			throw new PxtoneException("fmt unknown");
226 		}
227 		if (mast.rrr) {
228 			throw new PxtoneException("fmt unknown");
229 		}
230 
231 		beat_clock = EVENTDEFAULT_BEATCLOCK;
232 		beat_num = EVENTDEFAULT_BEATNUM;
233 		beat_tempo = EVENTDEFAULT_BEATTEMPO;
234 		repeat_clock = 0;
235 		last_clock = 0;
236 
237 		absolute = 0;
238 
239 		for (e = 0; e < cast(int) mast.event_num; e++) {
240 			p_doc.v_r(status);
241 			p_doc.v_r(clock);
242 			p_doc.v_r(volume);
243 			absolute += clock;
244 			clock = absolute;
245 
246 			switch (status) {
247 			case EVENTKIND.BEATCLOCK:
248 				beat_clock = volume;
249 				if (clock) {
250 					throw new PxtoneException("desc broken");
251 				}
252 				break;
253 			case EVENTKIND.BEATTEMPO:
254 				beat_tempo = reinterpretInt(volume);
255 				if (clock) {
256 					throw new PxtoneException("desc broken");
257 				}
258 				break;
259 			case EVENTKIND.BEATNUM:
260 				beat_num = volume;
261 				if (clock) {
262 					throw new PxtoneException("desc broken");
263 				}
264 				break;
265 			case EVENTKIND.REPEAT:
266 				repeat_clock = clock;
267 				if (volume) {
268 					throw new PxtoneException("desc broken");
269 				}
270 				break;
271 			case EVENTKIND.LAST:
272 				last_clock = clock;
273 				if (volume) {
274 					throw new PxtoneException("desc broken");
275 				}
276 				break;
277 			default:
278 				throw new PxtoneException("fmt unknown");
279 			}
280 		}
281 
282 		if (e != mast.event_num) {
283 			throw new PxtoneException("desc broken");
284 		}
285 
286 		_beat_num = beat_num;
287 		_beat_tempo = beat_tempo;
288 		_beat_clock = beat_clock;
289 
290 		set_repeat_meas(repeat_clock / (beat_num * beat_clock));
291 		set_last_meas(last_clock / (beat_num * beat_clock));
292 	}
293 
294 	int io_r_x4x_EventNum(ref pxtnDescriptor p_doc) @safe {
295 		_x4x_MASTER mast;
296 		int size;
297 		int work;
298 		int e;
299 
300 		p_doc.r(size);
301 		p_doc.r(mast);
302 
303 		if (mast.data_num != 3) {
304 			return 0;
305 		}
306 
307 		for (e = 0; e < cast(int) mast.event_num; e++) {
308 			p_doc.v_r(work);
309 			p_doc.v_r(work);
310 			p_doc.v_r(work);
311 		}
312 
313 		return mast.event_num;
314 	}
315 }