1 module pxtone.delay;
2 
3 import pxtone.pxtn;
4 
5 import pxtone.descriptor;
6 import pxtone.error;
7 import pxtone.max;
8 
9 enum DELAYUNIT {
10 	Beat = 0,
11 	Meas,
12 	Second,
13 	num,
14 }
15 
16 // (12byte) =================
17 struct _DELAYSTRUCT {
18 	ushort unit;
19 	ushort group;
20 	float rate = 0.0;
21 	float freq = 0.0;
22 }
23 
24 struct pxtnDelay {
25 private:
26 	bool _b_played = true;
27 	DELAYUNIT _unit = DELAYUNIT.Beat;
28 	int _group = 0;
29 	float _rate = 33.0;
30 	float _freq = 3.0f;
31 
32 	int _smp_num = 0;
33 	int _offset = 0;
34 	int[][pxtnMAX_CHANNEL] _bufs = null;
35 	int _rate_s32 = 0;
36 
37 public:
38 
39 	 ~this() nothrow @system {
40 		Tone_Release();
41 	}
42 
43 	DELAYUNIT get_unit() const nothrow @safe {
44 		return _unit;
45 	}
46 
47 	int get_group() const nothrow @safe {
48 		return _group;
49 	}
50 
51 	float get_rate() const nothrow @safe {
52 		return _rate;
53 	}
54 
55 	float get_freq() const nothrow @safe {
56 		return _freq;
57 	}
58 
59 	void Set(DELAYUNIT unit, float freq, float rate, int group) nothrow @safe {
60 		_unit = unit;
61 		_group = group;
62 		_rate = rate;
63 		_freq = freq;
64 	}
65 
66 	bool get_played() const nothrow @safe {
67 		return _b_played;
68 	}
69 
70 	void set_played(bool b) nothrow @safe {
71 		_b_played = b;
72 	}
73 
74 	bool switch_played() nothrow @safe {
75 		_b_played = !_b_played;
76 		return _b_played;
77 	}
78 
79 	void Tone_Release() nothrow @system {
80 		_bufs = null;
81 		_smp_num = 0;
82 	}
83 
84 	void Tone_Ready(int beat_num, float beat_tempo, int sps) @system {
85 		Tone_Release();
86 
87 		scope(failure) {
88 			Tone_Release();
89 		}
90 		if (_freq && _rate) {
91 			_offset = 0;
92 			_rate_s32 = cast(int) _rate; // /100;
93 
94 			switch (_unit) {
95 			case DELAYUNIT.Beat:
96 				_smp_num = cast(int)(sps * 60 / beat_tempo / _freq);
97 				break;
98 			case DELAYUNIT.Meas:
99 				_smp_num = cast(int)(sps * 60 * beat_num / beat_tempo / _freq);
100 				break;
101 			case DELAYUNIT.Second:
102 				_smp_num = cast(int)(sps / _freq);
103 				break;
104 			default:
105 				break;
106 			}
107 
108 			for (int c = 0; c < pxtnMAX_CHANNEL; c++) {
109 				_bufs[c] = new int[](_smp_num);
110 			}
111 		}
112 	}
113 
114 	void Tone_Supple(int ch, int[] group_smps) nothrow @safe {
115 		if (!_smp_num) {
116 			return;
117 		}
118 		int a = _bufs[ch][_offset] * _rate_s32 / 100;
119 		if (_b_played) {
120 			group_smps[_group] += a;
121 		}
122 		_bufs[ch][_offset] = group_smps[_group];
123 	}
124 
125 	void Tone_Increment() nothrow @safe {
126 		if (!_smp_num) {
127 			return;
128 		}
129 		if (++_offset >= _smp_num) {
130 			_offset = 0;
131 		}
132 	}
133 
134 	void Tone_Clear() nothrow @system {
135 		if (!_smp_num) {
136 			return;
137 		}
138 		int def = 0; // ..
139 		for (int i = 0; i < pxtnMAX_CHANNEL; i++) {
140 			_bufs[i][0 .. _smp_num] = def;
141 		}
142 	}
143 
144 	void Write(ref pxtnDescriptor p_doc) const @system {
145 		_DELAYSTRUCT dela;
146 		int size;
147 
148 		dela.unit = cast(ushort) _unit;
149 		dela.group = cast(ushort) _group;
150 		dela.rate = _rate;
151 		dela.freq = _freq;
152 
153 		// dela ----------
154 		size = _DELAYSTRUCT.sizeof;
155 		p_doc.w_asfile(size);
156 		p_doc.w_asfile(dela);
157 	}
158 
159 	void Read(ref pxtnDescriptor p_doc) @system {
160 		_DELAYSTRUCT dela;
161 		int size = 0;
162 
163 		p_doc.r(size);
164 		p_doc.r(dela);
165 		if (dela.unit >= DELAYUNIT.num) {
166 			throw new PxtoneException("fmt unknown");
167 		}
168 
169 		_unit = cast(DELAYUNIT) dela.unit;
170 		_freq = dela.freq;
171 		_rate = dela.rate;
172 		_group = dela.group;
173 
174 		if (_group >= pxtnMAX_TUNEGROUPNUM) {
175 			_group = 0;
176 		}
177 	}
178 }