1 module pxtone.evelist;
2 
3 import pxtone.descriptor;
4 import pxtone.error;
5 import pxtone.util;
6 
7 ///////////////////////
8 // global
9 ///////////////////////
10 
11 bool Evelist_Kind_IsTail(int kind) nothrow @safe {
12 	if (kind == EVENTKIND.ON || kind == EVENTKIND.PORTAMENT) {
13 		return true;
14 	}
15 	return false;
16 }
17 
18 enum EVENTKIND {
19 	NULL = 0, //  0
20 
21 	ON, //  1
22 	KEY, //  2
23 	PAN_VOLUME, //  3
24 	VELOCITY, //  4
25 	VOLUME, //  5
26 	PORTAMENT, //  6
27 	BEATCLOCK, //  7
28 	BEATTEMPO, //  8
29 	BEATNUM, //  9
30 	REPEAT, // 10
31 	LAST, // 11
32 	VOICENO, // 12
33 	GROUPNO, // 13
34 	TUNING, // 14
35 	PAN_TIME, // 15
36 
37 	NUM, // 16
38 }
39 
40 enum EVENTDEFAULT_VOLUME = 104;
41 enum EVENTDEFAULT_VELOCITY = 104;
42 enum EVENTDEFAULT_PAN_VOLUME = 64;
43 enum EVENTDEFAULT_PAN_TIME = 64;
44 enum EVENTDEFAULT_PORTAMENT = 0;
45 enum EVENTDEFAULT_VOICENO = 0;
46 enum EVENTDEFAULT_GROUPNO = 0;
47 enum EVENTDEFAULT_KEY = 0x6000;
48 enum EVENTDEFAULT_BASICKEY = 0x4500; // 4A(440Hz?)
49 enum EVENTDEFAULT_TUNING = 1.0f;
50 
51 enum EVENTDEFAULT_BEATNUM = 4;
52 enum EVENTDEFAULT_BEATTEMPO = 120;
53 enum EVENTDEFAULT_BEATCLOCK = 480;
54 
55 struct EVERECORD {
56 	ubyte kind;
57 	ubyte unit_no;
58 	ubyte reserve1;
59 	ubyte reserve2;
60 	int value;
61 	int clock;
62 	EVERECORD* prev;
63 	EVERECORD* next;
64 }
65 
66 int _DefaultKindValue(ubyte kind) nothrow @safe {
67 	switch (kind) {
68 		//	case EVENTKIND.ON        : return ;
69 	case EVENTKIND.KEY:
70 		return EVENTDEFAULT_KEY;
71 	case EVENTKIND.PAN_VOLUME:
72 		return EVENTDEFAULT_PAN_VOLUME;
73 	case EVENTKIND.VELOCITY:
74 		return EVENTDEFAULT_VELOCITY;
75 	case EVENTKIND.VOLUME:
76 		return EVENTDEFAULT_VOLUME;
77 	case EVENTKIND.PORTAMENT:
78 		return EVENTDEFAULT_PORTAMENT;
79 	case EVENTKIND.BEATCLOCK:
80 		return EVENTDEFAULT_BEATCLOCK;
81 	case EVENTKIND.BEATTEMPO:
82 		return EVENTDEFAULT_BEATTEMPO;
83 	case EVENTKIND.BEATNUM:
84 		return EVENTDEFAULT_BEATNUM;
85 		//	case EVENTKIND.REPEAT    : return ;
86 		//	case EVENTKIND.LAST      : return ;
87 	case EVENTKIND.VOICENO:
88 		return EVENTDEFAULT_VOICENO;
89 	case EVENTKIND.GROUPNO:
90 		return EVENTDEFAULT_GROUPNO;
91 	case EVENTKIND.TUNING:
92 		return reinterpretFloat(EVENTDEFAULT_TUNING);
93 	case EVENTKIND.PAN_TIME:
94 		return EVENTDEFAULT_PAN_TIME;
95 	default:
96 		break;
97 	}
98 	return 0;
99 }
100 
101 int _ComparePriority(ubyte kind1, ubyte kind2) nothrow @safe {
102 	static immutable int[EVENTKIND.NUM] priority_table = [0, // EVENTKIND.NULL  = 0
103 		50, // EVENTKIND.ON
104 		40, // EVENTKIND.KEY
105 		60, // EVENTKIND.PAN_VOLUME
106 		70, // EVENTKIND.VELOCITY
107 		80, // EVENTKIND.VOLUME
108 		30, // EVENTKIND.PORTAMENT
109 		0, // EVENTKIND.BEATCLOCK
110 		0, // EVENTKIND.BEATTEMPO
111 		0, // EVENTKIND.BEATNUM
112 		0, // EVENTKIND.REPEAT
113 		255, // EVENTKIND.LAST
114 		10, // EVENTKIND.VOICENO
115 		20, // EVENTKIND.GROUPNO
116 		90, // EVENTKIND.TUNING
117 		100, // EVENTKIND.PAN_TIME
118 		];
119 
120 	return priority_table[kind1] - priority_table[kind2];
121 }
122 
123 // event struct(12byte) =================
124 struct _x4x_EVENTSTRUCT {
125 	ushort unit_index;
126 	ushort event_kind;
127 	ushort data_num; // 1イベントのデータ数。現在は 2 ( clock / volume )
128 	ushort rrr;
129 	uint event_num;
130 }
131 
132 //--------------------------------
133 
134 struct pxtnEvelist {
135 
136 private:
137 
138 	int _eve_allocated_num;
139 	EVERECORD[] _eves;
140 	EVERECORD* _start;
141 	int _linear;
142 
143 	EVERECORD* _p_x4x_rec;
144 
145 	void _rec_set(EVERECORD* p_rec, EVERECORD* prev, EVERECORD* next, int clock, ubyte unit_no, ubyte kind, int value) nothrow @safe {
146 		if (prev) {
147 			prev.next = p_rec;
148 		} else {
149 			_start = p_rec;
150 		}
151 		if (next) {
152 			next.prev = p_rec;
153 		}
154 
155 		p_rec.next = next;
156 		p_rec.prev = prev;
157 		p_rec.clock = clock;
158 		p_rec.kind = kind;
159 		p_rec.unit_no = unit_no;
160 		p_rec.value = value;
161 	}
162 
163 	void _rec_cut(EVERECORD* p_rec) nothrow @safe {
164 		if (p_rec.prev) {
165 			p_rec.prev.next = p_rec.next;
166 		} else {
167 			_start = p_rec.next;
168 		}
169 		if (p_rec.next) {
170 			p_rec.next.prev = p_rec.prev;
171 		}
172 		p_rec.kind = EVENTKIND.NULL;
173 	}
174 
175 public:
176 
177 	void Release() nothrow @system {
178 		_eves = null;
179 		_start = null;
180 		_eve_allocated_num = 0;
181 	}
182 
183 	void Clear() nothrow @system {
184 		if (_eves) {
185 			_eves[0 .. _eve_allocated_num] = EVERECORD.init;
186 		}
187 		_start = null;
188 	}
189 
190 	~this() nothrow @system {
191 		Release();
192 	}
193 
194 	void Allocate(int max_event_num) @system {
195 		Release();
196 		_eves = new EVERECORD[](max_event_num);
197 		if (!(_eves)) {
198 			throw new PxtoneException("Unable to allocate memory");
199 		}
200 		_eves[0 .. max_event_num] = EVERECORD.init;
201 		_eve_allocated_num = max_event_num;
202 	}
203 
204 	int get_Num_Max() const nothrow @safe {
205 		if (!_eves) {
206 			return 0;
207 		}
208 		return _eve_allocated_num;
209 	}
210 
211 	int get_Max_Clock() const nothrow @safe {
212 		int max_clock = 0;
213 		int clock;
214 
215 		for (const(EVERECORD)* p = _start; p; p = p.next) {
216 			if (Evelist_Kind_IsTail(p.kind)) {
217 				clock = p.clock + p.value;
218 			} else {
219 				clock = p.clock;
220 			}
221 			if (clock > max_clock) {
222 				max_clock = clock;
223 			}
224 		}
225 
226 		return max_clock;
227 
228 	}
229 
230 	int get_Count() const nothrow @safe {
231 		if (!_eves || !_start) {
232 			return 0;
233 		}
234 
235 		int count = 0;
236 		for (const(EVERECORD)* p = _start; p; p = p.next) {
237 			count++;
238 		}
239 		return count;
240 	}
241 
242 	int get_Count(ubyte kind, int value) const nothrow @safe {
243 		if (!_eves) {
244 			return 0;
245 		}
246 
247 		int count = 0;
248 		for (const(EVERECORD)* p = _start; p; p = p.next) {
249 			if (p.kind == kind && p.value == value) {
250 				count++;
251 			}
252 		}
253 		return count;
254 	}
255 
256 	int get_Count(ubyte unit_no) const nothrow @safe {
257 		if (!_eves) {
258 			return 0;
259 		}
260 
261 		int count = 0;
262 		for (const(EVERECORD)* p = _start; p; p = p.next) {
263 			if (p.unit_no == unit_no) {
264 				count++;
265 			}
266 		}
267 		return count;
268 	}
269 
270 	int get_Count(ubyte unit_no, ubyte kind) const nothrow @safe {
271 		if (!_eves) {
272 			return 0;
273 		}
274 
275 		int count = 0;
276 		for (const(EVERECORD)* p = _start; p; p = p.next) {
277 			if (p.unit_no == unit_no && p.kind == kind) {
278 				count++;
279 			}
280 		}
281 		return count;
282 	}
283 
284 	int get_Count(int clock1, int clock2, ubyte unit_no) const nothrow @safe {
285 		if (!_eves) {
286 			return 0;
287 		}
288 
289 		const(EVERECORD)* p;
290 		for (p = _start; p; p = p.next) {
291 			if (p.unit_no == unit_no) {
292 				if (p.clock >= clock1) {
293 					break;
294 				}
295 				if (Evelist_Kind_IsTail(p.kind) && p.clock + p.value > clock1) {
296 					break;
297 				}
298 			}
299 		}
300 
301 		int count = 0;
302 		for (; p; p = p.next) {
303 			if (p.clock != clock1 && p.clock >= clock2) {
304 				break;
305 			}
306 			if (p.unit_no == unit_no) {
307 				count++;
308 			}
309 		}
310 		return count;
311 	}
312 
313 	int get_Value(int clock, ubyte unit_no, ubyte kind) const nothrow @system {
314 		if (!_eves) {
315 			return 0;
316 		}
317 
318 		const(EVERECORD)* p;
319 		int val = _DefaultKindValue(kind);
320 
321 		for (p = _start; p; p = p.next) {
322 			if (p.clock > clock) {
323 				break;
324 			}
325 			if (p.unit_no == unit_no && p.kind == kind) {
326 				val = p.value;
327 			}
328 		}
329 
330 		return val;
331 	}
332 
333 	const(EVERECORD)* get_Records() const nothrow @safe {
334 		if (!_eves) {
335 			return null;
336 		}
337 		return _start;
338 	}
339 
340 	bool Record_Add_i(int clock, ubyte unit_no, ubyte kind, int value) nothrow @system {
341 		if (!_eves) {
342 			return false;
343 		}
344 
345 		EVERECORD* p_new = null;
346 		EVERECORD* p_prev = null;
347 		EVERECORD* p_next = null;
348 
349 		// 空き検索
350 		for (int r = 0; r < _eve_allocated_num; r++) {
351 			if (_eves[r].kind == EVENTKIND.NULL) {
352 				p_new = &_eves[r];
353 				break;
354 			}
355 		}
356 		if (!p_new) {
357 			return false;
358 		}
359 
360 		// first.
361 		if (!_start) {
362 		}  // top.
363 		else if (clock < _start.clock) {
364 			p_next = _start;
365 		} else {
366 
367 			for (EVERECORD* p = _start; p; p = p.next) {
368 				// 同時 
369 				if (p.clock == clock) {
370 					for (; true; p = p.next) {
371 						if (p.clock != clock) {
372 							p_prev = p.prev;
373 							p_next = p;
374 							break;
375 						}
376 						if (unit_no == p.unit_no && kind == p.kind) {
377 							p_prev = p.prev;
378 							p_next = p.next;
379 							p.kind = EVENTKIND.NULL;
380 							break;
381 						} // 置き換え
382 						if (_ComparePriority(kind, p.kind) < 0) {
383 							p_prev = p.prev;
384 							p_next = p;
385 							break;
386 						} // プライオリティを検査
387 						if (!p.next) {
388 							p_prev = p;
389 							break;
390 						} // 末端
391 					}
392 					break;
393 				} else if (p.clock > clock) {
394 					p_prev = p.prev;
395 					p_next = p;
396 					break;
397 				}  // 追い越した
398 				else if (!p.next) {
399 					p_prev = p;
400 					break;
401 				} // 末端
402 			}
403 		}
404 
405 		_rec_set(p_new, p_prev, p_next, clock, unit_no, kind, value);
406 
407 		// cut prev tail
408 		if (Evelist_Kind_IsTail(kind)) {
409 			for (EVERECORD* p = p_new.prev; p; p = p.prev) {
410 				if (p.unit_no == unit_no && p.kind == kind) {
411 					if (clock < p.clock + p.value) {
412 						p.value = clock - p.clock;
413 					}
414 					break;
415 				}
416 			}
417 		}
418 
419 		// delete next
420 		if (Evelist_Kind_IsTail(kind)) {
421 			for (EVERECORD* p = p_new.next; p && p.clock < clock + value; p = p.next) {
422 				if (p.unit_no == unit_no && p.kind == kind) {
423 					_rec_cut(p);
424 				}
425 			}
426 		}
427 
428 		return true;
429 	}
430 
431 	bool Record_Add_f(int clock, ubyte unit_no, ubyte kind, float value_f) nothrow @system {
432 		int value = *(cast(int*)(&value_f));
433 		return Record_Add_i(clock, unit_no, kind, value);
434 	}
435 
436 	/////////////////////
437 	// linear
438 	/////////////////////
439 
440 	bool Linear_Start() nothrow @system {
441 		if (!_eves) {
442 			return false;
443 		}
444 		Clear();
445 		_linear = 0;
446 		return true;
447 	}
448 
449 	void Linear_Add_i(int clock, ubyte unit_no, ubyte kind, int value) nothrow @system {
450 		EVERECORD* p = &_eves[_linear];
451 
452 		p.clock = clock;
453 		p.unit_no = unit_no;
454 		p.kind = kind;
455 		p.value = value;
456 
457 		_linear++;
458 	}
459 
460 	void Linear_Add_f(int clock, ubyte unit_no, ubyte kind, float value_f) nothrow @system {
461 		int value = *(cast(int*)(&value_f));
462 		Linear_Add_i(clock, unit_no, kind, value);
463 	}
464 
465 	void Linear_End(bool b_connect) nothrow @system {
466 		if (_eves[0].kind != EVENTKIND.NULL) {
467 			_start = &_eves[0];
468 		}
469 
470 		if (b_connect) {
471 			for (int r = 1; r < _eve_allocated_num; r++) {
472 				if (_eves[r].kind == EVENTKIND.NULL) {
473 					break;
474 				}
475 				_eves[r].prev = &_eves[r - 1];
476 				_eves[r - 1].next = &_eves[r];
477 			}
478 		}
479 	}
480 
481 	int Record_Clock_Shift(int clock, int shift, ubyte unit_no) nothrow @system  // can't be under 0.
482 	{
483 		if (!_eves) {
484 			return 0;
485 		}
486 		if (!_start) {
487 			return 0;
488 		}
489 		if (!shift) {
490 			return 0;
491 		}
492 
493 		int count = 0;
494 		int c;
495 		ubyte k;
496 		int v;
497 		EVERECORD* p_next;
498 		EVERECORD* p_prev;
499 		EVERECORD* p = _start;
500 
501 		if (shift < 0) {
502 			for (; p; p = p.next) {
503 				if (p.clock >= clock) {
504 					break;
505 				}
506 			}
507 			while (p) {
508 				if (p.unit_no == unit_no) {
509 					c = p.clock + shift;
510 					k = p.kind;
511 					v = p.value;
512 					p_next = p.next;
513 
514 					_rec_cut(p);
515 					if (c >= 0) {
516 						Record_Add_i(c, unit_no, k, v);
517 					}
518 					count++;
519 
520 					p = p_next;
521 				} else {
522 					p = p.next;
523 				}
524 			}
525 		} else if (shift > 0) {
526 			while (p.next) {
527 				p = p.next;
528 			}
529 			while (p) {
530 				if (p.clock < clock) {
531 					break;
532 				}
533 
534 				if (p.unit_no == unit_no) {
535 					c = p.clock + shift;
536 					k = p.kind;
537 					v = p.value;
538 					p_prev = p.prev;
539 
540 					_rec_cut(p);
541 					Record_Add_i(c, unit_no, k, v);
542 					count++;
543 
544 					p = p_prev;
545 				} else {
546 					p = p.prev;
547 				}
548 			}
549 		}
550 		return count;
551 	}
552 
553 	int Record_Value_Set(int clock1, int clock2, ubyte unit_no, ubyte kind, int value) nothrow @safe {
554 		if (!_eves) {
555 			return 0;
556 		}
557 
558 		int count = 0;
559 
560 		for (EVERECORD* p = _start; p; p = p.next) {
561 			if (p.unit_no == unit_no && p.kind == kind && p.clock >= clock1 && p.clock < clock2) {
562 				p.value = value;
563 				count++;
564 			}
565 		}
566 
567 		return count;
568 	}
569 
570 	int Record_Value_Change(int clock1, int clock2, ubyte unit_no, ubyte kind, int value) nothrow @safe {
571 		if (!_eves) {
572 			return 0;
573 		}
574 
575 		int count = 0;
576 
577 		int max, min;
578 
579 		switch (kind) {
580 		case EVENTKIND.NULL:
581 			max = 0;
582 			min = 0;
583 			break;
584 		case EVENTKIND.ON:
585 			max = 120;
586 			min = 120;
587 			break;
588 		case EVENTKIND.KEY:
589 			max = 0xbfff;
590 			min = 0;
591 			break;
592 		case EVENTKIND.PAN_VOLUME:
593 			max = 0x80;
594 			min = 0;
595 			break;
596 		case EVENTKIND.PAN_TIME:
597 			max = 0x80;
598 			min = 0;
599 			break;
600 		case EVENTKIND.VELOCITY:
601 			max = 0x80;
602 			min = 0;
603 			break;
604 		case EVENTKIND.VOLUME:
605 			max = 0x80;
606 			min = 0;
607 			break;
608 		default:
609 			max = 0;
610 			min = 0;
611 		}
612 
613 		for (EVERECORD* p = _start; p; p = p.next) {
614 			if (p.unit_no == unit_no && p.kind == kind && p.clock >= clock1) {
615 				if (clock2 == -1 || p.clock < clock2) {
616 					p.value += value;
617 					if (p.value < min) {
618 						p.value = min;
619 					}
620 					if (p.value > max) {
621 						p.value = max;
622 					}
623 					count++;
624 				}
625 			}
626 		}
627 
628 		return count;
629 	}
630 
631 	int Record_Value_Omit(ubyte kind, int value) nothrow @safe {
632 		if (!_eves) {
633 			return 0;
634 		}
635 
636 		int count = 0;
637 
638 		for (EVERECORD* p = _start; p; p = p.next) {
639 			if (p.kind == kind) {
640 				if (p.value == value) {
641 					_rec_cut(p);
642 					count++;
643 				} else if (p.value > value) {
644 					p.value--;
645 					count++;
646 				}
647 			}
648 		}
649 		return count;
650 	}
651 
652 	int Record_Value_Replace(ubyte kind, int old_value, int new_value) nothrow @safe {
653 		if (!_eves) {
654 			return 0;
655 		}
656 
657 		int count = 0;
658 
659 		if (old_value == new_value) {
660 			return 0;
661 		}
662 		if (old_value < new_value) {
663 			for (EVERECORD* p = _start; p; p = p.next) {
664 				if (p.kind == kind) {
665 					if (p.value == old_value) {
666 						p.value = new_value;
667 						count++;
668 					} else if (p.value > old_value && p.value <= new_value) {
669 						p.value--;
670 						count++;
671 					}
672 				}
673 			}
674 		} else {
675 			for (EVERECORD* p = _start; p; p = p.next) {
676 				if (p.kind == kind) {
677 					if (p.value == old_value) {
678 						p.value = new_value;
679 						count++;
680 					} else if (p.value < old_value && p.value >= new_value) {
681 						p.value++;
682 						count++;
683 					}
684 				}
685 			}
686 		}
687 
688 		return count;
689 	}
690 
691 	int Record_Delete(int clock1, int clock2, ubyte unit_no, ubyte kind) nothrow @safe {
692 		if (!_eves) {
693 			return 0;
694 		}
695 
696 		int count = 0;
697 
698 		for (EVERECORD* p = _start; p; p = p.next) {
699 			if (p.clock != clock1 && p.clock >= clock2) {
700 				break;
701 			}
702 			if (p.clock >= clock1 && p.unit_no == unit_no && p.kind == kind) {
703 				_rec_cut(p);
704 				count++;
705 			}
706 		}
707 
708 		if (Evelist_Kind_IsTail(kind)) {
709 			for (EVERECORD* p = _start; p; p = p.next) {
710 				if (p.clock >= clock1) {
711 					break;
712 				}
713 				if (p.unit_no == unit_no && p.kind == kind && p.clock + p.value > clock1) {
714 					p.value = clock1 - p.clock;
715 					count++;
716 				}
717 			}
718 		}
719 
720 		return count;
721 	}
722 
723 	int Record_Delete(int clock1, int clock2, ubyte unit_no) nothrow @safe {
724 		if (!_eves) {
725 			return 0;
726 		}
727 
728 		int count = 0;
729 
730 		for (EVERECORD* p = _start; p; p = p.next) {
731 			if (p.clock != clock1 && p.clock >= clock2) {
732 				break;
733 			}
734 			if (p.clock >= clock1 && p.unit_no == unit_no) {
735 				_rec_cut(p);
736 				count++;
737 			}
738 		}
739 
740 		for (EVERECORD* p = _start; p; p = p.next) {
741 			if (p.clock >= clock1) {
742 				break;
743 			}
744 			if (p.unit_no == unit_no && Evelist_Kind_IsTail(p.kind) && p.clock + p.value > clock1) {
745 				p.value = clock1 - p.clock;
746 				count++;
747 			}
748 		}
749 
750 		return count;
751 	}
752 
753 	int Record_UnitNo_Miss(ubyte unit_no) nothrow @safe  // delete event has the unit-no
754 	{
755 		if (!_eves) {
756 			return 0;
757 		}
758 
759 		int count = 0;
760 
761 		for (EVERECORD* p = _start; p; p = p.next) {
762 			if (p.unit_no == unit_no) {
763 				_rec_cut(p);
764 				count++;
765 			} else if (p.unit_no > unit_no) {
766 				p.unit_no--;
767 				count++;
768 			}
769 		}
770 		return count;
771 	}
772 
773 	int Record_UnitNo_Set(ubyte unit_no) nothrow @safe  // set the unit-no
774 	{
775 		if (!_eves) {
776 			return 0;
777 		}
778 
779 		int count = 0;
780 		for (EVERECORD* p = _start; p; p = p.next) {
781 			p.unit_no = unit_no;
782 			count++;
783 		}
784 		return count;
785 	}
786 
787 	int Record_UnitNo_Replace(ubyte old_u, ubyte new_u) nothrow @safe  // exchange unit
788 	{
789 		if (!_eves) {
790 			return 0;
791 		}
792 
793 		int count = 0;
794 
795 		if (old_u == new_u) {
796 			return 0;
797 		}
798 		if (old_u < new_u) {
799 			for (EVERECORD* p = _start; p; p = p.next) {
800 				if (p.unit_no == old_u) {
801 					p.unit_no = new_u;
802 					count++;
803 				} else if (p.unit_no > old_u && p.unit_no <= new_u) {
804 					p.unit_no--;
805 					count++;
806 				}
807 			}
808 		} else {
809 			for (EVERECORD* p = _start; p; p = p.next) {
810 				if (p.unit_no == old_u) {
811 					p.unit_no = new_u;
812 					count++;
813 				} else if (p.unit_no < old_u && p.unit_no >= new_u) {
814 					p.unit_no++;
815 					count++;
816 				}
817 			}
818 		}
819 
820 		return count;
821 	}
822 
823 	int BeatClockOperation(int rate) nothrow @safe {
824 		if (!_eves) {
825 			return 0;
826 		}
827 
828 		int count = 0;
829 
830 		for (EVERECORD* p = _start; p; p = p.next) {
831 			p.clock *= rate;
832 			if (Evelist_Kind_IsTail(p.kind)) {
833 				p.value *= rate;
834 			}
835 			count++;
836 		}
837 
838 		return count;
839 	}
840 
841 	// ------------
842 	// io
843 	// ------------
844 
845 	void io_Write(ref pxtnDescriptor p_doc, int rough) const @system {
846 		int eve_num = get_Count();
847 		int ralatived_size = 0;
848 		int absolute = 0;
849 		int clock;
850 		int value;
851 
852 		for (const(EVERECORD)* p = get_Records(); p; p = p.next) {
853 			clock = p.clock - absolute;
854 
855 			ralatived_size += pxtnDescriptor_v_chk(p.clock);
856 			ralatived_size += 1;
857 			ralatived_size += 1;
858 			ralatived_size += pxtnDescriptor_v_chk(p.value);
859 
860 			absolute = p.clock;
861 		}
862 
863 		int size = cast(int)(int.sizeof + ralatived_size);
864 		p_doc.w_asfile(size);
865 		p_doc.w_asfile(eve_num);
866 
867 		absolute = 0;
868 
869 		for (const(EVERECORD)* p = get_Records(); p; p = p.next) {
870 			clock = p.clock - absolute;
871 
872 			if (Evelist_Kind_IsTail(p.kind)) {
873 				value = p.value / rough;
874 			} else {
875 				value = p.value;
876 			}
877 
878 			p_doc.v_w_asfile(clock / rough);
879 			p_doc.w_asfile(p.unit_no);
880 			p_doc.w_asfile(p.kind);
881 			p_doc.v_w_asfile(value);
882 
883 			absolute = p.clock;
884 		}
885 	}
886 
887 	void io_Read(ref pxtnDescriptor p_doc) @system {
888 		int size = 0;
889 		int eve_num = 0;
890 
891 		p_doc.r(size);
892 		p_doc.r(eve_num);
893 
894 		int clock = 0;
895 		int absolute = 0;
896 		ubyte unit_no = 0;
897 		ubyte kind = 0;
898 		int value = 0;
899 
900 		for (int e = 0; e < eve_num; e++) {
901 			p_doc.v_r(clock);
902 			p_doc.r(unit_no);
903 			p_doc.r(kind);
904 			p_doc.v_r(value);
905 			absolute += clock;
906 			clock = absolute;
907 			Linear_Add_i(clock, unit_no, kind, value);
908 		}
909 	}
910 
911 	int io_Read_EventNum(ref pxtnDescriptor p_doc) const @system {
912 		int size = 0;
913 		int eve_num = 0;
914 
915 		p_doc.r(size);
916 		p_doc.r(eve_num);
917 
918 		int count = 0;
919 		int clock = 0;
920 		ubyte unit_no = 0;
921 		ubyte kind = 0;
922 		int value = 0;
923 
924 		for (int e = 0; e < eve_num; e++) {
925 			p_doc.v_r(clock);
926 			p_doc.r(unit_no);
927 			p_doc.r(kind);
928 			p_doc.v_r(value);
929 			count++;
930 		}
931 		if (count != eve_num) {
932 			return 0;
933 		}
934 
935 		return eve_num;
936 	}
937 
938 	bool x4x_Read_Start() nothrow @system {
939 		if (!_eves) {
940 			return false;
941 		}
942 		Clear();
943 		_linear = 0;
944 		_p_x4x_rec = null;
945 		return true;
946 	}
947 
948 	void x4x_Read_NewKind() nothrow @safe {
949 		_p_x4x_rec = null;
950 	}
951 
952 	void x4x_Read_Add(int clock, ubyte unit_no, ubyte kind, int value) nothrow @system {
953 		EVERECORD* p_new = null;
954 		EVERECORD* p_prev = null;
955 		EVERECORD* p_next = null;
956 
957 		p_new = &_eves[_linear++];
958 
959 		// first.
960 		if (!_start) {
961 		}  // top
962 		else if (clock < _start.clock) {
963 			p_next = _start;
964 		} else {
965 			EVERECORD* p;
966 
967 			if (_p_x4x_rec) {
968 				p = _p_x4x_rec;
969 			} else {
970 				p = _start;
971 			}
972 
973 			for (; p; p = p.next) {
974 				// 同時
975 				if (p.clock == clock) {
976 					for (; true; p = p.next) {
977 						if (p.clock != clock) {
978 							p_prev = p.prev;
979 							p_next = p;
980 							break;
981 						}
982 						if (unit_no == p.unit_no && kind == p.kind) {
983 							p_prev = p.prev;
984 							p_next = p.next;
985 							p.kind = EVENTKIND.NULL;
986 							break;
987 						} // 置き換え
988 						if (_ComparePriority(kind, p.kind) < 0) {
989 							p_prev = p.prev;
990 							p_next = p;
991 							break;
992 						} // プライオリティを検査
993 						if (!p.next) {
994 							p_prev = p;
995 							break;
996 						} // 末端
997 					}
998 					break;
999 				} else if (p.clock > clock) {
1000 					p_prev = p.prev;
1001 					p_next = p;
1002 					break;
1003 				}  // 追い越した
1004 				else if (!p.next) {
1005 					p_prev = p;
1006 					break;
1007 				} // 末端
1008 			}
1009 		}
1010 		_rec_set(p_new, p_prev, p_next, clock, unit_no, kind, value);
1011 
1012 		_p_x4x_rec = p_new;
1013 	}
1014 
1015 	// write event.
1016 	void io_Unit_Read_x4x_EVENT(ref pxtnDescriptor p_doc, bool bTailAbsolute, bool bCheckRRR) @system {
1017 		_x4x_EVENTSTRUCT evnt;
1018 		int clock = 0;
1019 		int value = 0;
1020 		int absolute = 0;
1021 		int e = 0;
1022 		int size = 0;
1023 
1024 		p_doc.r(size);
1025 		p_doc.r(evnt);
1026 
1027 		if (evnt.data_num != 2) {
1028 			throw new PxtoneException("fmt unknown");
1029 		}
1030 		if (evnt.event_kind >= EVENTKIND.NUM) {
1031 			throw new PxtoneException("fmt unknown");
1032 		}
1033 		if (bCheckRRR && evnt.rrr) {
1034 			throw new PxtoneException("fmt unknown");
1035 		}
1036 
1037 		absolute = 0;
1038 		for (e = 0; e < cast(int) evnt.event_num; e++) {
1039 			p_doc.v_r(clock);
1040 			p_doc.v_r(value);
1041 			absolute += clock;
1042 			clock = absolute;
1043 			x4x_Read_Add(clock, cast(ubyte) evnt.unit_index, cast(ubyte) evnt.event_kind, value);
1044 			if (bTailAbsolute && Evelist_Kind_IsTail(evnt.event_kind)) {
1045 				absolute += value;
1046 			}
1047 		}
1048 		if (e != evnt.event_num) {
1049 			throw new PxtoneException("desc broken");
1050 		}
1051 
1052 		x4x_Read_NewKind();
1053 	}
1054 
1055 	void io_Read_x4x_EventNum(ref pxtnDescriptor p_doc, int* p_num) const @system {
1056 		if (!p_num) {
1057 			throw new PxtoneException("param");
1058 		}
1059 
1060 		_x4x_EVENTSTRUCT evnt;
1061 		int work = 0;
1062 		int e = 0;
1063 		int size = 0;
1064 
1065 		p_doc.r(size);
1066 		p_doc.r(evnt);
1067 
1068 		// support only 2
1069 		if (evnt.data_num != 2) {
1070 			throw new PxtoneException("fmt unknown");
1071 		}
1072 
1073 		for (e = 0; e < cast(int) evnt.event_num; e++) {
1074 			p_doc.v_r(work);
1075 			p_doc.v_r(work);
1076 		}
1077 		if (e != evnt.event_num) {
1078 			throw new PxtoneException("desc broken");
1079 		}
1080 
1081 		*p_num = evnt.event_num;
1082 	}
1083 }