diff --git a/include/DrumSynth.h b/include/DrumSynth.h index 750055ddb..3b418abd6 100644 --- a/include/DrumSynth.h +++ b/include/DrumSynth.h @@ -27,33 +27,33 @@ #define LMMS_DRUM_SYNTH_H #include + #include "lmms_basics.h" class QString; -namespace lmms +namespace lmms { + +class DrumSynth { +public: + DrumSynth() = default; + int GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sample_rate_t Fs); -class DrumSynth { - public: - DrumSynth() = default; - int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs); +private: + float LoudestEnv(); + int LongestEnv(); + void UpdateEnv(int e, long t); + void GetEnv(int env, const char* sec, const char* key, QString ini); - private: - float LoudestEnv(); - int LongestEnv(); - void UpdateEnv(int e, long t); - void GetEnv(int env, const char *sec, const char *key, QString ini); - - float waveform(float ph, int form); - - int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file); - int GetPrivateProfileInt(const char *sec, const char *key, int def, QString file); - float GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file); + float waveform(float ph, int form); + int GetPrivateProfileString( + const char* sec, const char* key, const char* def, char* buffer, int size, QString file); + int GetPrivateProfileInt(const char* sec, const char* key, int def, QString file); + float GetPrivateProfileFloat(const char* sec, const char* key, float def, QString file); }; - } // namespace lmms #endif // LMMS_DRUM_SYNTH_H diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index 031b19c1c..f855639cb 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -23,49 +23,42 @@ * */ - #include "DrumSynth.h" -#include -#include - -#include //sin(), exp(), etc. - #include - +#include +#include +#include #ifdef _MSC_VER -//not #if LMMS_BUILD_WIN32 because we have strncasecmp in mingw +// not #if LMMS_BUILD_WIN32 because we have strncasecmp in mingw #define strcasecmp _stricmp #endif // _MSC_VER -namespace lmms -{ - +namespace lmms { using namespace std; // const int Fs = 44100; -const float TwoPi = 6.2831853f; -const int MAX = 0; -const int ENV = 1; -const int PNT = 2; -const int dENV = 3; -const int NEXTT = 4; +const float TwoPi = 6.2831853f; +const int MAX = 0; +const int ENV = 1; +const int PNT = 2; +const int dENV = 3; +const int NEXTT = 4; // Bah, I'll move these into the class once I sepearate DrumsynthFile from DrumSynth // llama -float envpts[8][3][32]; //envelope/time-level/point -float envData[8][6]; //envelope running status -int chkOn[8], sliLev[8]; //section on/off and level -float timestretch; //overall time scaling +float envpts[8][3][32]; // envelope/time-level/point +float envData[8][6]; // envelope running status +int chkOn[8], sliLev[8]; // section on/off and level +float timestretch; // overall time scaling short DD[1200], clippoint; float DF[1200]; float phi[1200]; -long wavewords, wavemode=0; -float mem_t=1.0f, mem_o=1.0f, mem_n=1.0f, mem_b=1.0f, mem_tune=1.0f, mem_time=1.0f; - +long wavewords, wavemode = 0; +float mem_t = 1.0f, mem_o = 1.0f, mem_n = 1.0f, mem_b = 1.0f, mem_tune = 1.0f, mem_time = 1.0f; int DrumSynth::LongestEnv() { @@ -74,78 +67,107 @@ int DrumSynth::LongestEnv() for (long e = 1; e < 7; e++) // 3 { long eon = e - 1; - if (eon > 2) { eon = eon - 1; } + if (eon > 2) + { + eon = eon - 1; + } long p = 0; - while (envpts[e][0][p + 1] >= 0.f) { p++; } + while (envpts[e][0][p + 1] >= 0.f) + { + p++; + } envData[e][MAX] = envpts[e][0][p] * timestretch; - if (chkOn[eon] == 1 && envData[e][MAX] > l) { l = envData[e][MAX]; } - } - //l *= timestretch; + if (chkOn[eon] == 1 && envData[e][MAX] > l) + { + l = envData[e][MAX]; + } + } + // l *= timestretch; - return 2400 + (1200 * (int)(l / 1200)); + return 2400 + (1200 * static_cast(l / 1200)); } - float DrumSynth::LoudestEnv() { - float loudest=0.f; - int i=0; + float loudest = 0.f; + int i = 0; - while (i<5) //2 - { - if(chkOn[i]==1) if(sliLev[i]>loudest) loudest=(float)sliLev[i]; - i++; - } - return (loudest * loudest); + while (i < 5) // 2 + { + if ((chkOn[i] == 1) && (sliLev[i] > loudest)) + { + loudest = static_cast(sliLev[i]); + } + i++; + } + return loudest * loudest; } - void DrumSynth::UpdateEnv(int e, long t) { // 0.2's added envData[e][NEXTT] = envpts[e][0][static_cast(envData[e][PNT] + 1.f)] * timestretch; // get next point - if (envData[e][NEXTT] < 0) { envData[e][NEXTT] = 442000 * timestretch; } // if end point, hold - envData[e][ENV] = envpts[e][1][static_cast(envData[e][PNT] + 0.f)] * 0.01f; // this level - float endEnv = envpts[e][1][static_cast(envData[e][PNT] + 1.f)] * 0.01f; // next level + if (envData[e][NEXTT] < 0) + { + envData[e][NEXTT] = 442000 * timestretch; // if end point, hold + } + envData[e][ENV] = envpts[e][1][static_cast(envData[e][PNT] + 0.f)] * 0.01f; // this level + float endEnv = envpts[e][1][static_cast(envData[e][PNT] + 1.f)] * 0.01f; // next level float dT = envData[e][NEXTT] - static_cast(t); - if (dT < 1.0) { dT = 1.0; } + if (dT < 1.0) + { + dT = 1.0; + } envData[e][dENV] = (endEnv - envData[e][ENV]) / dT; envData[e][PNT] = envData[e][PNT] + 1.0f; } - -void DrumSynth::GetEnv(int env, const char *sec, const char *key, QString ini) +void DrumSynth::GetEnv(int env, const char* sec, const char* key, QString ini) { - char en[256], s[8]; - int i=0, o=0, ep=0; - GetPrivateProfileString(sec, key, "0,0 100,0", en, sizeof(en), ini); + char en[256], s[8]; + int i = 0, o = 0, ep = 0; + GetPrivateProfileString(sec, key, "0,0 100,0", en, sizeof(en), ini); - //be safe! - en[255]=0; - s[0]=0; + // be safe! + en[255] = 0; + s[0] = 0; - while(en[i]!=0) - { - if(en[i] == ',') - { - if(sscanf(s, "%f", &envpts[env][0][ep])==0) envpts[env][0][ep] = 0.f; - o=0; - } - else if(en[i] == ' ') - { - if(sscanf(s, "%f", &envpts[env][1][ep])==0) envpts[env][1][ep] = 0.f; - o=0; ep++; - } - else { s[o]=en[i]; o++; s[o]=0; } - i++; - } - if(sscanf(s, "%f", &envpts[env][1][ep])==0) envpts[env][1][ep] = 0.f; - envpts[env][0][ep + 1] = -1; + while (en[i] != 0) + { + if (en[i] == ',') + { + if (sscanf(s, "%f", &envpts[env][0][ep]) == 0) + { + envpts[env][0][ep] = 0.f; + } + o = 0; + } + else if (en[i] == ' ') + { + if (sscanf(s, "%f", &envpts[env][1][ep]) == 0) + { + envpts[env][1][ep] = 0.f; + } + o = 0; + ep++; + } + else + { + s[o] = en[i]; + o++; + s[o] = 0; + } + i++; + } + if (sscanf(s, "%f", &envpts[env][1][ep]) == 0) + { + envpts[env][1][ep] = 0.f; + } + envpts[env][0][ep + 1] = -1; - envData[env][MAX] = envpts[env][0][ep]; + envData[env][MAX] = envpts[env][0][ep]; } - float DrumSynth::waveform(float ph, int form) { float w; @@ -159,9 +181,15 @@ float DrumSynth::waveform(float ph, int form) w = static_cast(fabs(2.0f * static_cast(sin(fmod(0.5f * ph, TwoPi))) - 1.f)); break; // sine^2 case 2: - while (ph < TwoPi) { ph += TwoPi; } + while (ph < TwoPi) + { + ph += TwoPi; + } w = 0.6366197f * static_cast(fmod(ph, TwoPi) - 1.f); // tri - if (w > 1.f) { w = 2.f - w; } + if (w > 1.f) + { + w = 2.f - w; + } break; case 3: w = ph - TwoPi * static_cast(static_cast(ph / TwoPi)); // saw @@ -175,8 +203,8 @@ float DrumSynth::waveform(float ph, int form) return w; } - -int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file) +int DrumSynth::GetPrivateProfileString( + const char* sec, const char* key, const char* def, char* buffer, int size, QString file) { stringstream is; bool inSection = false; @@ -184,572 +212,765 @@ int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const c char* line = static_cast(malloc(200)); - // Use QFile to handle unicode file name on Windows - // Previously we used ifstream directly - QFile f(file); - f.open(QIODevice::ReadOnly); - QByteArray dat = f.readAll().constData(); - is.str(string(dat.constData(), dat.size())); + // Use QFile to handle unicode file name on Windows + // Previously we used ifstream directly + QFile f(file); + f.open(QIODevice::ReadOnly); + QByteArray dat = f.readAll().constData(); + is.str(string(dat.constData(), dat.size())); - while (is.good()) { - if (!inSection) { - is.ignore( numeric_limits::max(), '['); + while (is.good()) + { + if (!inSection) + { + is.ignore(numeric_limits::max(), '['); - if (!is.eof()) { - is.getline(line, 200, ']'); - if (strcasecmp(line, sec)==0) { - inSection = true; - } - } - } - else if (!is.eof()) { - is.getline(line, 200); - if (line[0] == '[') - break; + if (!is.eof()) + { + is.getline(line, 200, ']'); + if (strcasecmp(line, sec) == 0) + { + inSection = true; + } + } + } + else if (!is.eof()) + { + is.getline(line, 200); + if (line[0] == '[') + { + break; + } - char* k = strtok(line, " \t="); - char* b = strtok(nullptr, "\n\r\0"); + char* k = strtok(line, " \t="); + char* b = strtok(nullptr, "\n\r\0"); - if (k != 0 && strcasecmp(k, key)==0) { - if (b==0) { - len = 0; - buffer[0] = 0; - } - else { - k = (char *)(b + strlen(b)-1); - while ( (k>=b) && (*k==' ' || *k=='\t') ) - --k; - *(k+1) = '\0'; + if (k != 0 && strcasecmp(k, key) == 0) + { + if (b == 0) + { + len = 0; + buffer[0] = 0; + } + else + { + k = static_cast(b + strlen(b) - 1); + while ((k >= b) && (*k == ' ' || *k == '\t')) + { + --k; + } + *(k + 1) = '\0'; - len = strlen(b); - if (len > size-1) len = size-1; - strncpy(buffer, b, len+1); - } - break; - } - } - } + len = strlen(b); + if (len > size - 1) + { + len = size - 1; + } + strncpy(buffer, b, len + 1); + } + break; + } + } + } - if (len == 0) { - len = strlen(def); - strncpy(buffer, def, size); - } + if (len == 0) + { + len = strlen(def); + strncpy(buffer, def, size); + } - free(line); + free(line); - return len; + return len; } -int DrumSynth::GetPrivateProfileInt(const char *sec, const char *key, int def, QString file) +int DrumSynth::GetPrivateProfileInt(const char* sec, const char* key, int def, QString file) { - char tmp[16]; - int i=0; + char tmp[16]; + int i = 0; - GetPrivateProfileString(sec, key, "", tmp, sizeof(tmp), file); - sscanf(tmp, "%d", &i); if(tmp[0]==0) i=def; + GetPrivateProfileString(sec, key, "", tmp, sizeof(tmp), file); + sscanf(tmp, "%d", &i); + if (tmp[0] == 0) + { + i = def; + } - return i; + return i; } -float DrumSynth::GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file) +float DrumSynth::GetPrivateProfileFloat(const char* sec, const char* key, float def, QString file) { - char tmp[16]; - float f=0.f; + char tmp[16]; + float f = 0.f; - GetPrivateProfileString(sec, key, "", tmp, sizeof(tmp), file); - sscanf(tmp, "%f", &f); if(tmp[0]==0) f=def; + GetPrivateProfileString(sec, key, "", tmp, sizeof(tmp), file); + sscanf(tmp, "%f", &f); + if (tmp[0] == 0) + { + f = def; + } - return f; + return f; } - // Constantly opening and scanning each file for the setting really sucks. // But, the original did this, and we know it works. Will store file into // an associative array or something once we have a datastructure to load in to. // llama -int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs) +int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sample_rate_t Fs) { - //input file - char sec[32]; - char ver[32]; - char comment[256]; - int commentLen=0; + // input file + char sec[32]; + char ver[32]; + char comment[256]; + int commentLen = 0; - //generation - long Length, tpos=0, tplus, totmp, t, i, j; - float x[3] = {0.f, 0.f, 0.f}; - float MasterTune; - constexpr float randmax = 1.f / static_cast(RAND_MAX); - constexpr float randmax2 = 2.f / static_cast(RAND_MAX); - int MainFilter, HighPass; + // generation + long Length, tpos = 0, tplus, totmp, t, i, j; + float x[3] = {0.f, 0.f, 0.f}; + float MasterTune; + constexpr float randmax = 1.f / static_cast(RAND_MAX); + constexpr float randmax2 = 2.f / static_cast(RAND_MAX); + int MainFilter, HighPass; - long NON, NT, TON, DiON, TDroop=0, DStep; - float a, b=0.f, c=0.f, d=0.f, g, TT=0.f, TL, NL, F1, F2; - float TphiStart=0.f, Tphi, TDroopRate, ddF, DAtten, DGain; + long NON, NT, TON, DiON, TDroop = 0, DStep; + float a, b = 0.f, c = 0.f, d = 0.f, g, TT = 0.f, TL, NL, F1, F2; + float TphiStart = 0.f, Tphi, TDroopRate, ddF, DAtten, DGain; - long BON, BON2, BFStep, BFStep2, botmp; - float BdF=0.f, BdF2=0.f, BPhi, BPhi2, BF, BF2, BQ, BQ2, BL, BL2; + long BON, BON2, BFStep, BFStep2, botmp; + float BdF = 0.f, BdF2 = 0.f, BPhi, BPhi2, BF, BF2, BQ, BQ2, BL, BL2; - long OON, OF1Sync=0, OF2Sync=0, OMode, OW1, OW2; - float Ophi1, Ophi2, OF1, OF2, OL, Ot=0 /*PG: init */, OBal1, OBal2, ODrive; - float Ocf1, Ocf2, OcF, OcQ, OcA, Oc[6][2]; //overtone cymbal mode - float Oc0=0.0f, Oc1=0.0f, Oc2=0.0f; + long OON, OF1Sync = 0, OF2Sync = 0, OMode, OW1, OW2; + float Ophi1, Ophi2, OF1, OF2, OL, Ot = 0 /*PG: init */, OBal1, OBal2, ODrive; + float Ocf1, Ocf2, OcF, OcQ, OcA, Oc[6][2]; // overtone cymbal mode + float Oc0 = 0.0f, Oc1 = 0.0f, Oc2 = 0.0f; - float MFfb, MFtmp, MFres, MFin=0.f, MFout=0.f; - float DownAve; - long DownStart, DownEnd, jj; + float MFfb, MFtmp, MFres, MFin = 0.f, MFout = 0.f; + float DownAve; + long DownStart, DownEnd, jj; + if (wavemode == 0) // semi-real-time adjustments if working in memory!! + { + mem_t = 1.0f; + mem_o = 1.0f; + mem_n = 1.0f; + mem_b = 1.0f; + mem_tune = 0.0f; + mem_time = 1.0f; + } - if(wavemode==0) //semi-real-time adjustments if working in memory!! - { - mem_t = 1.0f; - mem_o = 1.0f; - mem_n = 1.0f; - mem_b = 1.0f; - mem_tune = 0.0f; - mem_time = 1.0f; - } + // try to read version from input file + strcpy(sec, "General"); + GetPrivateProfileString(sec, "Version", "", ver, sizeof(ver), dsfile); + ver[9] = 0; + if ((strcasecmp(ver, "DrumSynth") != 0) // input fail + || (ver[11] != '1' && ver[11] != '2')) // version fail + { + return 0; + } - //try to read version from input file - strcpy(sec, "General"); - GetPrivateProfileString(sec,"Version","",ver,sizeof(ver),dsfile); - ver[9]=0; - if(strcasecmp(ver, "DrumSynth") != 0) {return 0;} //input fail - if(ver[11] != '1' && ver[11] != '2') {return 0;} //version fail + // read master parameters + GetPrivateProfileString(sec, "Comment", "", comment, sizeof(comment), dsfile); + while ((comment[commentLen] != 0) && (commentLen < 254)) + { + commentLen++; + } + if (commentLen == 0) + { + comment[0] = 32; + comment[1] = 0; + commentLen = 1; + } + comment[commentLen + 1] = 0; + commentLen++; + if ((commentLen % 2) == 1) + { + commentLen++; + } + timestretch = .01f * mem_time * GetPrivateProfileFloat(sec, "Stretch", 100.0, dsfile); + if (timestretch < 0.2f) + { + timestretch = 0.2f; + } + if (timestretch > 10.f) + { + timestretch = 10.f; + } + // the unit of envelope lengths is a sample in 44100Hz sample rate, so correct it + timestretch *= Fs / 44100.f; - //read master parameters - GetPrivateProfileString(sec,"Comment","",comment,sizeof(comment),dsfile); - while((comment[commentLen]!=0) && (commentLen<254)) commentLen++; - if(commentLen==0) { comment[0]=32; comment[1]=0; commentLen=1;} - comment[commentLen+1]=0; commentLen++; - if((commentLen % 2)==1) commentLen++; + DGain = 1.0f; // leave this here! + DGain = static_cast(std::pow(10.0, 0.05 * GetPrivateProfileFloat(sec, "Level", 0, dsfile))); - timestretch = .01f * mem_time * GetPrivateProfileFloat(sec,"Stretch",100.0,dsfile); - if(timestretch<0.2f) timestretch=0.2f; - if(timestretch>10.f) timestretch=10.f; - // the unit of envelope lengths is a sample in 44100Hz sample rate, so correct it - timestretch *= Fs / 44100.f; + MasterTune = GetPrivateProfileFloat(sec, "Tuning", 0.0, dsfile); + MasterTune = static_cast(std::pow(1.0594631f, MasterTune + mem_tune)); + MainFilter = 2 * GetPrivateProfileInt(sec, "Filter", 0, dsfile); + MFres = 0.0101f * GetPrivateProfileFloat(sec, "Resonance", 0.0, dsfile); + MFres = static_cast(std::pow(MFres, 0.5f)); - DGain = 1.0f; //leave this here! - DGain = static_cast(std::pow(10.0, 0.05 * GetPrivateProfileFloat(sec,"Level",0,dsfile))); + HighPass = GetPrivateProfileInt(sec, "HighPass", 0, dsfile); + GetEnv(7, sec, "FilterEnv", dsfile); - MasterTune = GetPrivateProfileFloat(sec,"Tuning",0.0,dsfile); - MasterTune = static_cast(std::pow(1.0594631f, MasterTune + mem_tune)); - MainFilter = 2 * GetPrivateProfileInt(sec,"Filter",0,dsfile); - MFres = 0.0101f * GetPrivateProfileFloat(sec,"Resonance",0.0,dsfile); - MFres = static_cast(std::pow(MFres, 0.5f)); + // read noise parameters + strcpy(sec, "Noise"); + chkOn[1] = GetPrivateProfileInt(sec, "On", 0, dsfile); + sliLev[1] = GetPrivateProfileInt(sec, "Level", 0, dsfile); + NT = GetPrivateProfileInt(sec, "Slope", 0, dsfile); + GetEnv(2, sec, "Envelope", dsfile); + NON = chkOn[1]; + NL = static_cast(sliLev[1] * sliLev[1]) * mem_n; + if (NT < 0) + { + a = 1.f + (NT / 105.f); + d = -NT / 105.f; + g = (1.f + 0.0005f * NT * NT) * NL; + } + else + { + a = 1.f; + b = -NT / 50.f; + c = static_cast(fabs(static_cast(NT))) / 100.f; + g = NL; + } - HighPass = GetPrivateProfileInt(sec,"HighPass",0,dsfile); - GetEnv(7, sec, "FilterEnv", dsfile); + // if(GetPrivateProfileInt(sec,"FixedSeq",0,dsfile)!=0) + // srand(1); //fixed random sequence + // read tone parameters + strcpy(sec, "Tone"); + chkOn[0] = GetPrivateProfileInt(sec, "On", 0, dsfile); + TON = chkOn[0]; + sliLev[0] = GetPrivateProfileInt(sec, "Level", 128, dsfile); + TL = static_cast(sliLev[0] * sliLev[0]) * mem_t; + GetEnv(1, sec, "Envelope", dsfile); + F1 = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; + if (fabs(F1) < 0.001f) + { + F1 = 0.001f; // to prevent overtone ratio div0 + } + F2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; + TDroopRate = GetPrivateProfileFloat(sec, "Droop", 0.f, dsfile); + if (TDroopRate > 0.f) + { + TDroopRate = static_cast(std::pow(10.0f, (TDroopRate - 20.0f) / 30.0f)); + TDroopRate = TDroopRate * -4.f / envData[1][MAX]; + TDroop = 1; + F2 = F1 + ((F2 - F1) / (1.f - static_cast(exp(TDroopRate * envData[1][MAX])))); + ddF = F1 - F2; + } + else + { + ddF = F2 - F1; + } - //read noise parameters - strcpy(sec, "Noise"); - chkOn[1] = GetPrivateProfileInt(sec,"On",0,dsfile); - sliLev[1] = GetPrivateProfileInt(sec,"Level",0,dsfile); - NT = GetPrivateProfileInt(sec,"Slope",0,dsfile); - GetEnv(2, sec, "Envelope", dsfile); - NON = chkOn[1]; - NL = (float)(sliLev[1] * sliLev[1]) * mem_n; - if(NT<0) - { a = 1.f + (NT / 105.f); d = -NT / 105.f; - g = (1.f + 0.0005f * NT * NT) * NL; } - else - { a = 1.f; b = -NT / 50.f; c = (float)fabs((float)NT) / 100.f; g = NL; } + Tphi = GetPrivateProfileFloat(sec, "Phase", 90.f, dsfile) / 57.29578f; // degrees>radians - //if(GetPrivateProfileInt(sec,"FixedSeq",0,dsfile)!=0) - //srand(1); //fixed random sequence + // read overtone parameters + strcpy(sec, "Overtones"); + chkOn[2] = GetPrivateProfileInt(sec, "On", 0, dsfile); + OON = chkOn[2]; + sliLev[2] = GetPrivateProfileInt(sec, "Level", 128, dsfile); + OL = static_cast(sliLev[2] * sliLev[2]) * mem_o; + GetEnv(3, sec, "Envelope1", dsfile); + GetEnv(4, sec, "Envelope2", dsfile); + OMode = GetPrivateProfileInt(sec, "Method", 2, dsfile); + OF1 = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; + OF2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; + OW1 = GetPrivateProfileInt(sec, "Wave1", 0, dsfile); + OW2 = GetPrivateProfileInt(sec, "Wave2", 0, dsfile); + OBal2 = static_cast(GetPrivateProfileInt(sec, "Param", 50, dsfile)); + ODrive = static_cast(std::pow(OBal2, 3.0f)) / std::pow(50.0f, 3.0f); + OBal2 *= 0.01f; + OBal1 = 1.f - OBal2; + Ophi1 = Tphi; + Ophi2 = Tphi; + if (MainFilter == 0) + { + MainFilter = GetPrivateProfileInt(sec, "Filter", 0, dsfile); + } + if ((GetPrivateProfileInt(sec, "Track1", 0, dsfile) == 1) && (TON == 1)) + { + OF1Sync = 1; + OF1 = OF1 / F1; + } + if ((GetPrivateProfileInt(sec, "Track2", 0, dsfile) == 1) && (TON == 1)) + { + OF2Sync = 1; + OF2 = OF2 / F1; + } - //read tone parameters - strcpy(sec, "Tone"); - chkOn[0] = GetPrivateProfileInt(sec,"On",0,dsfile); TON = chkOn[0]; - sliLev[0] = GetPrivateProfileInt(sec,"Level",128,dsfile); - TL = (float)(sliLev[0] * sliLev[0]) * mem_t; - GetEnv(1, sec, "Envelope", dsfile); - F1 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F1",200.0,dsfile) / Fs; - if(fabs(F1)<0.001f) F1=0.001f; //to prevent overtone ratio div0 - F2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F2",120.0,dsfile) / Fs; - TDroopRate = GetPrivateProfileFloat(sec,"Droop",0.f,dsfile); - if(TDroopRate>0.f) - { - TDroopRate = static_cast(std::pow(10.0f, (TDroopRate - 20.0f) / 30.0f)); - TDroopRate = TDroopRate * -4.f / envData[1][MAX]; - TDroop = 1; - F2 = F1+((F2-F1)/(1.f-(float)exp(TDroopRate * envData[1][MAX]))); - ddF = F1 - F2; - } - else ddF = F2-F1; + OcA = 0.28f + OBal1 * OBal1; // overtone cymbal mode + OcQ = OcA * OcA; + OcF = (1.8f - 0.7f * OcQ) * 0.92f; // multiply by env 2 + OcA *= 1.0f + 4.0f * OBal1; // level is a compromise! + Ocf1 = TwoPi / OF1; + Ocf2 = TwoPi / OF2; + for (i = 0; i < 6; i++) + { + Oc[i][0] = Oc[i][1] = Ocf1 + (Ocf2 - Ocf1) * 0.2f * static_cast(i); + } - Tphi = GetPrivateProfileFloat(sec,"Phase",90.f,dsfile) / 57.29578f; //degrees>radians + // read noise band parameters + strcpy(sec, "NoiseBand"); + chkOn[3] = GetPrivateProfileInt(sec, "On", 0, dsfile); + BON = chkOn[3]; + sliLev[3] = GetPrivateProfileInt(sec, "Level", 128, dsfile); + BL = static_cast(sliLev[3] * sliLev[3]) * mem_b; + BF = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; + BPhi = TwoPi / 8.f; + GetEnv(5, sec, "Envelope", dsfile); + BFStep = GetPrivateProfileInt(sec, "dF", 50, dsfile); + BQ = static_cast(BFStep); + BQ = BQ * BQ / (10000.f - 6600.f * (static_cast(sqrt(BF)) - 0.19f)); + BFStep = 1 + static_cast((40.f - (BFStep / 2.5f)) / (BQ + 1.f + (1.f * BF))); - //read overtone parameters - strcpy(sec, "Overtones"); - chkOn[2] = GetPrivateProfileInt(sec,"On",0,dsfile); OON = chkOn[2]; - sliLev[2] = GetPrivateProfileInt(sec,"Level",128,dsfile); - OL = (float)(sliLev[2] * sliLev[2]) * mem_o; - GetEnv(3, sec, "Envelope1", dsfile); - GetEnv(4, sec, "Envelope2", dsfile); - OMode = GetPrivateProfileInt(sec,"Method",2,dsfile); - OF1 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F1",200.0,dsfile) / Fs; - OF2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F2",120.0,dsfile) / Fs; - OW1 = GetPrivateProfileInt(sec,"Wave1",0,dsfile); - OW2 = GetPrivateProfileInt(sec,"Wave2",0,dsfile); - OBal2 = (float)GetPrivateProfileInt(sec,"Param",50,dsfile); - ODrive = static_cast(std::pow(OBal2, 3.0f)) / std::pow(50.0f, 3.0f); - OBal2 *= 0.01f; - OBal1 = 1.f - OBal2; - Ophi1 = Tphi; - Ophi2 = Tphi; - if(MainFilter==0) - MainFilter = GetPrivateProfileInt(sec,"Filter",0,dsfile); - if((GetPrivateProfileInt(sec,"Track1",0,dsfile)==1) && (TON==1)) - { OF1Sync = 1; OF1 = OF1 / F1; } - if((GetPrivateProfileInt(sec,"Track2",0,dsfile)==1) && (TON==1)) - { OF2Sync = 1; OF2 = OF2 / F1; } + strcpy(sec, "NoiseBand2"); + chkOn[4] = GetPrivateProfileInt(sec, "On", 0, dsfile); + BON2 = chkOn[4]; + sliLev[4] = GetPrivateProfileInt(sec, "Level", 128, dsfile); + BL2 = static_cast(sliLev[4] * sliLev[4]) * mem_b; + BF2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; + BPhi2 = TwoPi / 8.f; + GetEnv(6, sec, "Envelope", dsfile); + BFStep2 = GetPrivateProfileInt(sec, "dF", 50, dsfile); + BQ2 = static_cast(BFStep2); + BQ2 = BQ2 * BQ2 / (10000.f - 6600.f * (static_cast(sqrt(BF2)) - 0.19f)); + BFStep2 = 1 + static_cast((40 - (BFStep2 / 2.5)) / (BQ2 + 1 + (1 * BF2))); - OcA = 0.28f + OBal1 * OBal1; //overtone cymbal mode - OcQ = OcA * OcA; - OcF = (1.8f - 0.7f * OcQ) * 0.92f; //multiply by env 2 - OcA *= 1.0f + 4.0f * OBal1; //level is a compromise! - Ocf1 = TwoPi / OF1; - Ocf2 = TwoPi / OF2; - for(i=0; i<6; i++) Oc[i][0] = Oc[i][1] = Ocf1 + (Ocf2 - Ocf1) * 0.2f * (float)i; + // read distortion parameters + strcpy(sec, "Distortion"); + chkOn[5] = GetPrivateProfileInt(sec, "On", 0, dsfile); + DiON = chkOn[5]; + DStep = 1 + GetPrivateProfileInt(sec, "Rate", 0, dsfile); + if (DStep == 7) { DStep = 20; } + if (DStep == 6) { DStep = 10; } + if (DStep == 5) { DStep = 8; } - //read noise band parameters - strcpy(sec, "NoiseBand"); - chkOn[3] = GetPrivateProfileInt(sec,"On",0,dsfile); BON = chkOn[3]; - sliLev[3] = GetPrivateProfileInt(sec,"Level",128,dsfile); - BL = (float)(sliLev[3] * sliLev[3]) * mem_b; - BF = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F",1000.0,dsfile) / Fs; - BPhi = TwoPi / 8.f; - GetEnv(5, sec, "Envelope", dsfile); - BFStep = GetPrivateProfileInt(sec,"dF",50,dsfile); - BQ = (float)BFStep; - BQ = BQ * BQ / (10000.f-6600.f*((float)sqrt(BF)-0.19f)); - BFStep = 1 + (int)((40.f - (BFStep / 2.5f)) / (BQ + 1.f + (1.f * BF))); + clippoint = 32700; + DAtten = 1.0f; - strcpy(sec, "NoiseBand2"); - chkOn[4] = GetPrivateProfileInt(sec,"On",0,dsfile); BON2 = chkOn[4]; - sliLev[4] = GetPrivateProfileInt(sec,"Level",128,dsfile); - BL2 = (float)(sliLev[4] * sliLev[4]) * mem_b; - BF2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F",1000.0,dsfile) / Fs; - BPhi2 = TwoPi / 8.f; - GetEnv(6, sec, "Envelope", dsfile); - BFStep2 = GetPrivateProfileInt(sec,"dF",50,dsfile); - BQ2 = (float)BFStep2; - BQ2 = BQ2 * BQ2 / (10000.f-6600.f*((float)sqrt(BF2)-0.19f)); - BFStep2 = 1 + (int)((40 - (BFStep2 / 2.5)) / (BQ2 + 1 + (1 * BF2))); + if (DiON == 1) + { + DAtten = DGain * static_cast(LoudestEnv()); + clippoint = DAtten > 32700 ? 32700 : static_cast(DAtten); + DAtten = static_cast(std::pow(2.0, 2.0 * GetPrivateProfileInt(sec, "Bits", 0, dsfile))); + DGain = DAtten * DGain + * static_cast(std::pow(10.0, 0.05 * GetPrivateProfileInt(sec, "Clipping", 0, dsfile))); + } - //read distortion parameters - strcpy(sec, "Distortion"); - chkOn[5] = GetPrivateProfileInt(sec,"On",0,dsfile); DiON = chkOn[5]; - DStep = 1 + GetPrivateProfileInt(sec,"Rate",0,dsfile); - if(DStep==7) DStep=20; - if(DStep==6) DStep=10; - if(DStep==5) DStep=8; + // prepare envelopes + for (i = 1; i < 8; i++) + { + envData[i][NEXTT] = 0; + envData[i][PNT] = 0; + } + Length = LongestEnv(); - clippoint = 32700; - DAtten = 1.0f; + // allocate the buffer + // if(wave!=NULL) free(wave); + // wave = new int16_t[channels * (Length + 1280)]; //wave memory buffer + wave = new int16_t[channels * Length]; // wave memory buffer + if (wave == nullptr) + { + return 0; + } + wavewords = 0; - if(DiON==1) - { - DAtten = DGain * (short)LoudestEnv(); - if(DAtten>32700) clippoint=32700; else clippoint=(short)DAtten; - DAtten = static_cast(std::pow(2.0, 2.0 * GetPrivateProfileInt(sec,"Bits",0,dsfile))); - DGain = DAtten * DGain * static_cast(std::pow(10.0, 0.05 * GetPrivateProfileInt(sec,"Clipping",0,dsfile))); - } + /* + if(wavemode==0) + { + //open output file + fp = fopen(wavfile, "wb"); + if(!fp) {return 3;} //output fail - //prepare envelopes - for (i=1;i<8;i++) { envData[i][NEXTT]=0; envData[i][PNT]=0; } - Length = LongestEnv(); + //set up INFO chunk + WI.list = 0x5453494C; + WI.listLength = 36 + commentLen; + WI.info = 0x4F464E49; + WI.isft = 0x54465349; + WI.isftLength = 16; + strcpy(WI.software, "DrumSynth v2.0 "); WI.software[15]=0; + WI.icmt = 0x544D4349; + WI.icmtLength = commentLen; - //allocate the buffer - //if(wave!=NULL) free(wave); - //wave = new int16_t[channels * (Length + 1280)]; //wave memory buffer - wave = new int16_t[channels * Length]; //wave memory buffer - if(wave==nullptr) {return 0;} - wavewords = 0; + //write WAV header + WH.riff = 0x46464952; + WH.riffLength = 36 + (2 * Length) + 44 + commentLen; + WH.wave = 0x45564157; + WH.fmt = 0x20746D66; + WH.waveLength = 16; + WH.wFormatTag = WAVE_FORMAT_PCM; + WH.nChannels = 1; + WH.nSamplesPerSec = Fs; + WH.nAvgBytesPerSec = 2 * Fs; + WH.nBlockAlign = 2; + WH.wBitsPerSample = 16; + WH.data = 0x61746164; + WH.dataLength = 2 * Length; + fwrite(&WH, 1, 44, fp); + } + */ - /* - if(wavemode==0) - { - //open output file - fp = fopen(wavfile, "wb"); - if(!fp) {return 3;} //output fail + // generate + tpos = 0; + while (tpos < Length) + { + tplus = tpos + 1199; - //set up INFO chunk - WI.list = 0x5453494C; - WI.listLength = 36 + commentLen; - WI.info = 0x4F464E49; - WI.isft = 0x54465349; - WI.isftLength = 16; - strcpy(WI.software, "DrumSynth v2.0 "); WI.software[15]=0; - WI.icmt = 0x544D4349; - WI.icmtLength = commentLen; + if (NON == 1) // noise + { + for (t = tpos; t <= tplus; t++) + { + if (t < envData[2][NEXTT]) + { + envData[2][ENV] = envData[2][ENV] + envData[2][dENV]; + } + else + { + UpdateEnv(2, t); + } + x[2] = x[1]; + x[1] = x[0]; + x[0] = (randmax2 * static_cast(rand())) - 1.f; + TT = a * x[0] + b * x[1] + c * x[2] + d * TT; + DF[t - tpos] = TT * g * envData[2][ENV]; + } + if (t >= envData[2][MAX]) + { + NON = 0; + } + } + else + { + for (j = 0; j < 1200; j++) + { + DF[j] = 0.f; + } + } - //write WAV header - WH.riff = 0x46464952; - WH.riffLength = 36 + (2 * Length) + 44 + commentLen; - WH.wave = 0x45564157; - WH.fmt = 0x20746D66; - WH.waveLength = 16; - WH.wFormatTag = WAVE_FORMAT_PCM; - WH.nChannels = 1; - WH.nSamplesPerSec = Fs; - WH.nAvgBytesPerSec = 2 * Fs; - WH.nBlockAlign = 2; - WH.wBitsPerSample = 16; - WH.data = 0x61746164; - WH.dataLength = 2 * Length; - fwrite(&WH, 1, 44, fp); - } - */ + if (TON == 1) // tone + { + TphiStart = Tphi; + if (TDroop == 1) + { + for (t = tpos; t <= tplus; t++) + { + phi[t - tpos] = F2 + (ddF * static_cast(exp(t * TDroopRate))); + } + } + else + { + for (t = tpos; t <= tplus; t++) + { + phi[t - tpos] = F1 + (t / envData[1][MAX]) * ddF; + } + } + for (t = tpos; t <= tplus; t++) + { + totmp = t - tpos; + if (t < envData[1][NEXTT]) + { + envData[1][ENV] = envData[1][ENV] + envData[1][dENV]; + } + else + { + UpdateEnv(1, t); + } + Tphi = Tphi + phi[totmp]; + DF[totmp] += TL * envData[1][ENV] * static_cast(sin(fmod(Tphi, TwoPi))); // overflow? + } + if (t >= envData[1][MAX]) + { + TON = 0; + } + } + else + { + for (j = 0; j < 1200; j++) + { + phi[j] = F2; // for overtone sync + } + } - //generate - tpos = 0; - while(tpos(rand()) - 0.5f; + } + BPhi = BPhi + BF + BQ * BdF; + botmp = t - tpos; + DF[botmp] = DF[botmp] + static_cast(cos(fmod(BPhi, TwoPi))) * envData[5][ENV] * BL; + } + if (t >= envData[5][MAX]) + { + BON = 0; + } + } - if(NON==1) //noise - { - for(t=tpos; t<=tplus; t++) - { - if(t < envData[2][NEXTT]) envData[2][ENV] = envData[2][ENV] + envData[2][dENV]; - else UpdateEnv(2, t); - x[2] = x[1]; - x[1] = x[0]; - x[0] = (randmax2 * (float)rand()) - 1.f; - TT = a * x[0] + b * x[1] + c * x[2] + d * TT; - DF[t - tpos] = TT * g * envData[2][ENV]; - } - if(t>=envData[2][MAX]) NON=0; - } - else { - for(j=0; j<1200; j++) DF[j]=0.f; - } + if (BON2 == 1) // noise band 2 + { + for (t = tpos; t <= tplus; t++) + { + if (t < envData[6][NEXTT]) + { + envData[6][ENV] = envData[6][ENV] + envData[6][dENV]; + } + else + { + UpdateEnv(6, t); + } + if ((t % BFStep2) == 0) + { + BdF2 = randmax * static_cast(rand()) - 0.5f; + } + BPhi2 = BPhi2 + BF2 + BQ2 * BdF2; + botmp = t - tpos; + DF[botmp] = DF[botmp] + static_cast(cos(fmod(BPhi2, TwoPi))) * envData[6][ENV] * BL2; + } + if (t >= envData[6][MAX]) + { + BON2 = 0; + } + } - if(TON==1) //tone - { - TphiStart = Tphi; - if(TDroop==1) - { - for(t=tpos; t<=tplus; t++) - phi[t - tpos] = F2 + (ddF * (float)exp(t * TDroopRate)); - } - else - { - for(t=tpos; t<=tplus; t++) - phi[t - tpos] = F1 + (t / envData[1][MAX]) * ddF; - } - for(t=tpos; t<=tplus; t++) - { - totmp = t - tpos; - if(t < envData[1][NEXTT]) - envData[1][ENV] = envData[1][ENV] + envData[1][dENV]; - else UpdateEnv(1, t); - Tphi = Tphi + phi[totmp]; - DF[totmp] += TL * envData[1][ENV] * (float)sin(fmod(Tphi,TwoPi));//overflow? - } - if(t>=envData[1][MAX]) TON=0; - } - else for(j=0; j<1200; j++) phi[j]=F2; //for overtone sync + for (t = tpos; t <= tplus; t++) + { + if (OON == 1) // overtones + { + if (t < envData[3][NEXTT]) + { + envData[3][ENV] = envData[3][ENV] + envData[3][dENV]; + } + else + { + if (t >= envData[3][MAX]) // wait for OT2 + { + envData[3][ENV] = 0; + envData[3][dENV] = 0; + envData[3][NEXTT] = 999999; + } + else + { + UpdateEnv(3, t); + } + } + // + if (t < envData[4][NEXTT]) + { + envData[4][ENV] = envData[4][ENV] + envData[4][dENV]; + } + else + { + if (t >= envData[4][MAX]) // wait for OT1 + { + envData[4][ENV] = 0; + envData[4][dENV] = 0; + envData[4][NEXTT] = 999999; + } + else + { + UpdateEnv(4, t); + } + } + // + TphiStart = TphiStart + phi[t - tpos]; + if (OF1Sync == 1) + { + Ophi1 = TphiStart * OF1; + } + else + { + Ophi1 = Ophi1 + OF1; + } + if (OF2Sync == 1) + { + Ophi2 = TphiStart * OF2; + } + else + { + Ophi2 = Ophi2 + OF2; + } + Ot = 0.0f; + switch (OMode) + { + case 0: // add + Ot = OBal1 * envData[3][ENV] * waveform(Ophi1, OW1); + Ot = OL * (Ot + OBal2 * envData[4][ENV] * waveform(Ophi2, OW2)); + break; - if(BON==1) //noise band 1 - { - for(t=tpos; t<=tplus; t++) - { - if(t < envData[5][NEXTT]) - envData[5][ENV] = envData[5][ENV] + envData[5][dENV]; - else UpdateEnv(5, t); - if((t % BFStep) == 0) BdF = randmax * (float)rand() - 0.5f; - BPhi = BPhi + BF + BQ * BdF; - botmp = t - tpos; - DF[botmp] = DF[botmp] + (float)cos(fmod(BPhi,TwoPi)) * envData[5][ENV] * BL; - } - if(t>=envData[5][MAX]) BON=0; - } + case 1: // FM + Ot = ODrive * envData[4][ENV] * waveform(Ophi2, OW2); + Ot = OL * envData[3][ENV] * waveform(Ophi1 + Ot, OW1); + break; - if(BON2==1) //noise band 2 - { - for(t=tpos; t<=tplus; t++) - { - if(t < envData[6][NEXTT]) - envData[6][ENV] = envData[6][ENV] + envData[6][dENV]; - else UpdateEnv(6, t); - if((t % BFStep2) == 0) BdF2 = randmax * (float)rand() - 0.5f; - BPhi2 = BPhi2 + BF2 + BQ2 * BdF2; - botmp = t - tpos; - DF[botmp] = DF[botmp] + (float)cos(fmod(BPhi2,TwoPi)) * envData[6][ENV] * BL2; - } - if(t>=envData[6][MAX]) BON2=0; - } + case 2: // RM + Ot = (1 - ODrive / 8) + (((ODrive / 8) * envData[4][ENV]) * waveform(Ophi2, OW2)); + Ot = OL * envData[3][ENV] * waveform(Ophi1, OW1) * Ot; + break; + case 3: // 808 Cymbal + for (j = 0; j < 6; j++) + { + Oc[j][0] += 1.0f; - for (t=tpos; t<=tplus; t++) - { - if(OON==1) //overtones - { - if(t=envData[3][MAX]) //wait for OT2 - { - envData[3][ENV] = 0; - envData[3][dENV] = 0; - envData[3][NEXTT] = 999999; - } - else UpdateEnv(3, t); - } - // - if(t=envData[4][MAX]) //wait for OT1 - { - envData[4][ENV] = 0; - envData[4][dENV] = 0; - envData[4][NEXTT] = 999999; - } - else UpdateEnv(4, t); - } - // - TphiStart = TphiStart + phi[t - tpos]; - if(OF1Sync==1) Ophi1 = TphiStart * OF1; else Ophi1 = Ophi1 + OF1; - if(OF2Sync==1) Ophi2 = TphiStart * OF2; else Ophi2 = Ophi2 + OF2; - Ot=0.0f; - switch (OMode) - { - case 0: //add - Ot = OBal1 * envData[3][ENV] * waveform(Ophi1, OW1); - Ot = OL * (Ot + OBal2 * envData[4][ENV] * waveform(Ophi2, OW2)); - break; + if (Oc[j][0] > Oc[j][1]) + { + Oc[j][0] -= Oc[j][1]; + Ot = OL * envData[3][ENV]; + } + } + Ocf1 = envData[4][ENV] * OcF; // filter freq + Oc0 += Ocf1 * Oc1; + Oc1 += Ocf1 * (Ot + Oc2 - OcQ * Oc1 - Oc0); // bpf + Oc2 = Ot; + Ot = Oc1; + break; + } + } - case 1: //FM - Ot = ODrive * envData[4][ENV] * waveform(Ophi2, OW2); - Ot = OL * envData[3][ENV] * waveform(Ophi1 + Ot, OW1); - break; + if (MainFilter == 1) // filter overtones + { + if (t < envData[7][NEXTT]) + { + envData[7][ENV] = envData[7][ENV] + envData[7][dENV]; + } + else + { + UpdateEnv(7, t); + } - case 2: //RM - Ot = (1 - ODrive / 8) + (((ODrive / 8) * envData[4][ENV]) * waveform(Ophi2, OW2)); - Ot = OL * envData[3][ENV] * waveform(Ophi1, OW1) * Ot; - break; + MFtmp = envData[7][ENV]; + if (MFtmp > 0.2f) + { + MFfb = 1.001f - static_cast(std::pow(10.0f, MFtmp - 1)); + } + else + { + MFfb = 0.999f - 0.7824f * MFtmp; + } - case 3: //808 Cymbal - for(j=0; j<6; j++) - { - Oc[j][0] += 1.0f; + MFtmp = Ot + MFres * (1.f + (1.f / MFfb)) * (MFin - MFout); + MFin = MFfb * (MFin - MFtmp) + MFtmp; + MFout = MFfb * (MFout - MFin) + MFin; - if(Oc[j][0]>Oc[j][1]) - { - Oc[j][0] -= Oc[j][1]; - Ot = OL * envData[3][ENV]; - } - } - Ocf1 = envData[4][ENV] * OcF; //filter freq - Oc0 += Ocf1 * Oc1; - Oc1 += Ocf1 * (Ot + Oc2 - OcQ * Oc1 - Oc0); //bpf - Oc2 = Ot; - Ot = Oc1; - break; - } - } + DF[t - tpos] = DF[t - tpos] + (MFout - (HighPass * Ot)); + } + else if (MainFilter == 2) // filter all + { + if (t < envData[7][NEXTT]) + { + envData[7][ENV] = envData[7][ENV] + envData[7][dENV]; + } + else + { + UpdateEnv(7, t); + } - if(MainFilter==1) //filter overtones - { - if(t 0.2f) + { + MFfb = 1.001f - static_cast(std::pow(10.0f, MFtmp - 1)); + } + else + { + MFfb = 0.999f - 0.7824f * MFtmp; + } - MFtmp = envData[7][ENV]; - if(MFtmp >0.2f) - MFfb = 1.001f - static_cast(std::pow(10.0f, MFtmp - 1)); - else - MFfb = 0.999f - 0.7824f * MFtmp; + MFtmp = DF[t - tpos] + Ot + MFres * (1.f + (1.f / MFfb)) * (MFin - MFout); + MFin = MFfb * (MFin - MFtmp) + MFtmp; + MFout = MFfb * (MFout - MFin) + MFin; - MFtmp = Ot + MFres * (1.f + (1.f/MFfb)) * (MFin - MFout); - MFin = MFfb * (MFin - MFtmp) + MFtmp; - MFout = MFfb * (MFout - MFin) + MFin; + DF[t - tpos] = MFout - (HighPass * (DF[t - tpos] + Ot)); + } + // PG: Ot is uninitialized + else + { + DF[t - tpos] = DF[t - tpos] + Ot; // no filter + } + } - DF[t - tpos] = DF[t - tpos] + (MFout - (HighPass * Ot)); - } - else if(MainFilter==2) //filter all - { - if(t(DF[j] / DAtten); + } - MFtmp = envData[7][ENV]; - if(MFtmp >0.2f) - MFfb = 1.001f - static_cast(std::pow(10.0f, MFtmp - 1)); - else - MFfb = 0.999f - 0.7824f * MFtmp; + for (j = 0; j < 1200; j += DStep) // downsampling + { + DownAve = 0; + DownStart = j; + DownEnd = j + DStep - 1; + for (jj = DownStart; jj <= DownEnd; jj++) + { + DownAve = DownAve + DF[jj]; + } + DownAve = DownAve / DStep; + for (jj = DownStart; jj <= DownEnd; jj++) + { + DF[jj] = DownAve; + } + } + } + else + { + for (j = 0; j < 1200; j++) + { + DF[j] *= DGain; + } + } - MFtmp = DF[t - tpos] + Ot + MFres * (1.f + (1.f/MFfb)) * (MFin - MFout); - MFin = MFfb * (MFin - MFtmp) + MFtmp; - MFout = MFfb * (MFout - MFin) + MFin; + for (j = 0; j < 1200; j++) // clipping + output + { + if (DF[j] > clippoint) + { + wave[wavewords++] = clippoint; + } + else if (DF[j] < -clippoint) + { + wave[wavewords++] = -clippoint; + } + else + { + wave[wavewords++] = static_cast(DF[j]); + } - DF[t - tpos] = MFout - (HighPass * (DF[t - tpos] + Ot)); - } - // PG: Ot is uninitialized - else DF[t - tpos] = DF[t - tpos] + Ot; //no filter - } + for (int c = 1; c < channels; c++) + { + wave[wavewords] = wave[wavewords - 1]; + wavewords++; + } + } - if(DiON==1) //bit resolution - { - for(j=0; j<1200; j++) - DF[j] = DGain * (int)(DF[j] / DAtten); + tpos = tpos + 1200; + } - for(j=0; j<1200; j+=DStep) //downsampling - { - DownAve = 0; - DownStart = j; - DownEnd = j + DStep - 1; - for(jj = DownStart; jj<=DownEnd; jj++) - DownAve = DownAve + DF[jj]; - DownAve = DownAve / DStep; - for(jj = DownStart; jj<=DownEnd; jj++) - DF[jj] = DownAve; - } - } - else for(j=0; j<1200; j++) DF[j] *= DGain; + /* + if(wavemode==0) + { + fwrite(wave, 2, Length, fp); //write data + fwrite(&WI, 1, 44, fp); //write INFO chunk + fwrite(&comment, 1, commentLen, fp); + fclose(fp); + } + wavemode = 0; //force compatibility!! + */ - for(j = 0; j<1200; j++) //clipping + output - { - if(DF[j] > clippoint) - wave[wavewords++] = clippoint; - else if(DF[j] < -clippoint) - wave[wavewords++] = -clippoint; - else - wave[wavewords++] = (short)DF[j]; - - for (int c = 1; c < channels; c++) { - wave[wavewords] = wave[wavewords-1]; - wavewords++; - } - } - - tpos = tpos + 1200; - } - - /* - if(wavemode==0) - { - fwrite(wave, 2, Length, fp); //write data - fwrite(&WI, 1, 44, fp); //write INFO chunk - fwrite(&comment, 1, commentLen, fp); - fclose(fp); - } - wavemode = 0; //force compatibility!! - */ - - - return Length; + return Length; } - } // namespace lmms