void ZInstrument::addRegion(SfzRegion& r) { for (int i = 0; i < 128; ++i) { if (r.on_locc[i] != -1 || r.on_hicc[i] != -1) { r.trigger = Trigger::CC; break; } } Zone* z = new Zone; z->sample = readSample(r.sample, 0); if (z->sample) { qDebug("Sample Loop - start %d, end %d, mode %d", z->sample->loopStart(), z->sample->loopEnd(), z->sample->loopMode()); // if there is no opcode defining loop ranges, use sample definitions as fallback (according to spec) if (r.loopStart == -1) r.loopStart = z->sample->loopStart(); if (r.loopEnd == -1) r.loopEnd = z->sample->loopEnd(); } r.setZone(z); if (z->sample) addZone(z); }
bool ZInstrument::loadSfz(const QString& s) { _program = 0; QFile f(s); if (!f.open(QIODevice::ReadOnly)) { qDebug("ZInstrument: cannot load %s", qPrintable(s)); return false; } QFileInfo fi(f); QString path = fi.absolutePath(); qint64 total = fi.size(); QString sample; SfzRegion r; SfzRegion g; // group r.init(path); g.init(path); bool groupMode = false; zerberus->setLoadProgress(0); while (!f.atEnd()) { QByteArray ba = f.readLine(); zerberus->setLoadProgress(((qreal)f.pos() * 100) / total); ba = ba.simplified(); if (ba.isEmpty() || ba.startsWith("//")) continue; if (zerberus->loadWasCanceled()) return false; if (ba.startsWith("<group>")) { if (!groupMode && !r.isEmpty()) addRegion(r); g.init(path); r.init(path); groupMode = true; ba = ba.mid(7); } else if (ba.startsWith("<region>")) { if (groupMode) { g = r; groupMode = false; } else { if (!r.isEmpty()) addRegion(r); r = g; // initialize next region with group values } ba = ba.mid(8); } QRegularExpression re("\\s?(\\w+)="); QRegularExpressionMatchIterator i = re.globalMatch(ba); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); int si = match.capturedEnd(); int ei; if (i.hasNext()) { QRegularExpressionMatch nextMatch = i.peekNext(); ei = nextMatch.capturedStart(); } else ei = ba.size(); QString s = ba.mid(si, ei-si); r.readOp(match.captured(1), s); } } zerberus->setLoadProgress(100); if (!groupMode && !r.isEmpty()) addRegion(r); return true; }
bool ZInstrument::loadSfz(const QString& s) { _program = 0; QFileInfo fi(s); QString path = fi.absolutePath(); QStringList fileContents = readFile(s); if (fileContents.empty()) { return false; } SfzControl c; c.init(); c.defines.clear(); for (int i = 0;i < 128; i++) c.set_cc[i] = -1; int idx = 0; bool inBlockComment = false; // preprocessor while(idx < fileContents.size()) { QRegularExpression findWithSpaces("\"(.+)\""); QRegularExpression comment("//.*$"); QRegularExpression trailingSpacesOrTab("^[\\s\\t]*"); QRegularExpressionMatch foundWithSpaces; QString curLine = fileContents[idx]; QString curLineCopy = curLine; bool nextIsImportant = false; int idxBlockComment = 0; int from = 0; for (QChar chr : curLineCopy) { bool terminated = false; if (nextIsImportant) { nextIsImportant = false; if (inBlockComment && chr == '/') { // found block end inBlockComment = false; terminated = true; curLine.remove(from, idxBlockComment - from + 1); idxBlockComment = from - 1; } else if (!inBlockComment && chr == '*') { // found block start inBlockComment = true; terminated = true; from = idxBlockComment - 1; } } if (!terminated && inBlockComment && chr == '*') nextIsImportant = true; else if (!terminated && !inBlockComment && chr == '/') nextIsImportant = true; idxBlockComment++; } if (inBlockComment) curLine.remove(from, curLine.size() - from); curLine = curLine.remove(comment); curLine.remove(trailingSpacesOrTab); fileContents[idx] = curLine; if (curLine.startsWith("#define")) { QStringList define = curLine.split(" "); foundWithSpaces = findWithSpaces.match(curLine); if (define.size() == 3) c.defines.insert(std::pair<QString, QString>(define[1], define[2])); else if(foundWithSpaces.hasMatch()) c.defines.insert(std::pair<QString, QString>(define[1], foundWithSpaces.captured(1))); fileContents.removeAt(idx); } else if (curLine.startsWith("#include")) { foundWithSpaces = findWithSpaces.match(curLine); if (foundWithSpaces.hasMatch()) { QString newFilename = foundWithSpaces.captured(1); for(auto define : c.defines) { newFilename.replace(define.first, define.second); } QStringList newFileContents = readFile(path + "/" + newFilename); if (newFileContents.empty()) return false; int offset = 1; for (QString newFileLine : newFileContents) { fileContents.insert(idx+offset, newFileLine); offset++; } fileContents.removeAt(idx); } } else if (curLine.isEmpty()) fileContents.removeAt(idx); else idx++; } int total = fileContents.size(); SfzRegion r; SfzRegion g; // group SfzRegion glob; r.init(path); g.init(path); glob.init(path); bool groupMode = false; bool globMode = false; zerberus->setLoadProgress(0); for (int idx = 0; idx < fileContents.size(); idx++) { QString curLine = fileContents[idx]; zerberus->setLoadProgress(((qreal) idx * 100) / (qreal) total); if (zerberus->loadWasCanceled()) return false; if (curLine.startsWith("<global>")) { if (!globMode && !groupMode && !r.isEmpty()) addRegion(r); glob.init(path); g.init(path); // global also resets group r.init(path); globMode = true; } if (curLine.startsWith("<group>")) { if (!groupMode && !globMode && !r.isEmpty()) addRegion(r); g.init(path); if (globMode) { glob = r; globMode = false; } else { r = glob; // initialize group with global values } groupMode = true; curLine = curLine.mid(7); } else if (curLine.startsWith("<region>")) { if (groupMode) { g = r; groupMode = false; } else if (globMode) { glob = r; g = glob; globMode = false; } else { if (!r.isEmpty()) addRegion(r); r = g; // initialize next region with group values } curLine = curLine.mid(8); } else if (curLine.startsWith("<control>")) c.init(); QRegularExpression re("\\s?([\\w\\$]+)="); // defines often use the $-sign QRegularExpressionMatchIterator i = re.globalMatch(curLine); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); int si = match.capturedEnd(); int ei; if (i.hasNext()) { QRegularExpressionMatch nextMatch = i.peekNext(); ei = nextMatch.capturedStart(); } else ei = curLine.size(); QString s = curLine.mid(si, ei-si); r.readOp(match.captured(1), s, c); } } for (int i = 0; i < 128; i++) _setcc[i] = c.set_cc[i]; zerberus->setLoadProgress(100); if (!groupMode && !globMode && !r.isEmpty()) addRegion(r); return true; }