|
@@ -5797,6 +5797,11 @@ struct cmDspClass_str* cmRouterClassCons( cmDspCtx_t* ctx )
|
5797
|
5797
|
// 'false' is transmitted to notify the channel that it should shutdown.
|
5798
|
5798
|
// The channel is not considered actually shutdown until dis[i]
|
5799
|
5799
|
// recieves a 'false'.
|
|
5800
|
+// ch The next prospective next available channel is sent whenever it
|
|
5801
|
+// becomes available. A next channel becomes available when
|
|
5802
|
+// a channel is marked as inactive via dis[i] or when
|
|
5803
|
+// a new channel is made active, via trigger, and another
|
|
5804
|
+// channel active channel exists.
|
5800
|
5805
|
// Notes:
|
5801
|
5806
|
// The gate[] output is designed to work with the gate[] input of Xfader. When
|
5802
|
5807
|
// availCh.gate[] goes high Xfader fades in, when availCh.gate[] goes low
|
|
@@ -5825,6 +5830,8 @@ typedef struct
|
5825
|
5830
|
unsigned baseDisInAvId;
|
5826
|
5831
|
unsigned baseGateOutAvId;
|
5827
|
5832
|
bool* stateArray;
|
|
5833
|
+ unsigned nextAvailChIdx;
|
|
5834
|
+ unsigned audioCycleCnt;
|
5828
|
5835
|
} cmDspAvailCh_t;
|
5829
|
5836
|
|
5830
|
5837
|
cmDspInst_t* _cmDspAvailCh_Alloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
|
|
@@ -5864,11 +5871,13 @@ cmDspInst_t* _cmDspAvailCh_Alloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig
|
5864
|
5871
|
|
5865
|
5872
|
p->baseDisInAvId = baseDisInAvId;
|
5866
|
5873
|
p->baseGateOutAvId = baseGateOutAvId;
|
|
5874
|
+ p->nextAvailChIdx = cmInvalidIdx;
|
|
5875
|
+ p->audioCycleCnt = 0;
|
5867
|
5876
|
|
5868
|
5877
|
unsigned i;
|
5869
|
5878
|
for(i=0; i<chCnt; ++i)
|
5870
|
5879
|
{
|
5871
|
|
- cmDspSetDefaultBool( ctx, &p->inst, baseDisInAvId+i, false, false );
|
|
5880
|
+ cmDspSetDefaultBool( ctx, &p->inst, baseDisInAvId+i, false, false );
|
5872
|
5881
|
cmDspSetDefaultBool( ctx, &p->inst, baseGateOutAvId+i, false, false );
|
5873
|
5882
|
}
|
5874
|
5883
|
cmDspSetDefaultUInt( ctx, &p->inst, kModeAvId, 0, kExclusiveModeAvId );
|
|
@@ -5884,11 +5893,104 @@ cmDspRC_t _cmDspAvailCh_Free(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
5884
|
5893
|
return kOkDspRC;
|
5885
|
5894
|
}
|
5886
|
5895
|
|
|
5896
|
+cmDspRC_t _cmDspAvailCh_DoReset( cmDspCtx_t* ctx, cmDspInst_t* inst )
|
|
5897
|
+{
|
|
5898
|
+ unsigned i;
|
|
5899
|
+ cmDspAvailCh_t* p = (cmDspAvailCh_t*)inst;
|
|
5900
|
+
|
|
5901
|
+ // ch 0 is the channel receiving parameters
|
|
5902
|
+ cmDspSetUInt(ctx,inst,kChIdxAvId,0);
|
|
5903
|
+
|
|
5904
|
+ for(i=0; i<p->chCnt; ++i)
|
|
5905
|
+ {
|
|
5906
|
+ cmDspSetBool(ctx, inst, p->baseDisInAvId + i, i==0); // disable all channels except ch zero
|
|
5907
|
+ cmDspSetBool(ctx, inst, p->baseGateOutAvId + i, i==0); // enable channel 0
|
|
5908
|
+ }
|
|
5909
|
+
|
|
5910
|
+ p->audioCycleCnt = 0;
|
|
5911
|
+ p->nextAvailChIdx = cmInvalidIdx;
|
|
5912
|
+
|
|
5913
|
+ // transmit reset
|
|
5914
|
+ cmDspSetBool(ctx,inst, kResetAvId, false );
|
|
5915
|
+
|
|
5916
|
+ return kOkDspRC;
|
|
5917
|
+}
|
|
5918
|
+
|
|
5919
|
+
|
5887
|
5920
|
cmDspRC_t _cmDspAvailCh_Reset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
5888
|
5921
|
{
|
5889
|
|
- return cmDspApplyAllDefaults(ctx,inst);
|
|
5922
|
+ cmDspRC_t rc;
|
|
5923
|
+ if((rc = cmDspApplyAllDefaults(ctx,inst)) == kOkDspRC )
|
|
5924
|
+ {
|
|
5925
|
+ rc = _cmDspAvailCh_DoReset(ctx,inst);
|
|
5926
|
+ }
|
|
5927
|
+ return rc;
|
5890
|
5928
|
}
|
5891
|
5929
|
|
|
5930
|
+void _cmDspAvailCh_SetNextAvailCh( cmDspCtx_t* ctx, cmDspInst_t* inst, bool warnFl )
|
|
5931
|
+{
|
|
5932
|
+ cmDspAvailCh_t* p = (cmDspAvailCh_t*)inst;
|
|
5933
|
+ unsigned i;
|
|
5934
|
+
|
|
5935
|
+ if( p->nextAvailChIdx != cmInvalidIdx )
|
|
5936
|
+ return;
|
|
5937
|
+
|
|
5938
|
+ for(i=0; i<p->chCnt; ++i)
|
|
5939
|
+ {
|
|
5940
|
+ // the channel's active state is held in the 'dis' variable.
|
|
5941
|
+ bool activeFl = cmDspBool(inst,p->baseDisInAvId+i);
|
|
5942
|
+
|
|
5943
|
+ // if ch[i] is the first avail inactive channel
|
|
5944
|
+ if( !activeFl )
|
|
5945
|
+ {
|
|
5946
|
+ p->nextAvailChIdx = i; // set the next available channel
|
|
5947
|
+ break;
|
|
5948
|
+ }
|
|
5949
|
+
|
|
5950
|
+ }
|
|
5951
|
+
|
|
5952
|
+ // if no available channels were found
|
|
5953
|
+ if( p->nextAvailChIdx == cmInvalidIdx && warnFl )
|
|
5954
|
+ cmDspInstErr(ctx,inst,kInvalidStateDspRC,"No available channels exist.");
|
|
5955
|
+ else
|
|
5956
|
+ {
|
|
5957
|
+ // Notify the external world which channel is to be used next.
|
|
5958
|
+ // This allows routers which are switching parameters between
|
|
5959
|
+ // xfade channels to switch new parameter values to go to the
|
|
5960
|
+ // next available channel rather than the current channel.
|
|
5961
|
+ // The next available channel will then be faded up with the
|
|
5962
|
+ // new parameters on the next trigger command.
|
|
5963
|
+ cmDspSetUInt(ctx,inst,kChIdxAvId,p->nextAvailChIdx);
|
|
5964
|
+ }
|
|
5965
|
+}
|
|
5966
|
+
|
|
5967
|
+cmDspRC_t _cmDspAvailCh_Exec( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
|
5968
|
+{
|
|
5969
|
+ cmDspRC_t rc = kOkDspRC;
|
|
5970
|
+ cmDspAvailCh_t* p = (cmDspAvailCh_t*)inst;
|
|
5971
|
+
|
|
5972
|
+ p->audioCycleCnt += 1;
|
|
5973
|
+
|
|
5974
|
+ // Setting the next available channel here solves the problem of doing the
|
|
5975
|
+ // first 'ch' output after the program starts executing.
|
|
5976
|
+ // The problem is that 'ch' should be set to 0 for at least the first
|
|
5977
|
+ // execution cycle so that parameters may be set to the initial active channel
|
|
5978
|
+ // during the first cycle. After the first cycle however parameters should be
|
|
5979
|
+ // sent to the next channel which will be faded up. Setting
|
|
5980
|
+ // 'ch' here accomplishes this without relying on an external signal.
|
|
5981
|
+ // Note that we wait until the second cycle because we don't know where
|
|
5982
|
+ // this 'availCh' will be in the execution cycle relative to other processors.
|
|
5983
|
+ // If it is at the beginning then other processors that might be setting
|
|
5984
|
+ // initial parameters will not have had a chance to run before the
|
|
5985
|
+ // 'ch' change. Waiting unitl the second cycle guarantees that all the
|
|
5986
|
+ // other processors had at least one chance to run.
|
|
5987
|
+ if( p->audioCycleCnt == 2 )
|
|
5988
|
+ {
|
|
5989
|
+ _cmDspAvailCh_SetNextAvailCh(ctx,inst,true);
|
|
5990
|
+ }
|
|
5991
|
+
|
|
5992
|
+ return rc;
|
|
5993
|
+}
|
5892
|
5994
|
|
5893
|
5995
|
cmDspRC_t _cmDspAvailCh_Recv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
5894
|
5996
|
{
|
|
@@ -5897,79 +5999,53 @@ cmDspRC_t _cmDspAvailCh_Recv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
5897
|
5999
|
|
5898
|
6000
|
bool exclModeFl = cmDspUInt(inst, kModeAvId ) == kExclusiveModeAvId;
|
5899
|
6001
|
|
|
6002
|
+ // if this is a reset
|
5900
|
6003
|
if( evt->dstVarId == kResetAvId )
|
5901
|
6004
|
{
|
5902
|
|
- unsigned i;
|
5903
|
|
-
|
5904
|
|
- cmDspSetUInt(ctx,inst,kChIdxAvId,0);
|
5905
|
|
-
|
5906
|
|
- for(i=0; i<p->chCnt; ++i)
|
5907
|
|
- {
|
5908
|
|
- bool fl = i==0;
|
5909
|
|
- cmDspSetBool(ctx, inst, p->baseDisInAvId + i, !fl);
|
5910
|
|
- cmDspSetBool(ctx, inst, p->baseGateOutAvId + i, fl);
|
5911
|
|
- }
|
5912
|
|
-
|
5913
|
|
- cmDspSetBool(ctx,inst, kResetAvId, false );
|
5914
|
|
-
|
5915
|
|
- return rc;
|
|
6005
|
+ return _cmDspAvailCh_DoReset(ctx,inst);
|
5916
|
6006
|
}
|
5917
|
6007
|
|
5918
|
6008
|
// if this is a trigger
|
5919
|
6009
|
if( evt->dstVarId == kTrigAvId )
|
5920
|
6010
|
{
|
5921
|
|
- unsigned i,j=-1;
|
5922
|
|
- bool fl = true;
|
5923
|
|
- for(i=0; i<p->chCnt; ++i)
|
5924
|
|
- {
|
5925
|
|
- // the channel's active state is held in the 'dis' variable.
|
5926
|
|
- bool activeFl = cmDspBool(inst,p->baseDisInAvId+i);
|
5927
|
|
-
|
5928
|
|
- // if ch[i] is the first avail inactive channel
|
5929
|
|
- if( fl && !activeFl )
|
5930
|
|
- {
|
5931
|
|
- // activate the available channel
|
5932
|
|
- //cmDspSetUInt(ctx,inst,kChIdxAvId,j);
|
5933
|
|
- //cmDspSetBool(ctx, inst, p->baseDisInAvId + j, true);
|
5934
|
|
- //cmDspSetBool(ctx, inst, p->baseGateOutAvId + j, true);
|
5935
|
|
-
|
5936
|
|
- j = i;
|
5937
|
|
- fl = false;
|
5938
|
|
- }
|
5939
|
|
-
|
5940
|
|
- // if ch[i] is active - then request that it shutdown
|
5941
|
|
- //if( activeFl && exclModeFl)
|
5942
|
|
- // cmDspSetBool(ctx, inst, p->baseGateOutAvId + i, false);
|
5943
|
|
-
|
5944
|
|
- }
|
5945
|
|
-
|
5946
|
|
- if( j==-1 )
|
5947
|
|
- cmDspInstErr(ctx,inst,kInvalidStateDspRC,"No available channels exist.");
|
|
6011
|
+ // if no available channels were previously found
|
|
6012
|
+ if( p->nextAvailChIdx == cmInvalidIdx )
|
|
6013
|
+ cmDspInstErr(ctx,inst,kInvalidStateDspRC,"There are no available channels to trigger.");
|
5948
|
6014
|
else
|
5949
|
6015
|
{
|
5950
|
|
- // activate the available channel
|
5951
|
|
- cmDspSetUInt(ctx,inst,kChIdxAvId,j);
|
5952
|
|
- cmDspSetBool(ctx, inst, p->baseDisInAvId + j, true);
|
5953
|
|
- cmDspSetBool(ctx, inst, p->baseGateOutAvId + j, true);
|
|
6016
|
+ // indicate that the next channel is no longer available
|
|
6017
|
+ cmDspSetBool(ctx, inst, p->baseDisInAvId + p->nextAvailChIdx, true);
|
|
6018
|
+
|
|
6019
|
+ // raise the gate to start the xfade.
|
|
6020
|
+ cmDspSetBool(ctx, inst, p->baseGateOutAvId + p->nextAvailChIdx, true);
|
5954
|
6021
|
|
5955
|
6022
|
if( exclModeFl )
|
5956
|
6023
|
{
|
|
6024
|
+ unsigned i;
|
5957
|
6025
|
for(i=0; i<p->chCnt; ++i)
|
5958
|
|
- if( i!=j && cmDspBool(inst,p->baseDisInAvId+i) )
|
|
6026
|
+ if( i!=p->nextAvailChIdx && cmDspBool(inst,p->baseDisInAvId+i) )
|
5959
|
6027
|
cmDspSetBool(ctx,inst, p->baseGateOutAvId+i, false );
|
5960
|
6028
|
}
|
|
6029
|
+
|
|
6030
|
+ p->nextAvailChIdx = cmInvalidIdx;
|
|
6031
|
+
|
|
6032
|
+ // It may be possible to know the next avail ch so try to set it here.
|
|
6033
|
+ _cmDspAvailCh_SetNextAvailCh(ctx, inst, false );
|
|
6034
|
+
|
5961
|
6035
|
}
|
5962
|
6036
|
|
5963
|
6037
|
|
5964
|
6038
|
return rc;
|
5965
|
6039
|
}
|
5966
|
6040
|
|
5967
|
|
-
|
5968
|
|
-
|
5969
|
6041
|
// if this is an incoming disable message.
|
5970
|
6042
|
if( p->baseDisInAvId <= evt->dstVarId && evt->dstVarId < p->baseDisInAvId+p->chCnt && cmDsvGetBool(evt->valuePtr) == false)
|
5971
|
|
- {
|
|
6043
|
+ {
|
5972
|
6044
|
cmDspSetEvent(ctx,inst,evt);
|
|
6045
|
+
|
|
6046
|
+ // a channel was disabled so a new channel is available for selection
|
|
6047
|
+ _cmDspAvailCh_SetNextAvailCh(ctx, inst, true );
|
|
6048
|
+
|
5973
|
6049
|
if( !exclModeFl )
|
5974
|
6050
|
cmDspSetBool(ctx, inst, p->baseGateOutAvId + (evt->dstVarId - p->baseDisInAvId), false);
|
5975
|
6051
|
}
|
|
@@ -5984,7 +6060,7 @@ struct cmDspClass_str* cmAvailChClassCons( cmDspCtx_t* ctx )
|
5984
|
6060
|
_cmDspAvailCh_Alloc,
|
5985
|
6061
|
_cmDspAvailCh_Free,
|
5986
|
6062
|
_cmDspAvailCh_Reset,
|
5987
|
|
- NULL,
|
|
6063
|
+ _cmDspAvailCh_Exec,
|
5988
|
6064
|
_cmDspAvailCh_Recv,
|
5989
|
6065
|
NULL,NULL,
|
5990
|
6066
|
"Enable the next availabled channel");
|