/* * Copyright (c) 2014-2020 Christian Schoenebeck * * http://www.linuxsampler.org * * This file is part of LinuxSampler and released under the same terms. * See README file for details. */ #include "InstrumentScriptVMFunctions.h" #include "InstrumentScriptVM.h" #include "EngineChannel.h" namespace LinuxSampler { namespace gig { ///////////////////////////////////////////////////////////////////////// // Function: // gig_set_dim_zone(event_id, dimension, zone) InstrumentScriptVMFunction_gig_set_dim_zone::InstrumentScriptVMFunction_gig_set_dim_zone(InstrumentScriptVM* parent) : m_vm(parent) { } bool InstrumentScriptVMFunction_gig_set_dim_zone::acceptsArgType(vmint iArg, ExprType_t type) const { return type == INT_EXPR || type == INT_ARR_EXPR; } VMFnResult* InstrumentScriptVMFunction_gig_set_dim_zone::exec(VMFnArgs* args) { EngineChannel* pEngineChannel = static_cast(m_vm->m_event->cause.pEngineChannel); vmint dim = args->arg(1)->asInt()->evalInt(); vmint zone = args->arg(2)->asInt()->evalInt(); if (args->arg(0)->exprType() == INT_EXPR) { const ScriptID id = args->arg(0)->asInt()->evalInt(); if (!id) { wrnMsg("gig_set_dim_zone(): note ID for argument 1 may not be zero"); return successResult(); } if (!id.isNoteID()) { wrnMsg("gig_set_dim_zone(): argument 1 is not a note ID"); return successResult(); } NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() ); if (!pNote) { dmsg(2,("gig_set_dim_zone(): no active note with ID %d\n", int(id))); return successResult(); } int note = pNote->cause.Param.Note.Key; ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(note); if (!pRegion) { dmsg(2,("gig_set_dim_zone(): no region for key %d\n", note)); return successResult(); } int idx = -1, baseBits = 0; for (int i = 0; i < pRegion->Dimensions; ++i) { if (pRegion->pDimensionDefinitions[i].dimension == dim) { idx = i; break; } baseBits += pRegion->pDimensionDefinitions[i].bits; } if (idx < 0) { dmsg(2,("gig_set_dim_zone(): no such gig dimension %" PRId64 "\n", (int64_t)dim)); return successResult(); // no such dimension found } int bits = pRegion->pDimensionDefinitions[idx].bits; int mask = 0; for (int i = 0; i < bits; ++i) mask |= (1 << (baseBits + i)); pNote->Format.Gig.DimMask |= mask; pNote->Format.Gig.DimBits |= (zone << baseBits) & mask; dmsg(3,("gig_set_dim_zone(): success, mask=%d bits=%d\n", pNote->Format.Gig.DimMask, pNote->Format.Gig.DimBits)); } else if (args->arg(0)->exprType() == INT_ARR_EXPR) { VMIntArrayExpr* ids = args->arg(0)->asIntArray(); for (vmint i = 0; i < ids->arraySize(); ++i) { const ScriptID id = ids->evalIntElement(i); if (!id || !id.isNoteID()) continue; NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() ); if (!pNote) continue; int note = pNote->cause.Param.Note.Key; ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(note); if (!pRegion) continue; int idx = -1, baseBits = 0; for (int i = 0; i < pRegion->Dimensions; ++i) { if (pRegion->pDimensionDefinitions[i].dimension == dim) { idx = i; break; } baseBits += pRegion->pDimensionDefinitions[i].bits; } if (idx < 0) continue; int bits = pRegion->pDimensionDefinitions[idx].bits; int mask = 0; for (int i = 0; i < bits; ++i) mask |= (1 << (baseBits + i)); pNote->Format.Gig.DimMask |= mask; pNote->Format.Gig.DimBits |= (zone << baseBits) & mask; dmsg(3,("gig_set_dim_zone(): success, mask=%d bits=%d\n", pNote->Format.Gig.DimMask, pNote->Format.Gig.DimBits)); } } return successResult(); } ///////////////////////////////////////////////////////////////////////// // Function: // same_region(key1, key2) InstrumentScriptVMFunction_same_region::InstrumentScriptVMFunction_same_region(InstrumentScriptVM* parent) : m_vm(parent) { } VMFnResult* InstrumentScriptVMFunction_same_region::exec(VMFnArgs* args) { EngineChannel* pEngineChannel = static_cast(m_vm->m_event->cause.pEngineChannel); vmint key1 = args->arg(0)->asInt()->evalInt(); vmint key2 = args->arg(1)->asInt()->evalInt(); if (key1 < 0 || key1 > 127) { wrnMsg("same_region(): key number for argument 1 out of range"); return successResult(-1); } if (key2 < 0 || key2 > 127) { wrnMsg("same_region(): key number for argument 2 out of range"); return successResult(-1); } ::gig::Region* pRgn1 = pEngineChannel->pInstrument->GetRegion((int)key1); ::gig::Region* pRgn2 = pEngineChannel->pInstrument->GetRegion((int)key2); if (!pRgn1 && !pRgn2) return successResult(5); if (pRgn1 == pRgn2) return successResult(1); if (pRgn1 && !pRgn2) return successResult(3); if (!pRgn1 && pRgn2) return successResult(4); if (pRgn1->KeyRange.overlaps(pRgn2->KeyRange)) return successResult(2); return successResult(0); } }} // namespace LinuxSampler::gig