1 module pxtone.unit; 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.max; 10 import pxtone.woice; 11 12 import std.exception; 13 14 // v1x (20byte) ================= 15 struct _x1x_UNIT { 16 char[pxtnMAX_TUNEUNITNAME] name; 17 ushort type; 18 ushort group; 19 } 20 21 /////////////////// 22 // pxtnUNIT x3x 23 /////////////////// 24 25 struct _x3x_UNIT { 26 ushort type; 27 ushort group; 28 } 29 30 struct pxtnUnit { 31 private: 32 bool _bOperated = true; 33 bool _bPlayed = true; 34 char[pxtnMAX_TUNEUNITNAME + 1] _name_buf = "no name"; 35 int _name_size = "no name".length; 36 37 // TUNEUNITTONESTRUCT 38 int _key_now; 39 int _key_start; 40 int _key_margin; 41 int _portament_sample_pos; 42 int _portament_sample_num; 43 int[pxtnMAX_CHANNEL] _pan_vols; 44 int[pxtnMAX_CHANNEL] _pan_times; 45 int[pxtnBUFSIZE_TIMEPAN][pxtnMAX_CHANNEL] _pan_time_bufs; 46 int _v_VOLUME; 47 int _v_VELOCITY; 48 int _v_GROUPNO; 49 float _v_TUNING = 0.0; 50 51 const(pxtnWoice)* _p_woice; 52 53 pxtnVOICETONE[pxtnMAX_UNITCONTROLVOICE] _vts; 54 55 public: 56 57 void Tone_Init() nothrow @safe { 58 _v_GROUPNO = EVENTDEFAULT_GROUPNO; 59 _v_VELOCITY = EVENTDEFAULT_VELOCITY; 60 _v_VOLUME = EVENTDEFAULT_VOLUME; 61 _v_TUNING = EVENTDEFAULT_TUNING; 62 _portament_sample_num = 0; 63 _portament_sample_pos = 0; 64 65 for (int i = 0; i < pxtnMAX_CHANNEL; i++) { 66 _pan_vols[i] = 64; 67 _pan_times[i] = 0; 68 } 69 } 70 71 void Tone_Clear() nothrow @safe { 72 for (int i = 0; i < pxtnMAX_CHANNEL; i++) { 73 _pan_time_bufs[i][0 .. pxtnBUFSIZE_TIMEPAN] = 0; 74 } 75 } 76 77 void Tone_Reset_and_2prm(int voice_idx, int env_rls_clock, float offset_freq) nothrow @safe { 78 pxtnVOICETONE* p_tone = &_vts[voice_idx]; 79 p_tone.life_count = 0; 80 p_tone.on_count = 0; 81 p_tone.smp_pos = 0; 82 p_tone.smooth_volume = 0; 83 p_tone.env_release_clock = env_rls_clock; 84 p_tone.offset_freq = offset_freq; 85 } 86 87 void Tone_Envelope() nothrow @safe { 88 if (!_p_woice) { 89 return; 90 } 91 92 for (int v = 0; v < _p_woice.get_voice_num(); v++) { 93 const pxtnVOICEINSTANCE* p_vi = _p_woice.get_instance(v); 94 pxtnVOICETONE* p_vt = &_vts[v]; 95 96 if (p_vt.life_count > 0 && p_vi.env_size) { 97 if (p_vt.on_count > 0) { 98 if (p_vt.env_pos < p_vi.env_size) { 99 p_vt.env_volume = p_vi.p_env[p_vt.env_pos]; 100 p_vt.env_pos++; 101 } 102 } // release. 103 else { 104 p_vt.env_volume = p_vt.env_start + (0 - p_vt.env_start) * p_vt.env_pos / p_vi.env_release; 105 p_vt.env_pos++; 106 } 107 } 108 } 109 } 110 111 void Tone_KeyOn() nothrow @safe { 112 _key_now = _key_start + _key_margin; 113 _key_start = _key_now; 114 _key_margin = 0; 115 } 116 117 void Tone_ZeroLives() nothrow @safe { 118 for (int i = 0; i < pxtnMAX_CHANNEL; i++) { 119 _vts[i].life_count = 0; 120 } 121 } 122 123 void Tone_Key(int key) nothrow @safe { 124 _key_start = _key_now; 125 _key_margin = key - _key_start; 126 _portament_sample_pos = 0; 127 } 128 129 void Tone_Pan_Volume(int ch, int pan) nothrow @safe { 130 _pan_vols[0] = 64; 131 _pan_vols[1] = 64; 132 if (ch == 2) { 133 if (pan >= 64) { 134 _pan_vols[0] = 128 - pan; 135 } else { 136 _pan_vols[1] = pan; 137 } 138 } 139 } 140 141 void Tone_Pan_Time(int ch, int pan, int sps) nothrow @safe { 142 _pan_times[0] = 0; 143 _pan_times[1] = 0; 144 145 if (ch == 2) { 146 if (pan >= 64) { 147 _pan_times[0] = pan - 64; 148 if (_pan_times[0] > 63) { 149 _pan_times[0] = 63; 150 } 151 _pan_times[0] = (_pan_times[0] * 44100) / sps; 152 } else { 153 _pan_times[1] = 64 - pan; 154 if (_pan_times[1] > 63) { 155 _pan_times[1] = 63; 156 } 157 _pan_times[1] = (_pan_times[1] * 44100) / sps; 158 } 159 } 160 } 161 162 void Tone_Velocity(int val) nothrow @safe { 163 _v_VELOCITY = val; 164 } 165 166 void Tone_Volume(int val) nothrow @safe { 167 _v_VOLUME = val; 168 } 169 170 void Tone_Portament(int val) nothrow @safe { 171 _portament_sample_num = val; 172 } 173 174 void Tone_GroupNo(int val) nothrow @safe { 175 _v_GROUPNO = val; 176 } 177 178 void Tone_Tuning(float val) nothrow @safe { 179 _v_TUNING = val; 180 } 181 182 void Tone_Sample(bool b_mute_by_unit, int ch_num, int time_pan_index, int smooth_smp) nothrow @safe { 183 if (!_p_woice) { 184 return; 185 } 186 187 if (b_mute_by_unit && !_bPlayed) { 188 for (int ch = 0; ch < ch_num; ch++) { 189 _pan_time_bufs[ch][time_pan_index] = 0; 190 } 191 return; 192 } 193 194 for (int ch = 0; ch < pxtnMAX_CHANNEL; ch++) { 195 int time_pan_buf = 0; 196 197 for (int v = 0; v < _p_woice.get_voice_num(); v++) { 198 pxtnVOICETONE* p_vt = &_vts[v]; 199 const pxtnVOICEINSTANCE* p_vi = _p_woice.get_instance(v); 200 201 int work = 0; 202 203 if (p_vt.life_count > 0) { 204 int pos = cast(int) p_vt.smp_pos * 2 + ch; 205 work += (cast(const(short)[])p_vi.p_smp_w)[pos]; 206 207 if (ch_num == 1) { 208 work += (cast(const(short)[])p_vi.p_smp_w)[pos + 1]; 209 work = work / 2; 210 } 211 212 work = (work * _v_VELOCITY) / 128; 213 work = (work * _v_VOLUME) / 128; 214 work = work * _pan_vols[ch] / 64; 215 216 if (p_vi.env_size) { 217 work = work * p_vt.env_volume / 128; 218 } 219 220 // smooth tail 221 if (_p_woice.get_voice(v).voice_flags & PTV_VOICEFLAG_SMOOTH && p_vt.life_count < smooth_smp) { 222 work = work * p_vt.life_count / smooth_smp; 223 } 224 } 225 time_pan_buf += work; 226 } 227 _pan_time_bufs[ch][time_pan_index] = time_pan_buf; 228 } 229 } 230 231 void Tone_Supple(int[] group_smps, int ch, int time_pan_index) const nothrow @safe { 232 int idx = (time_pan_index - _pan_times[ch]) & (pxtnBUFSIZE_TIMEPAN - 1); 233 group_smps[_v_GROUPNO] += _pan_time_bufs[ch][idx]; 234 } 235 236 int Tone_Increment_Key() nothrow @safe { 237 // prtament.. 238 if (_portament_sample_num && _key_margin) { 239 if (_portament_sample_pos < _portament_sample_num) { 240 _portament_sample_pos++; 241 _key_now = cast(int)(_key_start + cast(double) _key_margin * _portament_sample_pos / _portament_sample_num); 242 } else { 243 _key_now = _key_start + _key_margin; 244 _key_start = _key_now; 245 _key_margin = 0; 246 } 247 } else { 248 _key_now = _key_start + _key_margin; 249 } 250 return _key_now; 251 } 252 253 void Tone_Increment_Sample(float freq) nothrow @safe { 254 if (!_p_woice) { 255 return; 256 } 257 258 for (int v = 0; v < _p_woice.get_voice_num(); v++) { 259 const pxtnVOICEINSTANCE* p_vi = _p_woice.get_instance(v); 260 pxtnVOICETONE* p_vt = &_vts[v]; 261 262 if (p_vt.life_count > 0) { 263 p_vt.life_count--; 264 } 265 if (p_vt.life_count > 0) { 266 p_vt.on_count--; 267 268 p_vt.smp_pos += p_vt.offset_freq * _v_TUNING * freq; 269 270 if (p_vt.smp_pos >= p_vi.smp_body_w) { 271 if (_p_woice.get_voice(v).voice_flags & PTV_VOICEFLAG_WAVELOOP) { 272 if (p_vt.smp_pos >= p_vi.smp_body_w) { 273 p_vt.smp_pos -= p_vi.smp_body_w; 274 } 275 if (p_vt.smp_pos >= p_vi.smp_body_w) { 276 p_vt.smp_pos = 0; 277 } 278 } else { 279 p_vt.life_count = 0; 280 } 281 } 282 283 // OFF 284 if (p_vt.on_count == 0 && p_vi.env_size) { 285 p_vt.env_start = p_vt.env_volume; 286 p_vt.env_pos = 0; 287 } 288 } 289 } 290 } 291 292 bool set_woice(const(pxtnWoice)* p_woice) nothrow @safe { 293 if (!p_woice) { 294 return false; 295 } 296 _p_woice = p_woice; 297 _key_now = EVENTDEFAULT_KEY; 298 _key_margin = 0; 299 _key_start = EVENTDEFAULT_KEY; 300 return true; 301 } 302 303 const(pxtnWoice)* get_woice() const nothrow @safe { 304 return _p_woice; 305 } 306 307 bool setNameBuf(scope const char[] name) nothrow @safe { 308 if (!name || name.length > pxtnMAX_TUNEUNITNAME) { 309 return false; 310 } 311 _name_buf[0 .. $] = 0; 312 if (name.length) { 313 _name_buf[0 .. name.length] = name; 314 } 315 _name_size = cast(int)name.length; 316 return true; 317 } 318 319 const(char)* get_name_buf(int* p_buf_size) const return nothrow @system { 320 if (p_buf_size) { 321 *p_buf_size = _name_size; 322 } 323 return _name_buf.ptr; 324 } 325 326 bool is_name_buf() const nothrow @safe { 327 if (_name_size > 0) { 328 return true; 329 } 330 return false; 331 } 332 333 pxtnVOICETONE* get_tone(int voice_idx) return nothrow @safe { 334 return &_vts[voice_idx]; 335 } 336 337 void set_operated(bool b) nothrow @safe { 338 _bOperated = b; 339 } 340 341 void set_played(bool b) nothrow @safe { 342 _bPlayed = b; 343 } 344 345 bool get_operated() const nothrow @safe { 346 return _bOperated; 347 } 348 349 bool get_played() const nothrow @safe { 350 return _bPlayed; 351 } 352 353 void Read_v3x(ref pxtnDescriptor p_doc, int* p_group) @system { 354 _x3x_UNIT unit; 355 int size = 0; 356 357 p_doc.r(size); 358 p_doc.r(unit); 359 if (cast(pxtnWOICETYPE) unit.type != pxtnWOICETYPE.PCM && cast(pxtnWOICETYPE) unit.type != pxtnWOICETYPE.PTV && cast(pxtnWOICETYPE) unit.type != pxtnWOICETYPE.PTN) { 360 throw new PxtoneException("fmt unknown"); 361 } 362 *p_group = unit.group; 363 } 364 365 void Read_v1x(ref pxtnDescriptor p_doc, int* p_group) @system { 366 _x1x_UNIT unit; 367 int size; 368 369 p_doc.r(size); 370 p_doc.r(unit); 371 enforce(cast(pxtnWOICETYPE) unit.type == pxtnWOICETYPE.PCM, new PxtoneException("Expecting a PCM unit")); 372 373 _name_buf[0 .. pxtnMAX_TUNEUNITNAME] = unit.name[0 .. pxtnMAX_TUNEUNITNAME]; 374 _name_buf[pxtnMAX_TUNEUNITNAME] = '\0'; 375 *p_group = unit.group; 376 } 377 }