| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - Channel structures |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-12 |
|
| 4 |
+ * Last modification on 2013-04-18 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Adapted from source code of FeOS Sound System |
| 7 | 7 |
* By fincs |
| ... | ... |
@@ -47,6 +47,7 @@ Channel::Channel() : chnId(-1), tempReg(), state(CS_NONE), trackId(-1), prio(0), |
| 47 | 47 |
key(0), ampl(0), extTune(0), orgKey(0), modType(0), modSpeed(0), modDepth(0), modRange(0), modDelay(0), modDelayCnt(0), modCounter(0), |
| 48 | 48 |
sweepLen(0), sweepCnt(0), sweepPitch(0), attackLvl(0), sustainLvl(0x7F), decayRate(0), releaseRate(0xFFFF), noteLength(-1), vol(0), ply(nullptr), reg() |
| 49 | 49 |
{
|
| 50 |
+ this->clearHistory(); |
|
| 50 | 51 |
} |
| 51 | 52 |
|
| 52 | 53 |
void Channel::UpdateVol(const Track &trk) |
| ... | ... |
@@ -122,6 +123,7 @@ void Channel::Kill() |
| 122 | 123 |
this->reg.ClearControlRegister(); |
| 123 | 124 |
this->vol = 0; |
| 124 | 125 |
this->noteLength = -1; |
| 126 |
+ this->clearHistory(); |
|
| 125 | 127 |
} |
| 126 | 128 |
|
| 127 | 129 |
static inline int getModFlag(int type) |
| ... | ... |
@@ -585,38 +587,17 @@ int32_t Channel::Interpolate() |
| 585 | 587 |
double ratio = this->reg.samplePosition; |
| 586 | 588 |
ratio -= static_cast<int32_t>(ratio); |
| 587 | 589 |
|
| 588 |
- uint32_t loc = static_cast<uint32_t>(this->reg.samplePosition); |
|
| 589 |
- const auto &data = &this->reg.source->dataptr[loc]; |
|
| 590 |
- int32_t a = data[0], b; |
|
| 591 |
- if (loc + 1 < this->reg.totalLength) |
|
| 592 |
- b = data[1]; |
|
| 593 |
- else |
|
| 594 |
- b = a; |
|
| 590 |
+ const auto &data = &this->sampleHistory[this->sampleHistoryPtr + 5]; |
|
| 591 |
+ int32_t a = data[0], b = data[1]; |
|
| 595 | 592 |
|
| 596 | 593 |
double c0, c1, c2, c3, c4, c5; |
| 597 | 594 |
if (this->ply->interpolation > INTERPOLATION_COSINE) |
| 598 | 595 |
{
|
| 599 |
- int32_t c, z; |
|
| 600 |
- if (loc + 2 < this->reg.totalLength) |
|
| 601 |
- c = data[2]; |
|
| 602 |
- else |
|
| 603 |
- c = b; |
|
| 604 |
- if (loc) |
|
| 605 |
- z = data[-1]; |
|
| 606 |
- else |
|
| 607 |
- z = a; |
|
| 596 |
+ int32_t c = data[2], z = data[-1]; |
|
| 608 | 597 |
|
| 609 | 598 |
if (this->ply->interpolation > INTERPOLATION_4POINTBSPLINE) |
| 610 | 599 |
{
|
| 611 |
- int32_t d, y; |
|
| 612 |
- if (loc + 3 < this->reg.totalLength) |
|
| 613 |
- d = data[3]; |
|
| 614 |
- else |
|
| 615 |
- d = c; |
|
| 616 |
- if (loc > 1) |
|
| 617 |
- y = data[-2]; |
|
| 618 |
- else |
|
| 619 |
- y = z; |
|
| 600 |
+ int32_t d = data[3], y = data[-2]; |
|
| 620 | 601 |
|
| 621 | 602 |
if (this->ply->interpolation == INTERPOLATION_6POINTBSPLINE) |
| 622 | 603 |
{
|
| ... | ... |
@@ -631,7 +612,7 @@ int32_t Channel::Interpolate() |
| 631 | 612 |
c5 = 1 / 120.0 * (d - y) + 1 / 24.0 * (z - c) + 1 / 12.0 * (b - a); |
| 632 | 613 |
return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0); |
| 633 | 614 |
} |
| 634 |
- else |
|
| 615 |
+ else // INTERPOLATION_6POINTOSCULATING |
|
| 635 | 616 |
{
|
| 636 | 617 |
ratio -= 0.5; |
| 637 | 618 |
double even1 = y + d, odd1 = y - d; |
| ... | ... |
@@ -646,7 +627,7 @@ int32_t Channel::Interpolate() |
| 646 | 627 |
return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0); |
| 647 | 628 |
} |
| 648 | 629 |
} |
| 649 |
- else |
|
| 630 |
+ else // INTERPOLATION_4POINTBSPLINE |
|
| 650 | 631 |
{
|
| 651 | 632 |
double ym1py1 = z + b; |
| 652 | 633 |
c0 = 1 / 6.0 * ym1py1 + 2 / 3.0 * a; |
| ... | ... |
@@ -661,7 +642,7 @@ int32_t Channel::Interpolate() |
| 661 | 642 |
double ratio2 = (1.0 - std::cos(ratio * M_PI)) * 0.5; |
| 662 | 643 |
return static_cast<int32_t>(a + ratio2 * (b - a)); |
| 663 | 644 |
} |
| 664 |
- else |
|
| 645 |
+ else // INTERPOLATION_LINEAR |
|
| 665 | 646 |
return static_cast<int32_t>(a + ratio * (b - a)); |
| 666 | 647 |
} |
| 667 | 648 |
|
| ... | ... |
@@ -712,7 +693,29 @@ int32_t Channel::GenerateSample() |
| 712 | 693 |
|
| 713 | 694 |
void Channel::IncrementSample() |
| 714 | 695 |
{
|
| 715 |
- this->reg.samplePosition += this->reg.sampleIncrease; |
|
| 696 |
+ double samplePosition = this->reg.samplePosition + this->reg.sampleIncrease; |
|
| 697 |
+ |
|
| 698 |
+ if (this->reg.format != 3 && this->reg.samplePosition >= 0) |
|
| 699 |
+ {
|
|
| 700 |
+ uint32_t loc = static_cast<uint32_t>(this->reg.samplePosition); |
|
| 701 |
+ uint32_t newloc = static_cast<uint32_t>(samplePosition); |
|
| 702 |
+ |
|
| 703 |
+ if (newloc >= this->reg.totalLength) |
|
| 704 |
+ newloc -= this->reg.length; |
|
| 705 |
+ |
|
| 706 |
+ while (loc != newloc) |
|
| 707 |
+ {
|
|
| 708 |
+ this->sampleHistory[this->sampleHistoryPtr] = this->sampleHistory[this->sampleHistoryPtr + 8] = this->reg.source->dataptr[loc++]; |
|
| 709 |
+ |
|
| 710 |
+ this->sampleHistoryPtr = (this->sampleHistoryPtr + 1) & 7; |
|
| 711 |
+ |
|
| 712 |
+ if (loc >= this->reg.totalLength) |
|
| 713 |
+ loc -= this->reg.length; |
|
| 714 |
+ } |
|
| 715 |
+ } |
|
| 716 |
+ |
|
| 717 |
+ this->reg.samplePosition = samplePosition; |
|
| 718 |
+ |
|
| 716 | 719 |
if (this->reg.format != 3 && this->reg.samplePosition >= this->reg.totalLength) |
| 717 | 720 |
{
|
| 718 | 721 |
if (this->reg.repeatMode == 1) |
| ... | ... |
@@ -724,3 +727,9 @@ void Channel::IncrementSample() |
| 724 | 727 |
this->Kill(); |
| 725 | 728 |
} |
| 726 | 729 |
} |
| 730 |
+ |
|
| 731 |
+void Channel::clearHistory() |
|
| 732 |
+{
|
|
| 733 |
+ this->sampleHistoryPtr = 0; |
|
| 734 |
+ memset(this->sampleHistory, 0, sizeof(this->sampleHistory)); |
|
| 735 |
+} |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - Channel structures |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-02 |
|
| 4 |
+ * Last modification on 2013-04-18 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Adapted from source code of FeOS Sound System |
| 7 | 7 |
* By fincs |
| ... | ... |
@@ -127,6 +127,14 @@ struct Channel |
| 127 | 127 |
const Player *ply; |
| 128 | 128 |
NDSSoundRegister reg; |
| 129 | 129 |
|
| 130 |
+ /* |
|
| 131 |
+ * Interpolation history buffer, which contains the maximum number of |
|
| 132 |
+ * samples required for any given interpolation mode. Doubled to |
|
| 133 |
+ * simplify the case of wrapping. Thanks to kode54 for providing this. |
|
| 134 |
+ */ |
|
| 135 |
+ uint32_t sampleHistoryPtr; |
|
| 136 |
+ int16_t sampleHistory[16]; |
|
| 137 |
+ |
|
| 130 | 138 |
Channel(); |
| 131 | 139 |
|
| 132 | 140 |
void UpdateVol(const Track &trk); |
| ... | ... |
@@ -141,6 +149,7 @@ struct Channel |
| 141 | 149 |
int32_t Interpolate(); |
| 142 | 150 |
int32_t GenerateSample(); |
| 143 | 151 |
void IncrementSample(); |
| 152 |
+ void clearHistory(); |
|
| 144 | 153 |
}; |
| 145 | 154 |
|
| 146 | 155 |
#endif |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - Player structure |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-01 |
|
| 4 |
+ * Last modification on 2013-04-18 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Adapted from source code of FeOS Sound System |
| 7 | 7 |
* By fincs |
| ... | ... |
@@ -120,6 +120,7 @@ int Player::ChannelAlloc(int type, int priority) |
| 120 | 120 |
this->channels[curChnNo].ply = this; |
| 121 | 121 |
this->channels[curChnNo].noteLength = -1; |
| 122 | 122 |
this->channels[curChnNo].vol = 0; |
| 123 |
+ this->channels[curChnNo].clearHistory(); |
|
| 123 | 124 |
return curChnNo; |
| 124 | 125 |
} |
| 125 | 126 |
|