* Added more interpolation methods to in_ncsf.
* Cleaned up a little of the code in the Interpolate function in in_ncsf.
* Made it so changes in the config can apply to a running song, depending on the player.
* Slight optimization of in_ncsf's interpolation so it doesn't have as much std::vector accessing.
* Stopped trying to use the slope of the points to determine points outside the sample's range, hopefully will stop some of the clipping.
--- a/src/in_ncsf/SSEQPlayer/Channel.cpp
+++ b/src/in_ncsf/SSEQPlayer/Channel.cpp
@@ -1,7 +1,7 @@
/*
* SSEQ Player - Channel structures
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-02
+ * Last modification on 2013-04-10
*
* Adapted from source code of FeOS Sound System
* By fincs
@@ -586,52 +586,108 @@
ratio -= static_cast<int32_t>(ratio);
uint32_t loc = static_cast<uint32_t>(this->reg.samplePosition);
- const auto &data = &this->reg.source->data[loc];
+ const auto &data = &this->reg.source->dataptr[loc];
int32_t a = data[0], b;
if (loc + 1 < this->reg.totalLength)
b = data[1];
else
- {
- if (loc)
- {
- int32_t am1 = data[-1];
- b = 2 * a - am1;
- }
- else
- b = a;
- }
-
- if (this->ply->interpolation == INTERPOLATION_BSPLINE || this->ply->interpolation == INTERPOLATION_HERMITE || this->ply->interpolation == INTERPOLATION_OPTIMAL)
+ b = a;
+
+ double c0, c1, c2, c3, c4, c5;
+ if (this->ply->interpolation > INTERPOLATION_2POINTOPTIMAL)
{
int32_t c, z;
if (loc + 2 < this->reg.totalLength)
c = data[2];
else
- {
- if (loc)
- {
- int32_t am1 = data[-1];
- c = 3 * a - 2 * am1;
- }
- else
- c = a;
- }
+ c = a;
if (loc)
z = data[-1];
else
- {
- if (loc + 1 < this->reg.totalLength)
+ z = a;
+
+ if (this->ply->interpolation > INTERPOLATION_4POINTOPTIMAL)
+ {
+ int32_t d, y;
+ if (loc + 3 < this->reg.totalLength)
+ d = data[3];
+ else
+ d = a;
+ if (loc > 1)
+ y = data[-2];
+ else
+ y = a;
+
+ if (this->ply->interpolation == INTERPOLATION_6POINTHERMITE)
{
- int32_t ap1 = data[1];
- z = 2 * a - ap1;
+ double eighthym2 = 0.125 * y;
+ double eleventwentyfourthy2 = 11 / 24.0 * c;
+ double twelfthy3 = 1 / 12.0 * d;
+ c0 = a;
+ c1 = 1 / 12.0 * (y - c) + 2 / 3.0 * (b - z);
+ c2 = 13 / 12.0 * z - 25 / 12.0 * a + 1.5 * b - eleventwentyfourthy2 + twelfthy3 - eighthym2;
+ c3 = 5 / 12.0 * a - 7 / 12.0 * b + 7 / 24.0 * c - 1 / 24.0 * (y + z + d);
+ c4 = eighthym2 - 7 / 12.0 * z + 13 / 12.0 * a - b + eleventwentyfourthy2 - twelfthy3;
+ c5 = 1 / 24.0 * (d - y) + 5 / 24.0 * (z - c) + 5 / 12.0 * (b - a);
+ return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ else if (this->ply->interpolation == INTERPOLATION_6POINTLAGRANGE)
+ {
+ float ym1py1 = z + b;
+ float twentyfourthym2py2 = 1 / 24.0 * (y + c);
+ float c0 = a;
+ float c1 = 1 / 20.0 * y - 0.5 * z - 1 / 3.0 * a + b - 0.25 * c + 1 / 30.0 * d;
+ float c2 = 2 / 3.0 * ym1py1 - 1.25 * a - twentyfourthym2py2;
+ float c3 = 5 / 12.0 * a - 7 / 12.0 * b + 7 / 24.0 * c - 1 / 24.0 * (y + z + d);
+ float c4 = 0.25 * a - 1 / 6.0 * ym1py1 + twentyfourthym2py2;
+ float c5 = 1 / 120.0 * (d - y) + 1 / 24.0 * (z - c) + 1 / 12.0 * (b - a);
+ return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ else if (this->ply->interpolation == INTERPOLATION_6POINTBSPLINE)
+ {
+ double ym2py2 = y + c, ym1py1 = z + b;
+ double y2mym2 = c - y, y1mym1 = b - z;
+ double sixthym1py1 = 1 / 6.0 * ym1py1;
+ c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * a;
+ c1 = 1 / 24.0 * y2mym2 + 5 / 12.0 * y1mym1;
+ c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * a;
+ c3 = 1 / 12.0 * y2mym2 - 1 / 6.0 * y1mym1;
+ c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * a;
+ c5 = 1 / 120.0 * (d - y) + 1 / 24.0 * (z - c) + 1 / 12.0 * (b - a);
+ return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
}
else
- z = a;
- }
-
- double c0, c1, c2, c3;
-
- if (this->ply->interpolation == INTERPOLATION_BSPLINE)
+ {
+ ratio -= 0.5;
+ double even1 = b + a, odd1 = b - a;
+ double even2 = c + z, odd2 = c - z;
+ double even3 = d + y, odd3 = d - y;
+ c0 = even1 * 0.41809989254549901 + even2 * 0.08049339946273310 + even3 * 0.00140670799165932;
+ c1 = odd1 * 0.32767596257424964 + odd2 * 0.20978189376640677 + odd3 * 0.00859567104974701;
+ c2 = even1 * -0.206944618112960001 + even2 * 0.18541689550861262 + even3 * 0.02152772260740132;
+ c3 = odd1 * -0.21686095413034051 + odd2 * 0.02509557922091643 + odd3 * 0.02831484751363800;
+ c4 = even1 * 0.04163046817137675 + even2 * -0.06244556931623735 + even3 * 0.02081510113314315;
+ c5 = odd1 * 0.07990500783668089 + odd2 * -0.03994519162531633 + odd3 * 0.00798609327859495;
+ return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ }
+ else if (this->ply->interpolation == INTERPOLATION_4POINTHERMITE)
+ {
+ c0 = a;
+ c1 = 0.5 * (b - z);
+ c2 = z - 2.5 * a + 2 * b - 0.5 * c;
+ c3 = 0.5 * (c - z) + 1.5 * (a - b);
+ return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ else if (this->ply->interpolation == INTERPOLATION_4POINTLAGRANGE)
+ {
+ float c0 = a;
+ float c1 = b - 1 / 3.0 * z - 0.5 * a - 1 / 6.0 * c;
+ float c2 = 0.5 * (z + b) - a;
+ float c3 = 1 / 6.0 * (c - z) + 0.5 * (a - b);
+ return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ else if (this->ply->interpolation == INTERPOLATION_4POINTBSPLINE)
{
double zpb = z + b;
c0 = 1 / 6.0 * zpb + 2 / 3.0 * a;
@@ -640,26 +696,28 @@
c3 = 0.5 * (a - b) + 1 / 6.0 * (c - z);
return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
}
- else if (this->ply->interpolation == INTERPOLATION_HERMITE)
- {
- c0 = a;
- c1 = 0.5 * (b - z);
- c2 = z - 2.5 * a + 2 * b - 0.5 * c;
- c3 = 0.5 * (c - z) + 1.5 * (a - b);
- return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
- }
else
{
ratio -= 0.5;
double even1 = b + a, odd1 = b - a;
double even2 = c + z, odd2 = c - z;
- c0 = even1 * 0.46835497211269561 + even2 * 0.03164502784253309;
- c1 = odd1 * 0.56001293337091440 + odd2 * 0.14666238593949288;
- c2 = even1 * -0.250038759826233691 + even2 * 0.25003876124297131;
- c3 = odd1 * -0.49949850957839148 + odd2 * 0.16649935475113800;
- double c4 = even1 * 0.00016095224137360 + even2 * -0.00016095810460478;
+ c0 = even1 * 0.46822774170144532 + even2 * 0.03177225758005808;
+ c1 = odd1 * 0.55890365706150436 + odd2 * 0.14703258836343669;
+ c2 = even1 * -0.250153411893796031 + even2 * 0.25015343462990891;
+ c3 = odd1 * -0.49800710906733769 + odd2 * 0.16600005174304033;
+ c4 = even1 * 0.00064264050033187 + even2 * -0.00064273459469381;
return static_cast<int32_t>((((c4 * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
}
+ }
+ else if (this->ply->interpolation == INTERPOLATION_2POINTOPTIMAL)
+ {
+ ratio -= 0.5;
+ double even1 = b + a, odd1 = b - a;
+ c0 = even1 * 0.50001096675880796;
+ c1 = odd1 * 1.03585606328743830;
+ c2 = even1 * -0.000131601105693441;
+ c3 = odd1 * -0.38606621963374965;
+ return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
}
else if (this->ply->interpolation == INTERPOLATION_COSINE)
{
@@ -678,7 +736,7 @@
if (this->reg.format != 3)
{
if (this->ply->interpolation == INTERPOLATION_NONE)
- return this->reg.source->data[static_cast<uint32_t>(this->reg.samplePosition)];
+ return this->reg.source->dataptr[static_cast<uint32_t>(this->reg.samplePosition)];
else
return this->Interpolate();
}
--- a/src/in_ncsf/SSEQPlayer/SWAV.cpp
+++ b/src/in_ncsf/SSEQPlayer/SWAV.cpp
@@ -1,7 +1,7 @@
/*
* SSEQ Player - SDAT SWAV (Waveform/Sample) structure
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-03-25
+ * Last modification on 2013-04-10
*
* Nintendo DS Nitro Composer (SDAT) Specification document found at
* http://www.feshrine.net/hacking/doc/nds-sdat.html
@@ -28,7 +28,7 @@
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
-SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonLoopLength(0), data()
+SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonLoopLength(0), data(), dataptr(nullptr)
{
}
@@ -119,5 +119,6 @@
this->loopOffset *= 8;
this->nonLoopLength *= 8;
}
+ this->dataptr = &this->data[0];
}
--- a/src/in_ncsf/SSEQPlayer/SWAV.h
+++ b/src/in_ncsf/SSEQPlayer/SWAV.h
@@ -1,7 +1,7 @@
/*
* SSEQ Player - SDAT SWAV (Waveform/Sample) structure
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-03-21
+ * Last modification on 2013-04-10
*
* Nintendo DS Nitro Composer (SDAT) Specification document found at
* http://www.feshrine.net/hacking/doc/nds-sdat.html
@@ -21,6 +21,7 @@
uint32_t loopOffset;
uint32_t nonLoopLength;
std::vector<int16_t> data;
+ const int16_t *dataptr;
SWAV();
--- a/src/in_ncsf/SSEQPlayer/consts.h
+++ b/src/in_ncsf/SSEQPlayer/consts.h
@@ -1,7 +1,7 @@
/*
* SSEQ Player - Constants/Macros
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-02
+ * Last modification on 2013-04-10
*
* Adapted from source code of FeOS Sound System
* By fincs
@@ -51,7 +51,21 @@
inline uint32_t SOUND_FORMAT(int n) { return n << 29; }
const uint32_t SCHANNEL_ENABLE = BIT(31);
-enum Interpolation { INTERPOLATION_NONE, INTERPOLATION_LINEAR, INTERPOLATION_COSINE, INTERPOLATION_BSPLINE, INTERPOLATION_HERMITE, INTERPOLATION_OPTIMAL };
+enum Interpolation
+{
+ INTERPOLATION_NONE,
+ INTERPOLATION_LINEAR,
+ INTERPOLATION_COSINE,
+ INTERPOLATION_2POINTOPTIMAL,
+ INTERPOLATION_4POINTHERMITE,
+ INTERPOLATION_4POINTLAGRANGE,
+ INTERPOLATION_4POINTBSPLINE,
+ INTERPOLATION_4POINTOPTIMAL,
+ INTERPOLATION_6POINTHERMITE,
+ INTERPOLATION_6POINTLAGRANGE,
+ INTERPOLATION_6POINTBSPLINE,
+ INTERPOLATION_6POINTOPTIMAL
+};
#endif
--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -1,7 +1,7 @@
/*
* xSF - NCSF configuration
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-02
+ * Last modification on 2013-04-10
*
* Partially based on the vio*sf framework
*/
@@ -42,8 +42,8 @@
unsigned XSFConfig::initSampleRate = 44100;
std::wstring XSFConfig::commonName = L"NCSF Decoder";
-std::wstring XSFConfig::versionNumber = L"1.2";
-unsigned XSFConfig_NCSF::initInterpolation = 5;
+std::wstring XSFConfig::versionNumber = L"1.3";
+unsigned XSFConfig_NCSF::initInterpolation = 7;
std::wstring XSFConfig_NCSF::initMutes = L"0000000000000000";
XSFConfig *XSFConfig::Create()
@@ -82,7 +82,7 @@
void XSFConfig_NCSF::GenerateSpecificDialogs()
{
this->configDialog.AddLabelControl(DialogLabelBuilder(L"Interpolation").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::FROM_BOTTOMLEFT, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(90, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::FROM_TOPRIGHT, Point<short>(5, -3)).WithID(idInterpolation).
+ this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(110, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::FROM_TOPRIGHT, Point<short>(5, -3)).WithID(idInterpolation).
IsDropDownList().WithTabStop());
this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::FROM_BOTTOMLEFT, Point<short>(0, 10), 2).IsLeftJustified());
this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::FROM_TOPRIGHT, Point<short>(5, -3)).WithID(idMutes).
@@ -95,12 +95,18 @@
{
case WM_INITDIALOG:
// Interpolation
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"No Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Cosine Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"B-spline Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Hermite Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Optimal Interpolation"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"None"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Cosine"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"2-point, 3rd-order Optimal 16x"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order Hermite"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order Lagrange"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order B-spline"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 4th-order Optimal 16x"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Hermite"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Lagrange"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order B-spline"));
+ SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Optimal 16x"));
SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
// Mutes
for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
@@ -131,13 +137,11 @@
this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
}
-void XSFConfig_NCSF::CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad)
+void XSFConfig_NCSF::CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool)
{
XSFPlayer_NCSF *NCSFPlayer = static_cast<XSFPlayer_NCSF *>(xSFPlayer);
- if (preLoad)
- NCSFPlayer->SetInterpolation(this->interpolation);
- else
- NCSFPlayer->SetMutes(this->mutes);
+ NCSFPlayer->SetInterpolation(this->interpolation);
+ NCSFPlayer->SetMutes(this->mutes);
}
void XSFConfig_NCSF::About(HWND parent)
--- a/src/in_xsf_framework/in_xsf.cpp
+++ b/src/in_xsf_framework/in_xsf.cpp
@@ -1,7 +1,7 @@
/*
* xSF - Winamp plugin
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-02
+ * Last modification on 2013-04-10
*
* Partially based on the vio*sf framework
*/
@@ -73,6 +73,8 @@
void config(HWND hwndParent)
{
xSFConfig->CallConfigDialog(inMod.hDllInstance, hwndParent);
+ if (xSFPlayer)
+ xSFConfig->CopyConfigToMemory(xSFPlayer, false);
}
void about(HWND hwndParent)