2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2009 by Christian Schoenebeck * |
* Copyright (C) 2003-2013 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
910 |
} |
} |
911 |
|
|
912 |
// reverse the sample frames for backward playback |
// reverse the sample frames for backward playback |
913 |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
if (totalreadsamples > swapareastart) //FIXME: this if() is just a crash workaround for now (#102), but totalreadsamples <= swapareastart should never be the case, so there's probably still a bug above! |
914 |
|
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
915 |
} |
} |
916 |
} while (samplestoread && readsamples); |
} while (samplestoread && readsamples); |
917 |
break; |
break; |
1433 |
: vcf_res_ctrl_none; |
: vcf_res_ctrl_none; |
1434 |
uint16_t eg3depth = _3ewa->ReadUint16(); |
uint16_t eg3depth = _3ewa->ReadUint16(); |
1435 |
EG3Depth = (eg3depth <= 1200) ? eg3depth /* positives */ |
EG3Depth = (eg3depth <= 1200) ? eg3depth /* positives */ |
1436 |
: (-1) * (int16_t) ((eg3depth ^ 0xffff) + 1); /* binary complementary for negatives */ |
: (-1) * (int16_t) ((eg3depth ^ 0xfff) + 1); /* binary complementary for negatives */ |
1437 |
_3ewa->ReadInt16(); // unknown |
_3ewa->ReadInt16(); // unknown |
1438 |
ChannelOffset = _3ewa->ReadUint8() / 4; |
ChannelOffset = _3ewa->ReadUint8() / 4; |
1439 |
uint8_t regoptions = _3ewa->ReadUint8(); |
uint8_t regoptions = _3ewa->ReadUint8(); |
1581 |
*/ |
*/ |
1582 |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) { |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) { |
1583 |
Instances++; |
Instances++; |
1584 |
|
//NOTE: I think we cannot call CopyAssign() here (in a constructor) as long as its a virtual method |
1585 |
*this = src; // default memberwise shallow copy of all parameters |
*this = src; // default memberwise shallow copy of all parameters |
1586 |
pParentList = _3ewl; // restore the chunk pointer |
pParentList = _3ewl; // restore the chunk pointer |
1587 |
|
|
1597 |
pSampleLoops[k] = src.pSampleLoops[k]; |
pSampleLoops[k] = src.pSampleLoops[k]; |
1598 |
} |
} |
1599 |
} |
} |
1600 |
|
|
1601 |
|
/** |
1602 |
|
* Make a (semi) deep copy of the DimensionRegion object given by @a orig |
1603 |
|
* and assign it to this object. |
1604 |
|
* |
1605 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
1606 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
1607 |
|
* |
1608 |
|
* @param orig - original DimensionRegion object to be copied from |
1609 |
|
*/ |
1610 |
|
void DimensionRegion::CopyAssign(const DimensionRegion* orig) { |
1611 |
|
// delete all allocated data first |
1612 |
|
if (VelocityTable) delete [] VelocityTable; |
1613 |
|
if (pSampleLoops) delete [] pSampleLoops; |
1614 |
|
|
1615 |
|
// backup parent list pointer |
1616 |
|
RIFF::List* p = pParentList; |
1617 |
|
|
1618 |
|
//NOTE: copy code copied from assignment constructor above, see comment there as well |
1619 |
|
|
1620 |
|
*this = *orig; // default memberwise shallow copy of all parameters |
1621 |
|
pParentList = p; // restore the chunk pointer |
1622 |
|
|
1623 |
|
// deep copy of owned structures |
1624 |
|
if (orig->VelocityTable) { |
1625 |
|
VelocityTable = new uint8_t[128]; |
1626 |
|
for (int k = 0 ; k < 128 ; k++) |
1627 |
|
VelocityTable[k] = orig->VelocityTable[k]; |
1628 |
|
} |
1629 |
|
if (orig->pSampleLoops) { |
1630 |
|
pSampleLoops = new DLS::sample_loop_t[orig->SampleLoops]; |
1631 |
|
for (int k = 0 ; k < orig->SampleLoops ; k++) |
1632 |
|
pSampleLoops[k] = orig->pSampleLoops[k]; |
1633 |
|
} |
1634 |
|
} |
1635 |
|
|
1636 |
/** |
/** |
1637 |
* Updates the respective member variable and updates @c SampleAttenuation |
* Updates the respective member variable and updates @c SampleAttenuation |
1873 |
} |
} |
1874 |
|
|
1875 |
const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth |
const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth |
1876 |
: uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */ |
: uint16_t(((-EG3Depth) - 1) ^ 0xfff); /* binary complementary for negatives */ |
1877 |
store16(&pData[116], eg3depth); |
store16(&pData[116], eg3depth); |
1878 |
|
|
1879 |
// next 2 bytes unknown |
// next 2 bytes unknown |
1921 |
(VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */ |
(VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */ |
1922 |
pData[137] = vcfbreakpoint; |
pData[137] = vcfbreakpoint; |
1923 |
|
|
1924 |
const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 | |
const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 + |
1925 |
VCFVelocityCurve * 5; |
VCFVelocityCurve * 5; |
1926 |
pData[138] = vcfvelocity; |
pData[138] = vcfvelocity; |
1927 |
|
|
2961 |
} |
} |
2962 |
return NULL; |
return NULL; |
2963 |
} |
} |
2964 |
|
|
2965 |
|
/** |
2966 |
|
* Make a (semi) deep copy of the Region object given by @a orig |
2967 |
|
* and assign it to this object. |
2968 |
|
* |
2969 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
2970 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
2971 |
|
* |
2972 |
|
* @param orig - original Region object to be copied from |
2973 |
|
*/ |
2974 |
|
void Region::CopyAssign(const Region* orig) { |
2975 |
|
// handle base classes |
2976 |
|
DLS::Region::CopyAssign(orig); |
2977 |
|
|
2978 |
|
// handle own member variables |
2979 |
|
for (int i = Dimensions - 1; i >= 0; --i) { |
2980 |
|
DeleteDimension(&pDimensionDefinitions[i]); |
2981 |
|
} |
2982 |
|
Layers = 0; // just to be sure |
2983 |
|
for (int i = 0; i < orig->Dimensions; i++) { |
2984 |
|
// we need to copy the dim definition here, to avoid the compiler |
2985 |
|
// complaining about const-ness issue |
2986 |
|
dimension_def_t def = orig->pDimensionDefinitions[i]; |
2987 |
|
AddDimension(&def); |
2988 |
|
} |
2989 |
|
for (int i = 0; i < 256; i++) { |
2990 |
|
if (pDimensionRegions[i] && orig->pDimensionRegions[i]) { |
2991 |
|
pDimensionRegions[i]->CopyAssign( |
2992 |
|
orig->pDimensionRegions[i] |
2993 |
|
); |
2994 |
|
} |
2995 |
|
} |
2996 |
|
Layers = orig->Layers; |
2997 |
|
} |
2998 |
|
|
2999 |
|
|
3000 |
// *************** MidiRule *************** |
// *************** MidiRule *************** |
3106 |
} |
} |
3107 |
|
|
3108 |
Instrument::~Instrument() { |
Instrument::~Instrument() { |
3109 |
|
for (int i = 0 ; pMidiRules[i] ; i++) { |
3110 |
|
delete pMidiRules[i]; |
3111 |
|
} |
3112 |
delete[] pMidiRules; |
delete[] pMidiRules; |
3113 |
} |
} |
3114 |
|
|
3237 |
MidiRule* Instrument::GetMidiRule(int i) { |
MidiRule* Instrument::GetMidiRule(int i) { |
3238 |
return pMidiRules[i]; |
return pMidiRules[i]; |
3239 |
} |
} |
3240 |
|
|
3241 |
|
/** |
3242 |
|
* Make a (semi) deep copy of the Instrument object given by @a orig |
3243 |
|
* and assign it to this object. |
3244 |
|
* |
3245 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
3246 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
3247 |
|
* |
3248 |
|
* @param orig - original Instrument object to be copied from |
3249 |
|
*/ |
3250 |
|
void Instrument::CopyAssign(const Instrument* orig) { |
3251 |
|
// handle base class |
3252 |
|
// (without copying DLS region stuff) |
3253 |
|
DLS::Instrument::CopyAssignCore(orig); |
3254 |
|
|
3255 |
|
// handle own member variables |
3256 |
|
Attenuation = orig->Attenuation; |
3257 |
|
EffectSend = orig->EffectSend; |
3258 |
|
FineTune = orig->FineTune; |
3259 |
|
PitchbendRange = orig->PitchbendRange; |
3260 |
|
PianoReleaseMode = orig->PianoReleaseMode; |
3261 |
|
DimensionKeyRange = orig->DimensionKeyRange; |
3262 |
|
|
3263 |
|
// free old midi rules |
3264 |
|
for (int i = 0 ; pMidiRules[i] ; i++) { |
3265 |
|
delete pMidiRules[i]; |
3266 |
|
} |
3267 |
|
//TODO: MIDI rule copying |
3268 |
|
pMidiRules[0] = NULL; |
3269 |
|
|
3270 |
|
// delete all old regions |
3271 |
|
while (Regions) DeleteRegion(GetFirstRegion()); |
3272 |
|
// create new regions and copy them from original |
3273 |
|
{ |
3274 |
|
RegionList::const_iterator it = orig->pRegions->begin(); |
3275 |
|
for (int i = 0; i < orig->Regions; ++i, ++it) { |
3276 |
|
Region* dstRgn = AddRegion(); |
3277 |
|
//NOTE: Region does semi-deep copy ! |
3278 |
|
dstRgn->CopyAssign( |
3279 |
|
static_cast<gig::Region*>(*it) |
3280 |
|
); |
3281 |
|
} |
3282 |
|
} |
3283 |
|
|
3284 |
|
UpdateRegionKeyTable(); |
3285 |
|
} |
3286 |
|
|
3287 |
|
|
3288 |
// *************** Group *************** |
// *************** Group *************** |
3682 |
pInstruments->push_back(pInstrument); |
pInstruments->push_back(pInstrument); |
3683 |
return pInstrument; |
return pInstrument; |
3684 |
} |
} |
3685 |
|
|
3686 |
|
/** @brief Add a duplicate of an existing instrument. |
3687 |
|
* |
3688 |
|
* Duplicates the instrument definition given by @a orig and adds it |
3689 |
|
* to this file. This allows in an instrument editor application to |
3690 |
|
* easily create variations of an instrument, which will be stored in |
3691 |
|
* the same .gig file, sharing i.e. the same samples. |
3692 |
|
* |
3693 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
3694 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
3695 |
|
* |
3696 |
|
* You have to call Save() to make this persistent to the file. |
3697 |
|
* |
3698 |
|
* @param orig - original instrument to be copied |
3699 |
|
* @returns duplicated copy of the given instrument |
3700 |
|
*/ |
3701 |
|
Instrument* File::AddDuplicateInstrument(const Instrument* orig) { |
3702 |
|
Instrument* instr = AddInstrument(); |
3703 |
|
instr->CopyAssign(orig); |
3704 |
|
return instr; |
3705 |
|
} |
3706 |
|
|
3707 |
/** @brief Delete an instrument. |
/** @brief Delete an instrument. |
3708 |
* |
* |