--- libgig/trunk/src/tools/wav2gig.cpp 2021/08/28 13:46:54 3989 +++ libgig/trunk/src/tools/wav2gig.cpp 2021/08/30 20:14:15 3990 @@ -82,7 +82,7 @@ static void printUsage() { cout << "wav2gig - Create GigaStudio file from a set of WAV files." << endl; cout << endl; - cout << "Usage: wav2gig [-v] [-f] [-r] GIGFILE WAVFILEORDIR1 [ WAVFILEORDIR2 ... ]" << endl; + cout << "Usage: wav2gig [OPTIONS] GIGFILE WAVFILEORDIR1 [ WAVFILEORDIR2 ... ]" << endl; cout << endl; cout << " -v Print version and exit." << endl; cout << endl; @@ -90,6 +90,28 @@ cout << endl; cout << " -r Recurse through all subdirs of provided input WAV dirs." << endl; cout << endl; + cout << " --regex-name1 PATTERN" << endl; + cout << endl; + cout << " Regular expression for overriding the NAME1 part of the input sample file name scheme." << endl; + cout << endl; + cout << " --regex-name2 PATTERN" << endl; + cout << endl; + cout << " Regular expression for overriding the NAME2 part of the input sample file name scheme." << endl; + cout << endl; + cout << " --regex-velocity-nr PATTERN" << endl; + cout << endl; + cout << " Regular expression for overriding the VELOCITY_NR part of the input sample file name scheme." << endl; + cout << endl; + cout << " --regex-note-nr PATTERN" << endl; + cout << endl; + cout << " Regular expression for overriding the NOTE_NR part of the input sample file name scheme." << endl; + cout << endl; + cout << " --regex-note-name PATTERN" << endl; + cout << endl; + cout << " Regular expression for overriding the NOTE_NAME part of the input sample file name scheme." << endl; + cout << endl; + cout << "Read 'man wav2gig' for detailed help." << endl; + cout << endl; } static bool beginsWith(const string& haystack, const string& needle) { @@ -100,6 +122,15 @@ return haystack.substr(haystack.size() - needle.size(), needle.size()) == needle; } +static string tokenByRegExGroup(const string& haystack, const string& pattern, + size_t group = 1) +{ + regex rx(pattern); + smatch m; + regex_search(haystack, m, rx); + return (m.size() <= group) ? (string) "" : (string) m[group]; +} + static bool fileExists(const string& filename) { FILE* hFile = fopen(filename.c_str(), "r"); if (!hFile) return false; @@ -159,6 +190,14 @@ return false; } +struct FilenameRegExPatterns { + string name1; + string name2; + string velocityNr; + string noteNr; + string noteName; +}; + static void collectWavFilesOfDir(set& result, string path, bool bRecurse, bool* pbError = NULL) { DIR* d = opendir(path.c_str()); if (!d) { @@ -265,7 +304,9 @@ typedef map WavInstrument; -static WavInfo getWavInfo(string filename) { +static WavInfo getWavInfo(string filename, + const FilenameRegExPatterns& patterns) +{ WavInfo wav; wav.fileName = filename; wav.sfinfo = {}; @@ -288,26 +329,43 @@ } } { - regex rx( - "^([^-]+) - " // name 1 (e.g. "BSTEIN18") - "([^-]+) - " // name 2 (e.g. "noname") - "([^-]+) - " // velocity value (e.g. "18") - "([^-]+) - " // note number (e.g. "021") - "([^.]+)" // note name (e.g. "a-1") - ); - smatch m; - regex_search(filename, m, rx); - if (m.size() < 5) { - cerr << "Invalid file name format: \"" << filename << "\"!" << endl; + wav.name1 = tokenByRegExGroup(filename, patterns.name1); + if (wav.name1.empty()) { + cerr << "Unexpected file name format: \"" << filename + << "\" for 'name1' RegEx pattern \"" << patterns.name1 + << "\" !" << endl; + exit(EXIT_FAILURE); + } + wav.name2 = tokenByRegExGroup(filename, patterns.name2); + if (wav.name2.empty()) { + cerr << "Unexpected file name format: \"" << filename + << "\" for 'name2' RegEx pattern \"" << patterns.name2 + << "\" !" << endl; + exit(EXIT_FAILURE); + } + string sVelocity = tokenByRegExGroup(filename, patterns.velocityNr); + if (sVelocity.empty()) { + cerr << "Unexpected file name format: \"" << filename + << "\" for 'velocity-nr' RegEx pattern \"" << patterns.velocityNr + << "\" !" << endl; exit(EXIT_FAILURE); } - wav.name1 = m[1]; - string sVelocity = m[3]; wav.velocity = atoi(sVelocity.c_str()); - string sNote = m[4]; - wav.note = atoi(sNote.c_str()); - wav.name2 = m[2]; - wav.noteName = m[5]; + string sNoteNr = tokenByRegExGroup(filename, patterns.noteNr); + if (sNoteNr.empty()) { + cerr << "Unexpected file name format: \"" << filename + << "\" for 'note-nr' RegEx pattern \"" << patterns.noteNr + << "\" !" << endl; + exit(EXIT_FAILURE); + } + wav.note = atoi(sNoteNr.c_str()); + wav.noteName = tokenByRegExGroup(filename, patterns.noteName); + if (wav.noteName.empty()) { + cerr << "Unexpected file name format: \"" << filename + << "\" for 'note-name' RegEx pattern \"" << patterns.noteName + << "\" !" << endl; + exit(EXIT_FAILURE); + } } return wav; } @@ -377,11 +435,24 @@ int main(int argc, char *argv[]) { bool bForce = false; bool bRecursive = false; + FilenameRegExPatterns patterns = { + // name 1 (e.g. "BSTEIN18") + .name1 = "^([^-]+) - [^-]+ - [^-]+ - [^-]+ - [^.]+", + // name 2 (e.g. "noname") + .name2 = "^[^-]+ - ([^-]+) - [^-]+ - [^-]+ - [^.]+", + // velocity value (e.g. "18") + .velocityNr = "^[^-]+ - [^-]+ - ([^-]+) - [^-]+ - [^.]+", + // note number (e.g. "021") + .noteNr = "^[^-]+ - [^-]+ - [^-]+ - ([^-]+) - [^.]+", + // note name (e.g. "a-1") + .noteName = "^[^-]+ - [^-]+ - [^-]+ - [^-]+ - ([^.]+)", + }; // validate & parse arguments provided to this program int iArg; for (iArg = 1; iArg < argc; ++iArg) { const string opt = argv[iArg]; + const string nextOpt = (iArg + 1 < argc) ? argv[iArg + 1] : ""; if (opt == "--") { // common for all command line tools: separator between initial option arguments and subsequent file arguments iArg++; break; @@ -395,6 +466,36 @@ bForce = true; } else if (opt == "-r") { bRecursive = true; + } else if (opt == "--regex-name1") { + if (nextOpt.empty() || beginsWith(nextOpt, "-")) { + cerr << "Missing argument for option '" << opt << "'" << endl; + return EXIT_FAILURE; + } + patterns.name1 = nextOpt; + } else if (opt == "--regex-name2") { + if (nextOpt.empty() || beginsWith(nextOpt, "-")) { + cerr << "Missing argument for option '" << opt << "'" << endl; + return EXIT_FAILURE; + } + patterns.name2 = nextOpt; + } else if (opt == "--regex-velocity-nr") { + if (nextOpt.empty() || beginsWith(nextOpt, "-")) { + cerr << "Missing argument for option '" << opt << "'" << endl; + return EXIT_FAILURE; + } + patterns.velocityNr = nextOpt; + } else if (opt == "--regex-note-nr") { + if (nextOpt.empty() || beginsWith(nextOpt, "-")) { + cerr << "Missing argument for option '" << opt << "'" << endl; + return EXIT_FAILURE; + } + patterns.noteNr = nextOpt; + } else if (opt == "--regex-note-name") { + if (nextOpt.empty() || beginsWith(nextOpt, "-")) { + cerr << "Missing argument for option '" << opt << "'" << endl; + return EXIT_FAILURE; + } + patterns.noteName = nextOpt; } else { cerr << "Unknown option '" << opt << "'" << endl; cerr << endl; @@ -462,7 +563,7 @@ for (set::const_iterator it = wavFileNames.begin(); it != wavFileNames.end(); ++it) { - WavInfo wavInfo = getWavInfo(*it); + WavInfo wavInfo = getWavInfo(*it, patterns); wavInfo.assertValid(); // make sure collected informations are OK if (wavInstrument[wavInfo.note].count(wavInfo.velocity)) { cerr << "Velocity conflict between file '" << wavInfo.fileName