324 |
return velocityRanges; |
return velocityRanges; |
325 |
} |
} |
326 |
|
|
327 |
|
/** |
328 |
|
* Ensure that the given list of ranges covers the full range between 0 .. 127. |
329 |
|
* |
330 |
|
* @param orig - (input) original set of ranges (read only) |
331 |
|
* @param corrected - (output) corrected set of ranges (will be cleared and refilled) |
332 |
|
* @return map that pairs respective original range with respective corrected range |
333 |
|
*/ |
334 |
|
static map<DLS::range_t,DLS::range_t> killGapsInRanges(const set<DLS::range_t>& orig, set<DLS::range_t>& corrected) { |
335 |
|
map<DLS::range_t,DLS::range_t> result; |
336 |
|
corrected.clear(); |
337 |
|
if (orig.empty()) return result; |
338 |
|
|
339 |
|
int iLow = 0; |
340 |
|
int i = 0; |
341 |
|
for (set<DLS::range_t>::const_iterator it = orig.begin(); it != orig.end(); ++it, ++i) { |
342 |
|
DLS::range_t r = *it; |
343 |
|
r.low = iLow; |
344 |
|
iLow = r.high + 1; |
345 |
|
if (i == orig.size() - 1) r.high = 127; |
346 |
|
corrected.insert(r); |
347 |
|
result[*it] = r; |
348 |
|
} |
349 |
|
return result; |
350 |
|
} |
351 |
|
|
352 |
|
static void printRanges(const set<DLS::range_t>& ranges) { |
353 |
|
cout << "{ "; |
354 |
|
for (set<DLS::range_t>::const_iterator it = ranges.begin(); it != ranges.end(); ++it) { |
355 |
|
if (it != ranges.begin()) cout << ", "; |
356 |
|
cout << (int)it->low << ".." << (int)it->high; |
357 |
|
} |
358 |
|
cout << " }" << flush; |
359 |
|
} |
360 |
|
|
361 |
static vector<Korg::KSFSample*> ksfSamples; // input .KSF files |
static vector<Korg::KSFSample*> ksfSamples; // input .KSF files |
362 |
static vector<Korg::KMPInstrument*> kmpInstruments; // input .KMP files |
static vector<Korg::KMPInstrument*> kmpInstruments; // input .KMP files |
363 |
static gig::File* g_gig = NULL; // output .gig file |
static gig::File* g_gig = NULL; // output .gig file |
518 |
bool bForce = false; |
bool bForce = false; |
519 |
|
|
520 |
// validate & parse arguments provided to this program |
// validate & parse arguments provided to this program |
|
if (argc < 3) { |
|
|
printUsage(); |
|
|
return EXIT_FAILURE; |
|
|
} |
|
521 |
int iArg; |
int iArg; |
522 |
for (iArg = 1; iArg < argc; ++iArg) { |
for (iArg = 1; iArg < argc; ++iArg) { |
523 |
const string opt = argv[iArg]; |
const string opt = argv[iArg]; |
541 |
return EXIT_FAILURE; |
return EXIT_FAILURE; |
542 |
} |
} |
543 |
} |
} |
544 |
|
if (argc < 3) { |
545 |
|
printUsage(); |
546 |
|
return EXIT_FAILURE; |
547 |
|
} |
548 |
|
|
549 |
set<string> inFileNames; |
set<string> inFileNames; |
550 |
string outFileName; |
string outFileName; |
631 |
dim.dimension = gig::dimension_samplechannel; |
dim.dimension = gig::dimension_samplechannel; |
632 |
dim.bits = 1; // 2^(1) = 2 |
dim.bits = 1; // 2^(1) = 2 |
633 |
dim.zones = 2; // stereo = 2 audio channels = 2 split zones |
dim.zones = 2; // stereo = 2 audio channels = 2 split zones |
634 |
|
cout << "Adding stereo dimension." << endl; |
635 |
gigRegion->AddDimension(&dim); |
gigRegion->AddDimension(&dim); |
636 |
|
|
637 |
iStereoDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_samplechannel); |
iStereoDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_samplechannel); |
648 |
DLS::range_t velRange = { 0 , 127 }; |
DLS::range_t velRange = { 0 , 127 }; |
649 |
bool isVelocitySplit = bInterpretNames && hasNumberRangeIndicator(kmpInstr->Name()); |
bool isVelocitySplit = bInterpretNames && hasNumberRangeIndicator(kmpInstr->Name()); |
650 |
if (isVelocitySplit) { // a velocity split is required for this region ... |
if (isVelocitySplit) { // a velocity split is required for this region ... |
651 |
// get the amount of velocity split zones for this |
// get the set of velocity split zones defined for |
652 |
// particular output instrument and key range |
// this particular output instrument and key range |
653 |
const set<DLS::range_t> velocitySplits = collectVelocitySplits(group, keyRange); |
set<DLS::range_t> origVelocitySplits = collectVelocitySplits(group, keyRange); |
654 |
|
// if there are any gaps, that is if the list of velocity |
655 |
// get the velocity range for current KORG region |
// split ranges do not cover the full range completely |
656 |
|
// between 0 .. 127, then auto correct it by increasing |
657 |
|
// the split zones accordingly |
658 |
|
map<DLS::range_t,DLS::range_t> velocityCorrectionMap; // maps original defined velocity range (key) -> corrected velocity range (value) |
659 |
{ |
{ |
660 |
int from, to; |
set<DLS::range_t> correctedSplits; |
661 |
if (parseNumberRange(kmpInstr->Name(), from, to) == kmpInstr->Name()) |
velocityCorrectionMap = killGapsInRanges(origVelocitySplits, correctedSplits); |
662 |
throw Korg::Exception("Internal error: parsing velocity range failed"); |
if (correctedSplits != origVelocitySplits) { |
663 |
velRange.low = from; |
cout << "WARNING: Velocity splits did not cover the full range 0..127, auto adjusted it from " << flush; |
664 |
velRange.high = to; |
printRanges(origVelocitySplits); |
665 |
|
cout << " to " << flush; |
666 |
|
printRanges(correctedSplits); |
667 |
|
cout << endl; |
668 |
|
} |
669 |
} |
} |
670 |
|
|
671 |
// create velocity split dimension if it doesn't exist already ... |
// only create a velocity dimension if there was really |
672 |
iVelocityDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_velocity); |
// more than one velocity split zone defined |
673 |
if (iVelocityDimensionIndex < 0) { |
if (origVelocitySplits.size() <= 1) { |
674 |
gig::dimension_def_t dim; |
cerr << "WARNING: Velocity split mentioned, but with only one zone, thus ignoring velocity split.\n"; |
675 |
dim.dimension = gig::dimension_velocity; |
} else { |
676 |
dim.zones = velocitySplits.size(); |
// get the velocity range for current KORG region |
677 |
|
{ |
678 |
// Find the number of bits required to hold the |
int from, to; |
679 |
// specified amount of zones. |
if (parseNumberRange(kmpInstr->Name(), from, to) == kmpInstr->Name()) |
680 |
int zoneBits = dim.zones - 1; |
throw Korg::Exception("Internal error: parsing velocity range failed"); |
681 |
for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2); |
velRange.low = from; |
682 |
dim.bits += zoneBits; |
velRange.high = to; |
683 |
|
if (velocityCorrectionMap.find(velRange) == velocityCorrectionMap.end()) |
684 |
|
throw Korg::Exception("Internal error: inconsistency in velocity split correction map"); |
685 |
|
velRange = velocityCorrectionMap[velRange]; // corrected |
686 |
|
} |
687 |
|
|
688 |
gigRegion->AddDimension(&dim); |
// create velocity split dimension if it doesn't exist already ... |
|
|
|
689 |
iVelocityDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_velocity); |
iVelocityDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_velocity); |
690 |
} |
if (iVelocityDimensionIndex < 0) { |
691 |
|
gig::dimension_def_t dim; |
692 |
|
dim.dimension = gig::dimension_velocity; |
693 |
|
dim.zones = origVelocitySplits.size(); |
694 |
|
// Find the number of bits required to hold the |
695 |
|
// specified amount of zones. |
696 |
|
int zoneBits = dim.zones - 1; |
697 |
|
for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2); |
698 |
|
dim.bits += zoneBits; |
699 |
|
cout << "Adding velocity dimension: zones=" << (int)dim.zones << ", bits=" << (int)dim.bits << endl; |
700 |
|
gigRegion->AddDimension(&dim); |
701 |
|
|
702 |
|
iVelocityDimensionIndex = getDimensionIndex(gigRegion, gig::dimension_velocity); |
703 |
|
} |
704 |
|
|
705 |
if (iVelocityDimensionIndex < 0) |
if (iVelocityDimensionIndex < 0) |
706 |
throw gig::Exception("Internal error: Could not resolve target velocity dimension bit"); |
throw gig::Exception("Internal error: Could not resolve target velocity dimension bit"); |
707 |
|
|
708 |
// find the velocity zone for this one |
// find the velocity zone for this one |
709 |
int iVelocitySplitZone = -1; |
int iVelocitySplitZone = -1; |
|
{ |
|
|
int i = 0; |
|
|
for (set<DLS::range_t>::const_iterator itVelSplit = velocitySplits.begin(); |
|
|
itVelSplit != velocitySplits.end(); ++itVelSplit, ++i) |
|
710 |
{ |
{ |
711 |
if (*itVelSplit == velRange) { |
int i = 0; |
712 |
iVelocitySplitZone = i; |
for (map<DLS::range_t,DLS::range_t>::const_iterator itVelSplit = velocityCorrectionMap.begin(); |
713 |
break; |
itVelSplit != velocityCorrectionMap.end(); ++itVelSplit, ++i) |
714 |
|
{ |
715 |
|
if (itVelSplit->second == velRange) { // already corrected before, thus second, not first |
716 |
|
iVelocitySplitZone = i; |
717 |
|
break; |
718 |
|
} |
719 |
} |
} |
720 |
|
if (iVelocitySplitZone == -1) |
721 |
|
throw gig::Exception("Internal error: Could not resolve target velocity dimension zone"); |
722 |
} |
} |
|
if (iVelocitySplitZone == -1) |
|
|
throw gig::Exception("Internal error: Could not resolve target velocity dimension zone"); |
|
|
} |
|
723 |
|
|
724 |
// select dimension bit for this stereo dimension split |
// select dimension bit for this stereo dimension split |
725 |
iDimBits[iVelocityDimensionIndex] = iVelocitySplitZone; |
iDimBits[iVelocityDimensionIndex] = iVelocitySplitZone; |
726 |
|
} |
727 |
} |
} |
728 |
|
|
729 |
// resolve target gig::DimensionRegion for the left/right and velocity split zone detected above |
// resolve target gig::DimensionRegion for the left/right and velocity split zone detected above |