1 module pxtone.pulse.noisebuilder; 2 3 import pxtone.pxtn; 4 5 import pxtone.error; 6 import pxtone.pulse.frequency; 7 import pxtone.pulse.oscillator; 8 import pxtone.pulse.pcm; 9 import pxtone.pulse.noise; 10 11 enum _BASIC_SPS = 44100.0; 12 enum _BASIC_FREQUENCY = 100.0; // 100 Hz 13 enum _SAMPLING_TOP = 32767; // 16 bit max 14 enum _KEY_TOP = 0x3200; // 40 key 15 16 enum _smp_num_rand = 44100; 17 enum _smp_num = cast(int)(_BASIC_SPS / _BASIC_FREQUENCY); 18 19 enum _RANDOMTYPE { 20 None = 0, 21 Saw, 22 Rect, 23 } 24 25 struct _OSCILLATOR { 26 double incriment; 27 double offset; 28 double volume; 29 const(short)[] p_smp; 30 bool bReverse; 31 _RANDOMTYPE ran_type; 32 int rdm_start; 33 int rdm_margin; 34 int rdm_index; 35 } 36 37 struct _POINT { 38 int smp; 39 double mag; 40 } 41 42 struct _UNIT { 43 bool bEnable; 44 double[2] pan; 45 int enve_index; 46 double enve_mag_start; 47 double enve_mag_margin; 48 int enve_count; 49 int enve_num; 50 _POINT[] enves; 51 52 _OSCILLATOR main; 53 _OSCILLATOR freq; 54 _OSCILLATOR volu; 55 } 56 57 void _set_ocsillator(_OSCILLATOR* p_to, pxNOISEDESIGN_OSCILLATOR* p_from, int sps, const(short)[] p_tbl, const(short)[] p_tbl_rand) nothrow @safe { 58 const(short)[] p; 59 60 switch (p_from.type) { 61 case pxWAVETYPE.Random: 62 p_to.ran_type = _RANDOMTYPE.Saw; 63 break; 64 case pxWAVETYPE.Random2: 65 p_to.ran_type = _RANDOMTYPE.Rect; 66 break; 67 default: 68 p_to.ran_type = _RANDOMTYPE.None; 69 break; 70 } 71 72 p_to.incriment = (_BASIC_SPS / sps) * (p_from.freq / _BASIC_FREQUENCY); 73 74 // offset 75 if (p_to.ran_type != _RANDOMTYPE.None) { 76 p_to.offset = 0; 77 } else { 78 p_to.offset = cast(double) _smp_num * (p_from.offset / 100); 79 } 80 81 p_to.volume = p_from.volume / 100; 82 p_to.p_smp = p_tbl; 83 p_to.bReverse = p_from.b_rev; 84 85 p_to.rdm_start = 0; 86 p_to.rdm_index = cast(int)(cast(double)(_smp_num_rand) * (p_from.offset / 100)); 87 p = p_tbl_rand; 88 p_to.rdm_margin = p[p_to.rdm_index]; 89 90 } 91 92 void _incriment(_OSCILLATOR* p_osc, double incriment, const(short)[] p_tbl_rand) nothrow @safe { 93 p_osc.offset += incriment; 94 if (p_osc.offset > _smp_num) { 95 p_osc.offset -= _smp_num; 96 if (p_osc.offset >= _smp_num) { 97 p_osc.offset = 0; 98 } 99 100 if (p_osc.ran_type != _RANDOMTYPE.None) { 101 const(short)[] p = p_tbl_rand; 102 p_osc.rdm_start = p[p_osc.rdm_index]; 103 p_osc.rdm_index++; 104 if (p_osc.rdm_index >= _smp_num_rand) { 105 p_osc.rdm_index = 0; 106 } 107 p_osc.rdm_margin = p[p_osc.rdm_index] - p_osc.rdm_start; 108 } 109 } 110 } 111 112 struct pxtnPulse_NoiseBuilder { 113 private: 114 static immutable short[][pxWAVETYPE.num] _p_tables = genTables(); 115 116 pxtnPulse_Frequency _freq; 117 118 public: 119 pxtnPulse_PCM BuildNoise(ref pxtnPulse_Noise p_noise, int ch, int sps, int bps) const @system { 120 int offset = 0; 121 double work = 0; 122 double vol = 0; 123 double fre = 0; 124 double store = 0; 125 int byte4 = 0; 126 int unit_num = 0; 127 ubyte* p = null; 128 int smp_num = 0; 129 130 _UNIT[] units = null; 131 pxtnPulse_PCM p_pcm; 132 133 p_noise.Fix(); 134 135 unit_num = p_noise.get_unit_num(); 136 137 units = new _UNIT[](unit_num); 138 scope(exit) { 139 units = null; 140 } 141 142 for (int u = 0; u < unit_num; u++) { 143 _UNIT* pU = &units[u]; 144 145 pxNOISEDESIGN_UNIT* p_du = p_noise.get_unit(u); 146 147 pU.bEnable = p_du.bEnable; 148 pU.enve_num = p_du.enve_num; 149 if (p_du.pan == 0) { 150 pU.pan[0] = 1; 151 pU.pan[1] = 1; 152 } else if (p_du.pan < 0) { 153 pU.pan[0] = 1; 154 pU.pan[1] = cast(double)(100.0f + p_du.pan) / 100; 155 } else { 156 pU.pan[1] = 1; 157 pU.pan[0] = cast(double)(100.0f - p_du.pan) / 100; 158 } 159 160 pU.enves = new _POINT[](pU.enve_num); 161 162 // envelope 163 for (int e = 0; e < p_du.enve_num; e++) { 164 pU.enves[e].smp = sps * p_du.enves[e].x / 1000; 165 pU.enves[e].mag = cast(double) p_du.enves[e].y / 100; 166 } 167 pU.enve_index = 0; 168 pU.enve_mag_start = 0; 169 pU.enve_mag_margin = 0; 170 pU.enve_count = 0; 171 while (pU.enve_index < pU.enve_num) { 172 pU.enve_mag_margin = pU.enves[pU.enve_index].mag - pU.enve_mag_start; 173 if (pU.enves[pU.enve_index].smp) { 174 break; 175 } 176 pU.enve_mag_start = pU.enves[pU.enve_index].mag; 177 pU.enve_index++; 178 } 179 180 _set_ocsillator(&pU.main, &p_du.main, sps, _p_tables[p_du.main.type], _p_tables[pxWAVETYPE.Random]); 181 _set_ocsillator(&pU.freq, &p_du.freq, sps, _p_tables[p_du.freq.type], _p_tables[pxWAVETYPE.Random]); 182 _set_ocsillator(&pU.volu, &p_du.volu, sps, _p_tables[p_du.volu.type], _p_tables[pxWAVETYPE.Random]); 183 } 184 185 smp_num = cast(int)(cast(double) p_noise.get_smp_num_44k() / (44100.0 / sps)); 186 187 p_pcm = pxtnPulse_PCM.init; 188 p_pcm.Create(ch, sps, bps, smp_num); 189 p = p_pcm.get_p_buf().ptr; 190 191 for (int s = 0; s < smp_num; s++) { 192 for (int c = 0; c < ch; c++) { 193 store = 0; 194 for (int u = 0; u < unit_num; u++) { 195 _UNIT* pU = &units[u]; 196 197 if (pU.bEnable) { 198 _OSCILLATOR* po; 199 200 // main 201 po = &pU.main; 202 switch (po.ran_type) { 203 case _RANDOMTYPE.None: 204 offset = cast(int) po.offset; 205 if (offset >= 0) { 206 work = po.p_smp[offset]; 207 } else { 208 work = 0; 209 } 210 break; 211 case _RANDOMTYPE.Saw: 212 if (po.offset >= 0) { 213 work = po.rdm_start + po.rdm_margin * cast(int) po.offset / _smp_num; 214 } else { 215 work = 0; 216 } 217 break; 218 case _RANDOMTYPE.Rect: 219 if (po.offset >= 0) { 220 work = po.rdm_start; 221 } else { 222 work = 0; 223 } 224 break; 225 default: 226 break; 227 } 228 if (po.bReverse) { 229 work *= -1; 230 } 231 work *= po.volume; 232 233 // volu 234 po = &pU.volu; 235 switch (po.ran_type) { 236 case _RANDOMTYPE.None: 237 offset = cast(int) po.offset; 238 vol = cast(double) po.p_smp[offset]; 239 break; 240 case _RANDOMTYPE.Saw: 241 vol = po.rdm_start + po.rdm_margin * cast(int) po.offset / _smp_num; 242 break; 243 case _RANDOMTYPE.Rect: 244 vol = po.rdm_start; 245 break; 246 default: 247 break; 248 } 249 if (po.bReverse) { 250 vol *= -1; 251 } 252 vol *= po.volume; 253 254 work = work * (vol + _SAMPLING_TOP) / (_SAMPLING_TOP * 2); 255 work = work * pU.pan[c]; 256 257 // envelope 258 if (pU.enve_index < pU.enve_num) { 259 work *= pU.enve_mag_start + (pU.enve_mag_margin * pU.enve_count / pU.enves[pU.enve_index].smp); 260 } else { 261 work *= pU.enve_mag_start; 262 } 263 store += work; 264 } 265 } 266 267 byte4 = cast(int) store; 268 if (byte4 > _SAMPLING_TOP) { 269 byte4 = _SAMPLING_TOP; 270 } 271 if (byte4 < -_SAMPLING_TOP) { 272 byte4 = -_SAMPLING_TOP; 273 } 274 if (bps == 8) { 275 *p = cast(ubyte)((byte4 >> 8) + 128); 276 p += 1; 277 } // 8bit 278 else { 279 *(cast(short*) p) = cast(short) byte4; 280 p += 2; 281 } // 16bit 282 } 283 284 // incriment 285 for (int u = 0; u < unit_num; u++) { 286 _UNIT* pU = &units[u]; 287 288 if (pU.bEnable) { 289 _OSCILLATOR* po = &pU.freq; 290 291 switch (po.ran_type) { 292 case _RANDOMTYPE.None: 293 offset = cast(int) po.offset; 294 fre = _KEY_TOP * po.p_smp[offset] / _SAMPLING_TOP; 295 break; 296 case _RANDOMTYPE.Saw: 297 fre = po.rdm_start + po.rdm_margin * cast(int) po.offset / _smp_num; 298 break; 299 case _RANDOMTYPE.Rect: 300 fre = po.rdm_start; 301 break; 302 default: 303 break; 304 } 305 306 if (po.bReverse) { 307 fre *= -1; 308 } 309 fre *= po.volume; 310 311 _incriment(&pU.main, pU.main.incriment * _freq.Get(cast(int) fre), _p_tables[pxWAVETYPE.Random]); 312 _incriment(&pU.freq, pU.freq.incriment, _p_tables[pxWAVETYPE.Random]); 313 _incriment(&pU.volu, pU.volu.incriment, _p_tables[pxWAVETYPE.Random]); 314 315 // envelope 316 if (pU.enve_index < pU.enve_num) { 317 pU.enve_count++; 318 if (pU.enve_count >= pU.enves[pU.enve_index].smp) { 319 pU.enve_count = 0; 320 pU.enve_mag_start = pU.enves[pU.enve_index].mag; 321 pU.enve_mag_margin = 0; 322 pU.enve_index++; 323 while (pU.enve_index < pU.enve_num) { 324 pU.enve_mag_margin = pU.enves[pU.enve_index].mag - pU.enve_mag_start; 325 if (pU.enves[pU.enve_index].smp) { 326 break; 327 } 328 pU.enve_mag_start = pU.enves[pU.enve_index].mag; 329 pU.enve_index++; 330 } 331 } 332 } 333 } 334 } 335 } 336 337 return p_pcm; 338 } 339 } 340 341 short[][pxWAVETYPE.num] genTables() { 342 pxtnPOINT[1] overtones_sine = [{1, 128}]; 343 pxtnPOINT[16] overtones_saw2 = [{1, 128}, {2, 128}, {3, 128}, {4, 128}, {5, 128}, {6, 128}, {7, 128}, {8, 128}, {9, 128}, {10, 128}, {11, 128}, {12, 128}, {13, 128}, {14, 128}, {15, 128}, {16, 128},]; 344 pxtnPOINT[8] overtones_rect2 = [{1, 128}, {3, 128}, {5, 128}, {7, 128}, {9, 128}, {11, 128}, {13, 128}, {15, 128},]; 345 346 pxtnPOINT[4] coodi_tri = [{0, 0}, {_smp_num / 4, 128}, {_smp_num * 3 / 4, -128}, {_smp_num, 0}]; 347 int s; 348 short[] p; 349 double work; 350 351 int a; 352 short v; 353 pxtnPulse_Oscillator osci; 354 int[2] _rand_buf; 355 356 void _random_reset() nothrow @safe { 357 _rand_buf[0] = 0x4444; 358 _rand_buf[1] = 0x8888; 359 } 360 361 short _random_get() nothrow @system { 362 ubyte[2] w1, w2; 363 364 short tmp = cast(short)(_rand_buf[0] + _rand_buf[1]); 365 w2[1] = (tmp & 0xFF); 366 w2[0] = (tmp & 0xFF00) >> 8; 367 _rand_buf[1] = cast(short) _rand_buf[0]; 368 _rand_buf[0] = cast(short) (w2[0] + (w2[1] << 8)); 369 370 return cast(short) (w2[0] + (w2[1] << 8)); 371 } 372 373 short[][pxWAVETYPE.num] _p_tables; 374 _p_tables[pxWAVETYPE.None] = new short[_smp_num]; 375 _p_tables[pxWAVETYPE.Sine] = new short[_smp_num]; 376 _p_tables[pxWAVETYPE.Saw] = new short[_smp_num]; 377 _p_tables[pxWAVETYPE.Rect] = new short[_smp_num]; 378 _p_tables[pxWAVETYPE.Random] = new short[_smp_num_rand]; 379 _p_tables[pxWAVETYPE.Saw2] = new short[_smp_num]; 380 _p_tables[pxWAVETYPE.Rect2] = new short[_smp_num]; 381 _p_tables[pxWAVETYPE.Tri] = new short[_smp_num]; 382 //_p_tables[pxWAVETYPE.Random2] = new short[_smp_num_rand]; 383 _p_tables[pxWAVETYPE.Rect3] = new short[_smp_num]; 384 _p_tables[pxWAVETYPE.Rect4] = new short[_smp_num]; 385 _p_tables[pxWAVETYPE.Rect8] = new short[_smp_num]; 386 _p_tables[pxWAVETYPE.Rect16] = new short[_smp_num]; 387 _p_tables[pxWAVETYPE.Saw3] = new short[_smp_num]; 388 _p_tables[pxWAVETYPE.Saw4] = new short[_smp_num]; 389 _p_tables[pxWAVETYPE.Saw6] = new short[_smp_num]; 390 _p_tables[pxWAVETYPE.Saw8] = new short[_smp_num]; 391 392 // none -- 393 394 // sine -- 395 osci.ReadyGetSample(overtones_sine[], 1, 128, _smp_num, 0); 396 p = _p_tables[pxWAVETYPE.Sine]; 397 for (s = 0; s < _smp_num; s++) { 398 work = osci.GetOneSample_Overtone(s); 399 if (work > 1.0) { 400 work = 1.0; 401 } 402 if (work < -1.0) { 403 work = -1.0; 404 } 405 p[0] = cast(short)(work * _SAMPLING_TOP); 406 p = p[1 .. $]; 407 } 408 409 // saw down -- 410 p = _p_tables[pxWAVETYPE.Saw]; 411 work = _SAMPLING_TOP + _SAMPLING_TOP; 412 for (s = 0; s < _smp_num; s++) { 413 p[0] = cast(short)(_SAMPLING_TOP - work * s / _smp_num); 414 p = p[1 .. $]; 415 } 416 417 // rect -- 418 p = _p_tables[pxWAVETYPE.Rect]; 419 for (s = 0; s < _smp_num / 2; s++) { 420 p[0] = cast(short)(_SAMPLING_TOP); 421 p = p[1 ..$]; 422 } 423 for ( /+s+/ ; s < _smp_num; s++) { 424 p[0] = cast(short)(-_SAMPLING_TOP); 425 p = p[1 .. $]; 426 } 427 428 // random -- 429 p = _p_tables[pxWAVETYPE.Random]; 430 _random_reset(); 431 for (s = 0; s < _smp_num_rand; s++) { 432 p[0] = _random_get(); 433 p = p[1 .. $]; 434 } 435 436 // saw2 -- 437 osci.ReadyGetSample(overtones_saw2[], 16, 128, _smp_num, 0); 438 p = _p_tables[pxWAVETYPE.Saw2]; 439 for (s = 0; s < _smp_num; s++) { 440 work = osci.GetOneSample_Overtone(s); 441 if (work > 1.0) { 442 work = 1.0; 443 } 444 if (work < -1.0) { 445 work = -1.0; 446 } 447 p[0] = cast(short)(work * _SAMPLING_TOP); 448 p = p[1 .. $]; 449 } 450 451 // rect2 -- 452 osci.ReadyGetSample(overtones_rect2[], 8, 128, _smp_num, 0); 453 p = _p_tables[pxWAVETYPE.Rect2]; 454 for (s = 0; s < _smp_num; s++) { 455 work = osci.GetOneSample_Overtone(s); 456 if (work > 1.0) { 457 work = 1.0; 458 } 459 if (work < -1.0) { 460 work = -1.0; 461 } 462 p[0] = cast(short)(work * _SAMPLING_TOP); 463 p = p[1 .. $]; 464 } 465 466 // Triangle -- 467 osci.ReadyGetSample(coodi_tri[], 4, 128, _smp_num, _smp_num); 468 p = _p_tables[pxWAVETYPE.Tri]; 469 for (s = 0; s < _smp_num; s++) { 470 work = osci.GetOneSample_Coodinate(s); 471 if (work > 1.0) { 472 work = 1.0; 473 } 474 if (work < -1.0) { 475 work = -1.0; 476 } 477 p[0] = cast(short)(work * _SAMPLING_TOP); 478 p = p[1 .. $]; 479 } 480 481 // Random2 -- x 482 483 // Rect-3 -- 484 p = _p_tables[pxWAVETYPE.Rect3]; 485 for (s = 0; s < _smp_num / 3; s++) { 486 p[0] = cast(short)(_SAMPLING_TOP); 487 p = p[1 .. $]; 488 } 489 for ( /+s+/ ; s < _smp_num; s++) { 490 p[0] = cast(short)(-_SAMPLING_TOP); 491 p = p[1 .. $]; 492 } 493 // Rect-4 -- 494 p = _p_tables[pxWAVETYPE.Rect4]; 495 for (s = 0; s < _smp_num / 4; s++) { 496 p[0] = cast(short)(_SAMPLING_TOP); 497 p = p[1 .. $]; 498 } 499 for ( /+s+/ ; s < _smp_num; s++) { 500 p[0] = cast(short)(-_SAMPLING_TOP); 501 p = p[1 .. $]; 502 } 503 // Rect-8 -- 504 p = _p_tables[pxWAVETYPE.Rect8]; 505 for (s = 0; s < _smp_num / 8; s++) { 506 p[0] = cast(short)(_SAMPLING_TOP); 507 p = p[1 .. $]; 508 } 509 for ( /+s+/ ; s < _smp_num; s++) { 510 p[0] = cast(short)(-_SAMPLING_TOP); 511 p = p[1 .. $]; 512 } 513 // Rect-16 -- 514 p = _p_tables[pxWAVETYPE.Rect16]; 515 for (s = 0; s < _smp_num / 16; s++) { 516 p[0] = cast(short)(_SAMPLING_TOP); 517 p = p[1 .. $]; 518 } 519 for ( /+s+/ ; s < _smp_num; s++) { 520 p[0] = cast(short)(-_SAMPLING_TOP); 521 p = p[1 .. $]; 522 } 523 524 // Saw-3 -- 525 p = _p_tables[pxWAVETYPE.Saw3]; 526 for (s = 0; s < _smp_num / 3; s++) { 527 p[0] = cast(short)(_SAMPLING_TOP); 528 p = p[1 .. $]; 529 } 530 for ( /+s+/ ; s < _smp_num * 2 / 3; s++) { 531 p[0] = cast(short)(0); 532 p = p[1 .. $]; 533 } 534 for ( /+s+/ ; s < _smp_num; s++) { 535 p[0] = cast(short)(-_SAMPLING_TOP); 536 p = p[1 .. $]; 537 } 538 539 // Saw-4 -- 540 p = _p_tables[pxWAVETYPE.Saw4]; 541 for (s = 0; s < _smp_num / 4; s++) { 542 p[0] = cast(short)(_SAMPLING_TOP); 543 p = p[1 .. $]; 544 } 545 for ( /+s+/ ; s < _smp_num * 2 / 4; s++) { 546 p[0] = cast(short)(_SAMPLING_TOP / 3); 547 p = p[1 .. $]; 548 } 549 for ( /+s+/ ; s < _smp_num * 3 / 4; s++) { 550 p[0] = cast(short)(-_SAMPLING_TOP / 3); 551 p = p[1 .. $]; 552 } 553 for ( /+s+/ ; s < _smp_num; s++) { 554 p[0] = cast(short)(-_SAMPLING_TOP); 555 p = p[1 .. $]; 556 } 557 558 // Saw-6 -- 559 p = _p_tables[pxWAVETYPE.Saw6]; 560 a = _smp_num * 1 / 6; 561 v = _SAMPLING_TOP; 562 for (s = 0; s < a; s++) { 563 p[0] = v; 564 p = p[1 .. $]; 565 } 566 a = _smp_num * 2 / 6; 567 v = _SAMPLING_TOP - _SAMPLING_TOP * 2 / 5; 568 for ( /+s+/ ; s < a; s++) { 569 p[0] = v; 570 p = p[1 .. $]; 571 } 572 a = _smp_num * 3 / 6; 573 v = _SAMPLING_TOP / 5; 574 for ( /+s+/ ; s < a; s++) { 575 p[0] = v; 576 p = p[1 .. $]; 577 } 578 a = _smp_num * 4 / 6; 579 v = -_SAMPLING_TOP / 5; 580 for ( /+s+/ ; s < a; s++) { 581 p[0] = v; 582 p = p[1 .. $]; 583 } 584 a = _smp_num * 5 / 6; 585 v = -_SAMPLING_TOP + _SAMPLING_TOP * 2 / 5; 586 for ( /+s+/ ; s < a; s++) { 587 p[0] = v; 588 p = p[1 .. $]; 589 } 590 a = _smp_num; 591 v = -_SAMPLING_TOP; 592 for ( /+s+/ ; s < a; s++) { 593 p[0] = v; 594 p = p[1 .. $]; 595 } 596 597 // Saw-8 -- 598 p = _p_tables[pxWAVETYPE.Saw8]; 599 a = _smp_num * 1 / 8; 600 v = _SAMPLING_TOP; 601 for (s = 0; s < a; s++) { 602 p[0] = v; 603 p = p[1 .. $]; 604 } 605 a = _smp_num * 2 / 8; 606 v = _SAMPLING_TOP - _SAMPLING_TOP * 2 / 7; 607 for ( /+s+/ ; s < a; s++) { 608 p[0] = v; 609 p = p[1 .. $]; 610 } 611 a = _smp_num * 3 / 8; 612 v = _SAMPLING_TOP - _SAMPLING_TOP * 4 / 7; 613 for ( /+s+/ ; s < a; s++) { 614 p[0] = v; 615 p = p[1 .. $]; 616 } 617 a = _smp_num * 4 / 8; 618 v = _SAMPLING_TOP / 7; 619 for ( /+s+/ ; s < a; s++) { 620 p[0] = v; 621 p = p[1 .. $]; 622 } 623 a = _smp_num * 5 / 8; 624 v = -_SAMPLING_TOP / 7; 625 for ( /+s+/ ; s < a; s++) { 626 p[0] = v; 627 p = p[1 .. $]; 628 } 629 a = _smp_num * 6 / 8; 630 v = -_SAMPLING_TOP + _SAMPLING_TOP * 4 / 7; 631 for ( /+s+/ ; s < a; s++) { 632 p[0] = v; 633 p = p[1 .. $]; 634 } 635 a = _smp_num * 7 / 8; 636 v = -_SAMPLING_TOP + _SAMPLING_TOP * 2 / 7; 637 for ( /+s+/ ; s < a; s++) { 638 p[0] = v; 639 p = p[1 .. $]; 640 } 641 a = _smp_num; 642 v = -_SAMPLING_TOP; 643 for ( /+s+/ ; s < a; s++) { 644 p[0] = v; 645 p = p[1 .. $]; 646 } 647 return _p_tables; 648 }