bool CPattern::operator== (const CPattern &other) const //----------------------------------------------------- { if(GetNumRows() != other.GetNumRows() || GetNumChannels() != other.GetNumChannels() || GetOverrideSignature() != other.GetOverrideSignature() || GetRowsPerBeat() != other.GetRowsPerBeat() || GetRowsPerMeasure() != other.GetRowsPerMeasure()) return false; if(m_ModCommands == nullptr || other.m_ModCommands == nullptr) return m_ModCommands == other.m_ModCommands; auto i = GetNumRows() * GetNumChannels(); auto m1 = m_ModCommands, m2 = other.m_ModCommands; while(i--) { if(*m1 != *m2) { return false; } m1++; m2++; } return true; }
double CSample::UpdateConstraint(CConstraints* pCC, CModel* pModel, bool bActiveOnly, int iMinNewConstraint, int& iNumVio, double fEpsilon) { int iNewConstraint = 0; double fsumvio = 0.0; int iTotalPattern = m_vPatterns.size(); iNumVio = 0; double vio = 0.0; int lastupdate = m_iLastUpdated; for (int i = lastupdate + 1; i < iTotalPattern + lastupdate + 1 && iNewConstraint < iMinNewConstraint - 1; i ++) { int ii = i; while (ii >= iTotalPattern) ii -= iTotalPattern; if (bActiveOnly && m_vActive[ii] == 0) continue; CPattern* pPattern = m_vPatterns[ii]; pPattern->AlignDecoy(pModel); int iParamDim = pModel->m_iParamDim; double* pw1 = new double[iParamDim]; double* pw2 = new double[iParamDim]; double labelloss = pPattern->GetLabelLoss(pModel); pPattern->GetLabelPhi(pw1, iParamDim, pModel); // fprintf(stderr, " label loss %.3f ", labelloss); int iDecoyClass = pPattern->GetDecoyPhi(pw2, iParamDim, pModel); double fsum = 0, fs2 = 0; for (int k = 0; k < iParamDim; k ++) { fsum += pw1[k] * pModel->m_vWeight[k]; fs2 += pw2[k] * pModel->m_vWeight[k]; } vio = fsum - fs2 - labelloss; fprintf(stderr, "\n %d (class %d) %.3f, (%d %.3f %.3f) ", ii, pPattern->m_original->m_iClassID, fsum, iDecoyClass, fs2, -vio); if (vio > - fEpsilon) //if (labelloss < 0.00001) { m_vActive[ii] = 0; } else { for (int k = 0; k < iParamDim; k ++) { pw1[k] = pw1[k] - pw2[k]; } pCC->Add(pw1, ii, labelloss); iNewConstraint ++; iNumVio ++; fsumvio += vio; fprintf(stderr, " ++ "); } m_iLastUpdated = ii; } return -fsumvio; }
int CSample::AlignHomolog(CModel* pModel) { fprintf(stderr, "\n"); for (int i = 0; i < (int) m_vPatterns.size(); i ++) { CPattern* pPattern = m_vPatterns[i]; fprintf(stderr, "\rPattern %d ", i); pPattern->AlignHomolog(pModel); } return (int)m_vPatterns.size(); }
static void CopyPatternName(CPattern &pattern, FileReader &file) //-------------------------------------------------------------- { char name[MAX_PATTERNNAME] = ""; file.ReadString<mpt::String::maybeNullTerminated>(name, MAX_PATTERNNAME); pattern.SetName(name); }
int CSample::Classify(CModel* pModel, const char* outputfile) { fprintf(stderr, "classifying samples ... "); FILE* fp = fopen(outputfile, "w"); if (!fp) { fprintf(stderr, "cant' write result to %s. terminated. \n", outputfile); return -1; } double fSumAcc = 0.0; for (int i = 0; i < (int) m_vPatterns.size(); i ++) { CPattern* pPattern = m_vPatterns[i]; fprintf(stderr, "\n%d: ", i + 1); fSumAcc += pPattern->Classify(pModel); } fprintf(stderr, "sample # %d, avg accuracy %f \n", (int)m_vPatterns.size(), fSumAcc/(double) m_vPatterns.size()); fclose(fp); return (int) m_vPatterns.size(); }
void GenerateCommands(CPattern& pat, const double dProbPcs, const double dProbPc) //------------------------------------------------------------------------------- { const double dPcxProb = dProbPcs + dProbPc; const CPattern::const_iterator end = pat.End(); for(CPattern::iterator i = pat.Begin(); i != end; i++) { const double rand = Rand01(); if(rand < dPcxProb) { if(rand < dProbPcs) i->note = NotePcSmooth; else i->note = NotePc; i->instr = Rand<uint8_t>(0, MAX_MIXPLUGINS); i->SetValueVolCol(Rand<uint16_t>(0, modplug::tracker::modevent_t::MaxColumnValue)); i->SetValueEffectCol(Rand<uint16_t>(0, modplug::tracker::modevent_t::MaxColumnValue)); } else i->Clear(); } }
// Read AMS or AMS2 (newVersion = true) pattern. At least this part of the format is more or less identical between the two trackers... static void ReadAMSPattern(CPattern &pattern, bool newVersion, FileReader &patternChunk, CSoundFile &sndFile) //----------------------------------------------------------------------------------------------------------- { enum { emptyRow = 0xFF, // No commands on row endOfRowMask = 0x80, // If set, no more commands on this row noteMask = 0x40, // If set, no note+instr in this command channelMask = 0x1F, // Mask for extracting channel // Note flags readNextCmd = 0x80, // One more command follows noteDataMask = 0x7F, // Extract note // Command flags volCommand = 0x40, // Effect is compressed volume command commandMask = 0x3F, // Command or volume mask }; // Effect translation table for extended (non-Protracker) effects static const ModCommand::COMMAND effTrans[] = { CMD_S3MCMDEX, // Forward / Backward CMD_PORTAMENTOUP, // Extra fine slide up CMD_PORTAMENTODOWN, // Extra fine slide up CMD_RETRIG, // Retrigger CMD_NONE, CMD_TONEPORTAVOL, // Toneporta with fine volume slide CMD_VIBRATOVOL, // Vibrato with fine volume slide CMD_NONE, CMD_PANNINGSLIDE, CMD_NONE, CMD_VOLUMESLIDE, // Two times finder volume slide than Axx CMD_NONE, CMD_CHANNELVOLUME, // Channel volume (0...127) CMD_PATTERNBREAK, // Long pattern break (in hex) CMD_S3MCMDEX, // Fine slide commands CMD_NONE, // Fractional BPM CMD_KEYOFF, // Key off at tick xx CMD_PORTAMENTOUP, // Porta up, but uses all octaves (?) CMD_PORTAMENTODOWN, // Porta down, but uses all octaves (?) CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_GLOBALVOLSLIDE, // Global volume slide CMD_NONE, CMD_GLOBALVOLUME, // Global volume (0... 127) }; static ModCommand dummy; for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) { PatternRow baseRow = pattern.GetRow(row); while(patternChunk.AreBytesLeft()) { const uint8 flags = patternChunk.ReadUint8(); if(flags == emptyRow) { break; } const CHANNELINDEX chn = (flags & channelMask); ModCommand &m = chn < pattern.GetNumChannels() ? baseRow[chn] : dummy; bool moreCommands = true; if(!(flags & noteMask)) { // Read note + instr uint8 note = patternChunk.ReadUint8(); moreCommands = (note & readNextCmd) != 0; note &= noteDataMask; if(note == 1) { m.note = NOTE_KEYOFF; } else if(note >= 2 && note <= 121 && newVersion) { m.note = note - 2 + NOTE_MIN; } else if(note >= 12 && note <= 108 && !newVersion) { m.note = note + 12 + NOTE_MIN; } m.instr = patternChunk.ReadUint8(); } while(moreCommands) { // Read one more effect command ModCommand origCmd = m; const uint8 command = patternChunk.ReadUint8(), effect = (command & commandMask); moreCommands = (command & readNextCmd) != 0; if(command & volCommand) { m.volcmd = VOLCMD_VOLUME; m.vol = effect; } else { m.param = patternChunk.ReadUint8(); if(effect < 0x10) { // PT commands m.command = effect; sndFile.ConvertModCommand(m); // Post-fix some commands switch(m.command) { case CMD_PANNING8: // 4-Bit panning m.command = CMD_PANNING8; m.param = (m.param & 0x0F) * 0x11; break; case CMD_VOLUME: m.command = CMD_NONE; m.volcmd = VOLCMD_VOLUME; m.vol = static_cast<ModCommand::VOL>(std::min((m.param + 1) / 2, 64)); break; case CMD_MODCMDEX: if(m.param == 0x80) { // Break sample loop (cut after loop) m.command = CMD_NONE; } else { m.ExtendedMODtoS3MEffect(); } break; } } else if(effect - 0x10 < (int)CountOf(effTrans)) { // Extended commands m.command = effTrans[effect - 0x10]; // Post-fix some commands switch(effect) { case 0x10: // Play sample forwards / backwards if(m.param <= 0x01) { m.param |= 0x9E; } else { m.command = CMD_NONE; } break; case 0x11: case 0x12: // Extra fine slides m.param = static_cast<ModCommand::PARAM>(std::min(uint8(0x0F), m.param) | 0xE0); break; case 0x15: case 0x16: // Fine slides m.param = static_cast<ModCommand::PARAM>((std::min(0x10, m.param + 1) / 2) | 0xF0); break; case 0x1E: // More fine slides switch(m.param >> 4) { case 0x1: // Fine porta up m.command = CMD_PORTAMENTOUP; m.param |= 0xF0; break; case 0x2: // Fine porta down m.command = CMD_PORTAMENTODOWN; m.param |= 0xF0; break; case 0xA: // Extra fine volume slide up m.command = CMD_VOLUMESLIDE; m.param = ((((m.param & 0x0F) + 1) / 2) << 4) | 0x0F; break; case 0xB: // Extra fine volume slide down m.command = CMD_VOLUMESLIDE; m.param = (((m.param & 0x0F) + 1) / 2) | 0xF0; break; default: m.command = CMD_NONE; break; } break; case 0x1C: // Adjust channel volume range m.param = static_cast<ModCommand::PARAM>(std::min((m.param + 1) / 2, 64)); break; } } // Try merging commands first ModCommand::CombineEffects(m.command, m.param, origCmd.command, origCmd.param); if(ModCommand::GetEffectWeight(origCmd.command) > ModCommand::GetEffectWeight(m.command)) { if(m.volcmd == VOLCMD_NONE && ModCommand::ConvertVolEffect(m.command, m.param, true)) { // Volume column to the rescue! m.volcmd = m.command; m.vol = m.param; } m.command = origCmd.command; m.param = origCmd.param; } } } if(flags & endOfRowMask) { // End of row break; } } }
int main(void) { // Initialisierung der Gewichts-, Vorgaben- und der Ausgabenmatrix, // sowie der Matrix für Start-Eingabe und Start-Akt.zustand int i, j, nanz = 9, sanz = 4, panz = 4; double **matrix; double **einakt; double **vorgabe; double **ergebnis; int schicht[] = { 2, 3, 3, 1 }; vorgabe = (double **) new double[panz]; ergebnis = (double **) new double[panz]; matrix = (double **) new double[nanz]; einakt = (double **) new double[nanz]; assert(vorgabe); assert(ergebnis); assert(matrix); assert(einakt); for (i=0; i<panz; i++) { vorgabe[i] = (double *) new double[schicht[0]]; assert(vorgabe[i]); ergebnis[i] = (double *) new double[schicht[sanz-1]]; assert(ergebnis[i]); } for (i=0; i<nanz; i++) { matrix[i] = (double *) new double[nanz]; assert(matrix[i]); einakt[i] = (double *) new double[2]; assert(einakt[i]); } srand((unsigned int) time(NULL)); for (i=0; i<nanz; i++) { for (j=0; j<nanz; j++) matrix[i][j] = 1.0/4.0 * (double) ((rand() - rand()) / ((double) RAND_MAX)); } vorgabe[0][0] = 0.0; vorgabe[0][1] = 0.0; ergebnis[0][0] = 0.0; vorgabe[1][0] = 1.0, vorgabe[1][1] = 1.0; ergebnis[1][0] = 0.0; vorgabe[2][0] = 0.0; vorgabe[2][1] = 1.0; ergebnis[2][0] = 1.0; vorgabe[3][0] = 1.0; vorgabe[3][1] = 0.0; ergebnis[3][0] = 1.0; // Initialisierung // abgeschlossen // Erklaerung: // Das Netz ist so aufgebaut, das nur Verbindungen zwischen Neuronen zweier benachbarter // Schichten erlaubt sind. Ausserdem gehe ich in der Implementierung der changeWeight() - // Funktion davon aus, das die Neuronen schichtweise durchnummeriert sind, d.h. Neuron 1 und Neuron 2 sind // Eingabeneuronen in der 1. Schicht, Neuronen 3, 4, 5 liegen in der 2. Schicht, Neuronen 6, 7, 8 in der // 3. Schicht und Neuron 9 ist das Ausgabeneuron in der 4. Schicht. // Erzeugung eines Patterns aus den Vorgabe- und Ergebnismatrizen CPattern *pattern = new CPattern(panz, schicht[0], schicht[sanz-1], vorgabe, ergebnis); // Erzeugung des neuronalen Netzes mit den Daten aus den beiden Matrizen CNeuroNet *net = new CNeuroNet(nanz, sanz, schicht, matrix, einakt); // Trainieren des Netzes auf das Pattern net->trainNet(pattern); // Ausgabe des Netzes, nach erfolgreichem Training des Patterns cout << endl << endl; for (i=0; i<panz; i++) { for (j=0; j<sanz; j++) { net->setEingaben(pattern->vorgaben[i]); net->berechneTakt(); } pattern->printVorgabe(i); cout << ", "; pattern->printAusgabe(i); cout << ", "; net->printAusgabe(); cout << endl; } // Aufräumarbeiten delete net; for (i=0; i<nanz; i++) { delete [] einakt[i]; delete [] matrix[i]; } delete [] vorgabe; delete [] ergebnis; delete [] matrix; delete [] einakt; return 0; }