History

replaced multiple booleans in ADSR4 with single state variable, and added some functions to tSimplePoly to allow handling of release envelopes

spiricom committed 6 years ago

Commit 6dcc4ae1 parent 64d544f4 files · +325 −235Browse files

Unified · Split

4 files
  1. LEAF/Inc/leaf-envelopes.h +5 −3
  2. LEAF/Inc/leaf-midi.h +16 −8
  3. LEAF/Src/leaf-envelopes.c +178 −202
  4. LEAF/Src/leaf-midi.c +126 −22
LEAF/Inc/leaf-envelopes.h+5−3
@@ -239,8 +239,10 @@ extern "C" { · 238 unmodified lines
239 239
240 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~240 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
241 241
242 /* ADSR 4*/242 //ADSR4
243 typedef struct _tADSR4243
244
245 typedef struct _tADSR4
244 {246 {
245 const float *exp_buff;247 const float *exp_buff;
246 uint32_t buff_size;248 uint32_t buff_size;
@@ -250,7 +252,7 @@ extern "C" { · 3 unmodified lines
250 252
251 float attackInc, decayInc, releaseInc, rampInc;253 float attackInc, decayInc, releaseInc, rampInc;
252 254
253 oBool inAttack, inDecay, inSustain, inRelease, inRamp;255 uint32_t whichStage;
254 256
255 float sustain, gain, rampPeak, releasePeak;257 float sustain, gain, rampPeak, releasePeak;
256 258
LEAF/Inc/leaf-midi.h+16−8
@@ -364,14 +364,6 @@ extern "C" { · 363 unmodified lines
364 //==============================================================================364 //==============================================================================
365 365
366 366
367 // simplified version of poly for more efficiency when we don't need ramps and pitch glide
368 /*!
369 * @defgroup tpoly tPoly
370 * @ingroup midi
371 * @brief An object for polyphonic handling.
372 * @{
373 */
374
375 /* tPoly */367 /* tPoly */
376 typedef struct _tSimplePoly368 typedef struct _tSimplePoly
377 {369 {
@@ -380,6 +372,8 @@ extern "C" { · 2 unmodified lines
380 int numVoices;372 int numVoices;
381 int maxNumVoices;373 int maxNumVoices;
382 int** voices;374 int** voices;
375 int stealing_on;
376 int recover_stolen;
383 377
384 int notes[128][2];378 int notes[128][2];
385 } _tSimplePoly;379 } _tSimplePoly;
@@ -435,6 +429,15 @@ extern "C" { · 49 unmodified lines
435 int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note);429 int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note);
436 430
437 431
432
433 void tSimplePoly_deactivateVoice(tSimplePoly* const polyh, uint8_t voice);
434
435 int tSimplePoly_markPendingNoteOff(tSimplePoly* const polyh, uint8_t note);
436
437
438 //find if there is a voice with that note -- useful for note offs where you want to wait to remove it from the poly until the release phase of the envelope is finished
439 int tSimplePoly_findVoiceAssignedToNote(tSimplePoly* const polyh, uint8_t note);
440
438 //! Set the number of voices available to play notes.441 //! Set the number of voices available to play notes.
439 /*!442 /*!
440 @param poly A pointer to the relevant tPoly.443 @param poly A pointer to the relevant tPoly.
@@ -471,6 +474,11 @@ extern "C" { · 30 unmodified lines
471 474
472 int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice);475 int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice);
473 476
477
478 //this one returns negative one if the voice is inactive
479 int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice);
480
481
474 //! Get the current MIDI velocity of a given voice.482 //! Get the current MIDI velocity of a given voice.
475 /*!483 /*!
476 @param poly A pointer to the relevant tPoly.484 @param poly A pointer to the relevant tPoly.
LEAF/Src/leaf-envelopes.c+178−202
@@ -850,7 +850,7 @@ float tADSR3_tick(tADSR3* const adsrenv) · 849 unmodified lines
850// use this if the size of the big ADSR tables is too much.850// use this if the size of the big ADSR tables is too much.
851void tADSR4_init (tADSR4* const adsrenv, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize)851void tADSR4_init (tADSR4* const adsrenv, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize)
852{852{
853 tADSR4_initToPool (adsrenv, attack, decay, sustain, release, expBuffer, bufferSize, &leaf.mempool);853 tADSR4_initToPool (adsrenv, attack, decay, sustain, release, expBuffer, bufferSize, &leaf.mempool);
854}854}
855 855
856void tADSR4_free(tADSR4* const adsrenv)856void tADSR4_free(tADSR4* const adsrenv)
@@ -887,11 +887,7 @@ void tADSR4_initToPool (tADSR4* const adsrenv, float attack, float decay, · 30 unmodified lines
887 887
888 adsr->next = 0.0f;888 adsr->next = 0.0f;
889 889
890 adsr->inRamp = OFALSE;890 adsr->whichStage = env_idle;
891 adsr->inAttack = OFALSE;
892 adsr->inDecay = OFALSE;
893 adsr->inSustain = OFALSE;
894 adsr->inRelease = OFALSE;
895 891
896 adsr->sustain = sustain;892 adsr->sustain = sustain;
897 893
@@ -916,7 +912,7 @@ void tADSR4_setAttack(tADSR4* const adsrenv, float attack) · 18 unmodified lines
916 912
917 if (attack < 0.0f)913 if (attack < 0.0f)
918 {914 {
919 attack = 0.0f;915 attack = 0.0f;
920 }916 }
921 917
922 adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack;918 adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack;
@@ -928,7 +924,7 @@ void tADSR4_setDecay(tADSR4* const adsrenv, float decay) · 5 unmodified lines
928 924
929 if (decay < 0.0f)925 if (decay < 0.0f)
930 {926 {
931 decay = 0.0f;927 decay = 0.0f;
932 }928 }
933 adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay;929 adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay;
934}930}
@@ -948,7 +944,7 @@ void tADSR4_setRelease(tADSR4* const adsrenv, float release) · 13 unmodified lines
948 944
949 if (release < 0.0f)945 if (release < 0.0f)
950 {946 {
951 release = 0.0f;947 release = 0.0f;
952 }948 }
953 adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release;949 adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release;
954}950}
@@ -966,23 +962,20 @@ void tADSR4_on(tADSR4* const adsrenv, float velocity) · 11 unmodified lines
966{962{
967 _tADSR4* adsr = *adsrenv;963 _tADSR4* adsr = *adsrenv;
968 964
969 if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.965 if (adsr->whichStage != env_idle) // In case ADSR retriggered while it is still happening.
970 {966 {
971 adsr->rampPhase = 0;967 adsr->rampPhase = 0;
972 adsr->inRamp = OTRUE;968 adsr->whichStage = env_ramp;
973 adsr->rampPeak = adsr->next;969 adsr->rampPeak = adsr->next;
974 }970 }
975 else // Normal start.971 else // Normal start.
976 {972 {
977 adsr->inAttack = OTRUE;973 adsr->whichStage = env_attack;
978 }974 }
979 975
980 adsr->attackPhase = 0;976 adsr->attackPhase = 0;
981 adsr->decayPhase = 0;977 adsr->decayPhase = 0;
982 adsr->releasePhase = 0;978 adsr->releasePhase = 0;
983 adsr->inDecay = OFALSE;
984 adsr->inSustain = OFALSE;
985 adsr->inRelease = OFALSE;
986 adsr->gain = velocity;979 adsr->gain = velocity;
987}980}
988 981
@@ -990,146 +983,139 @@ void tADSR4_off(tADSR4* const adsrenv) · 1 unmodified line
990{983{
991 _tADSR4* adsr = *adsrenv;984 _tADSR4* adsr = *adsrenv;
992 985
993 if (adsr->inRelease) return;986 if (adsr->whichStage == env_idle)
994 987 {
995 adsr->inAttack = OFALSE;988 return;
996 adsr->inDecay = OFALSE;989 }
997 adsr->inSustain = OFALSE;990 else
998 adsr->inRelease = OTRUE;991 {
999 992 adsr->whichStage = env_release;
1000 adsr->releasePeak = adsr->next;993 adsr->releasePeak = adsr->next;
994 }
1001}995}
1002 996
1003float tADSR4_tick(tADSR4* const adsrenv)997float tADSR4_tick(tADSR4* const adsrenv)
1004{998{
1005 _tADSR4* adsr = *adsrenv;999 _tADSR4* adsr = *adsrenv;
1006 1000
1007 1001 switch (adsr->whichStage)
1008 if (adsr->inRamp)
1009 {1002 {
1010 if (adsr->rampPhase > adsr->buff_sizeMinusOne)1003 case env_ramp:
1011 {1004 if (adsr->rampPhase > adsr->buff_sizeMinusOne)
1012 adsr->inRamp = OFALSE;1005 {
1013 adsr->inAttack = OTRUE;1006 adsr->whichStage = env_attack;
1014 adsr->next = 0.0f;1007 adsr->next = 0.0f;
1015 }1008 }
1016 else1009 else
1017 {1010 {
1018 uint32_t intPart = (uint32_t)adsr->rampPhase;1011 uint32_t intPart = (uint32_t)adsr->rampPhase;
1019 float floatPart = adsr->rampPhase - intPart;1012 float floatPart = adsr->rampPhase - intPart;
1020 float secondValue;1013 float secondValue;
1021 if (adsr->rampPhase + 1.0f > adsr->buff_sizeMinusOne)1014 if (adsr->rampPhase + 1.0f > adsr->buff_sizeMinusOne)
1022 {1015 {
1023 secondValue = 0.0f;1016 secondValue = 0.0f;
1024 }1017 }
1025 else1018 else
1026 {1019 {
1027 secondValue = adsr->exp_buff[(uint32_t)((adsr->rampPhase)+1)];1020 secondValue = adsr->exp_buff[(uint32_t)((adsr->rampPhase)+1)];
1028 }1021 }
1029 adsr->next = adsr->rampPeak * LEAF_interpolation_linear(adsr->exp_buff[(uint32_t)(adsr->rampPhase)], secondValue, floatPart);1022 adsr->next = adsr->rampPeak * LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart);
1030 }1023 }
1031 1024
1032 adsr->rampPhase += adsr->rampInc;1025 adsr->rampPhase += adsr->rampInc;
1033 }1026 break;
1034 1027
1035 if (adsr->inAttack)
1036 {
1037 1028
1038 // If attack done, time to turn around.1029 case env_attack:
1039 if (adsr->attackPhase > adsr->buff_sizeMinusOne)
1040 {
1041 adsr->inDecay = OTRUE;
1042 adsr->inAttack = OFALSE;
1043 adsr->next = adsr->gain;
1044 }
1045 else
1046 {
1047 // do interpolation !
1048 uint32_t intPart = (uint32_t)adsr->attackPhase;
1049 float floatPart = adsr->attackPhase - intPart;
1050 float secondValue;
1051 if (adsr->attackPhase + 1.0f > adsr->buff_sizeMinusOne)
1052 {
1053 secondValue = 0.0f;
1054 }
1055 else
1056 {
1057 secondValue = adsr->exp_buff[(uint32_t)((adsr->attackPhase)+1)];
1058 }
1059
1060 adsr->next = adsr->gain * (1.0f - LEAF_interpolation_linear(adsr->exp_buff[(uint32_t)(adsr->attackPhase)], secondValue, floatPart)); // inverted and backwards to get proper rising exponential shape/perception
1061 }
1062 1030
1063 // Increment ADSR attack.1031 // If attack done, time to turn around.
1064 adsr->attackPhase += adsr->attackInc;1032 if (adsr->attackPhase > adsr->buff_sizeMinusOne)
1033 {
1034 adsr->whichStage = env_decay;
1035 adsr->next = adsr->gain;
1036 }
1037 else
1038 {
1039 // do interpolation !
1040 uint32_t intPart = (uint32_t)adsr->attackPhase;
1041 float floatPart = adsr->attackPhase - intPart;
1042 float secondValue;
1043 if (adsr->attackPhase + 1.0f > adsr->buff_sizeMinusOne)
1044 {
1045 secondValue = 0.0f;
1046 }
1047 else
1048 {
1049 secondValue = adsr->exp_buff[(uint32_t)((adsr->attackPhase)+1)];
1050 }
1051
1052 adsr->next = adsr->gain * (1.0f - LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart)); // inverted and backwards to get proper rising exponential shape/perception
1053 }
1065 1054
1066 }1055 // Increment ADSR attack.
1056 adsr->attackPhase += adsr->attackInc;
1057 break;
1067 1058
1068 if (adsr->inDecay)1059 case env_decay:
1069 {
1070 1060
1071 // If decay done, sustain.1061 // If decay done, sustain.
1072 if (adsr->decayPhase > adsr->buff_sizeMinusOne)1062 if (adsr->decayPhase > adsr->buff_sizeMinusOne)
1073 {1063 {
1074 adsr->inDecay = OFALSE;1064 adsr->whichStage = env_sustain;
1075 adsr->inSustain = OTRUE;1065 adsr->next = adsr->gain * adsr->sustain;
1076 adsr->next = adsr->gain * adsr->sustain;1066 }
1077 }
1078 1067
1079 else1068 else
1080 {1069 {
1081 uint32_t intPart = (uint32_t)adsr->decayPhase;1070 uint32_t intPart = (uint32_t)adsr->decayPhase;
1082 float floatPart = adsr->decayPhase - intPart;1071 float floatPart = adsr->decayPhase - intPart;
1083 float secondValue;1072 float secondValue;
1084 if (adsr->decayPhase + 1.0f > adsr->buff_sizeMinusOne)1073 if (adsr->decayPhase + 1.0f > adsr->buff_sizeMinusOne)
1085 {1074 {
1086 secondValue = 0.0f;1075 secondValue = 0.0f;
1087 }1076 }
1088 else1077 else
1089 {1078 {
1090 secondValue = adsr->exp_buff[(uint32_t)((adsr->decayPhase)+1)];1079 secondValue = adsr->exp_buff[(uint32_t)((adsr->decayPhase)+1)];
1091 }1080 }
1092 float interpValue = (LEAF_interpolation_linear(adsr->exp_buff[(uint32_t)(adsr->decayPhase)], secondValue, floatPart));1081 float interpValue = (LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart));
1093 adsr->next = (adsr->gain * (adsr->sustain + (interpValue * (1.0f - adsr->sustain)))) * adsr->leakFactor; // do interpolation !1082 adsr->next = (adsr->gain * (adsr->sustain + (interpValue * (1.0f - adsr->sustain)))) * adsr->leakFactor; // do interpolation !
1094 }1083 }
1095 1084
1096 // Increment ADSR decay.1085 // Increment ADSR decay.
1097 adsr->decayPhase += adsr->decayInc;1086 adsr->decayPhase += adsr->decayInc;
1098 }1087 break;
1099 1088
1100 if (adsr->inSustain)1089 case env_sustain:
1101 {1090 adsr->next = adsr->next * adsr->leakFactor;
1102 adsr->next = adsr->next * adsr->leakFactor;1091 break;
1103 }
1104 1092
1105 if (adsr->inRelease)1093 case env_release:
1106 {1094 // If release done, finish.
1107 // If release done, finish.1095 if (adsr->releasePhase > adsr->buff_sizeMinusOne)
1108 if (adsr->releasePhase > adsr->buff_sizeMinusOne)1096 {
1109 {1097 adsr->whichStage = env_idle;
1110 adsr->inRelease = OFALSE;1098 adsr->next = 0.0f;
1111 adsr->next = 0.0f;1099 }
1112 }1100 else {
1113 else {1101 uint32_t intPart = (uint32_t)adsr->releasePhase;
1114 uint32_t intPart = (uint32_t)adsr->releasePhase;1102 float floatPart = adsr->releasePhase - intPart;
1115 float floatPart = adsr->releasePhase - intPart;1103 float secondValue;
1116 float secondValue;1104 if (adsr->releasePhase + 1.0f > adsr->buff_sizeMinusOne)
1117 if (adsr->releasePhase + 1.0f > adsr->buff_sizeMinusOne)1105 {
1118 {1106 secondValue = 0.0f;
1119 secondValue = 0.0f;1107 }
1120 }1108 else
1121 else1109 {
1122 {1110 secondValue = adsr->exp_buff[(uint32_t)((adsr->releasePhase)+1)];
1123 secondValue = adsr->exp_buff[(uint32_t)((adsr->releasePhase)+1)];1111 }
1124 }1112 adsr->next = adsr->releasePeak * (LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart)); // do interpolation !
1125 adsr->next = adsr->releasePeak * (LEAF_interpolation_linear(adsr->exp_buff[(uint32_t)(adsr->releasePhase)], secondValue, floatPart)); // do interpolation !1113 }
1126 }
1127 1114
1128 // Increment envelope release;1115 // Increment envelope release;
1129 adsr->releasePhase += adsr->releaseInc;1116 adsr->releasePhase += adsr->releaseInc;
1117 break;
1130 }1118 }
1131
1132
1133 return adsr->next;1119 return adsr->next;
1134}1120}
1135 1121
@@ -1137,87 +1123,77 @@ float tADSR4_tickNoInterp(tADSR4* const adsrenv) · 1 unmodified line
1137{1123{
1138 _tADSR4* adsr = *adsrenv;1124 _tADSR4* adsr = *adsrenv;
1139 1125
1140 1126 switch (adsr->whichStage)
1141 if (adsr->inRamp)
1142 {1127 {
1143 if (adsr->rampPhase > adsr->buff_sizeMinusOne)1128 case env_ramp:
1144 {1129 if (adsr->rampPhase > adsr->buff_sizeMinusOne)
1145 adsr->inRamp = OFALSE;1130 {
1146 adsr->inAttack = OTRUE;1131 adsr->whichStage = env_attack;
1147 adsr->next = 0.0f;1132 adsr->next = 0.0f;
1148 }1133 }
1149 else1134 else
1150 {1135 {
1151 adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)(adsr->rampPhase)];1136 adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
1152 }1137 }
1153
1154 adsr->rampPhase += adsr->rampInc;
1155 }
1156 1138
1157 if (adsr->inAttack)1139 adsr->rampPhase += adsr->rampInc;
1158 {1140 break;
1159 1141
1160 // If attack done, time to turn around.
1161 if (adsr->attackPhase > adsr->buff_sizeMinusOne)
1162 {
1163 adsr->inDecay = OTRUE;
1164 adsr->inAttack = OFALSE;
1165 adsr->next = adsr->gain;
1166 }
1167 else
1168 {
1169 // do interpolation !
1170 adsr->next = adsr->gain * (1.0f - adsr->exp_buff[(uint32_t)(adsr->attackPhase)]); // inverted and backwards to get proper rising exponential shape/perception
1171 }
1172 1142
1173 // Increment ADSR attack.1143 case env_attack:
1174 adsr->attackPhase += adsr->attackInc;
1175 1144
1176 }1145 // If attack done, time to turn around.
1146 if (adsr->attackPhase > adsr->buff_sizeMinusOne)
1147 {
1148 adsr->whichStage = env_decay;
1149 adsr->next = adsr->gain;
1150 }
1151 else
1152 {
1153 adsr->next = adsr->gain * (1.0f - adsr->exp_buff[(uint32_t)adsr->attackPhase]); // inverted and backwards to get proper rising exponential shape/perception
1154 }
1177 1155
1178 if (adsr->inDecay)1156 // Increment ADSR attack.
1179 {1157 adsr->attackPhase += adsr->attackInc;
1158 break;
1180 1159
1181 // If decay done, sustain.1160 case env_decay:
1182 if (adsr->decayPhase > adsr->buff_sizeMinusOne)
1183 {
1184 adsr->inDecay = OFALSE;
1185 adsr->inSustain = OTRUE;
1186 adsr->next = adsr->gain * adsr->sustain;
1187 }
1188 1161
1189 else1162 // If decay done, sustain.
1190 {1163 if (adsr->decayPhase > adsr->buff_sizeMinusOne)
1191 adsr->next = (adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)(adsr->decayPhase)]) * (1.0f - adsr->sustain)))) * adsr->leakFactor; // do interpolation !1164 {
1192 }1165 adsr->whichStage = env_sustain;
1166 adsr->next = adsr->gain * adsr->sustain;
1167 }
1193 1168
1194 // Increment ADSR decay.1169 else
1195 adsr->decayPhase += adsr->decayInc;1170 {
1196 }1171 adsr->next = (adsr->gain * (adsr->sustain + (adsr->exp_buff[(uint32_t)adsr->decayPhase] * (1.0f - adsr->sustain)))) * adsr->leakFactor;
1172 }
1197 1173
1198 if (adsr->inSustain)1174 // Increment ADSR decay.
1199 {1175 adsr->decayPhase += adsr->decayInc;
1200 adsr->next = adsr->next * adsr->leakFactor;1176 break;
1201 }
1202 1177
1203 if (adsr->inRelease)1178 case env_sustain:
1204 {1179 adsr->next = adsr->next * adsr->leakFactor;
1205 // If release done, finish.1180 break;
1206 if (adsr->releasePhase > adsr->buff_sizeMinusOne)
1207 {
1208 adsr->inRelease = OFALSE;
1209 adsr->next = 0.0f;
1210 }
1211 else {
1212 1181
1213 adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)(adsr->releasePhase)]); // do interpolation !1182 case env_release:
1214 }1183 // If release done, finish.
1184 if (adsr->releasePhase > adsr->buff_sizeMinusOne)
1185 {
1186 adsr->whichStage = env_idle;
1187 adsr->next = 0.0f;
1188 }
1189 else {
1190 adsr->next = adsr->releasePeak * adsr->exp_buff[(uint32_t)adsr->releasePhase];
1191 }
1215 1192
1216 // Increment envelope release;1193 // Increment envelope release;
1217 adsr->releasePhase += adsr->releaseInc;1194 adsr->releasePhase += adsr->releaseInc;
1195 break;
1218 }1196 }
1219
1220
1221 return adsr->next;1197 return adsr->next;
1222}1198}
1223 1199
LEAF/Src/leaf-midi.c+126−22
@@ -682,7 +682,8 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 681 unmodified lines
682 682
683 683
684 684
685//tSimplePoly = more efficient implementation without ramps and glide685
686//tSimplePoly = much more efficient implementation without ramps and glide
686 687
687 688
688// SIMPLE POLY689// SIMPLE POLY
@@ -709,7 +710,8 @@ void tSimplePoly_initToPool (tSimplePoly* const polyh, int maxNumV · 20 unmodified lines
709 poly->notes[i][0] = -1;710 poly->notes[i][0] = -1;
710 poly->notes[i][1] = 0;711 poly->notes[i][1] = 0;
711 }712 }
712 713 poly->stealing_on = 1;
714 poly->recover_stolen = 1;
713 poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m);715 poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m);
714 716
715 for (int i = 0; i < poly->maxNumVoices; ++i)717 for (int i = 0; i < poly->maxNumVoices; ++i)
@@ -743,13 +745,11 @@ int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel) · 27 unmodified lines
743 if (tStack_contains(&poly->stack, note) >= 0) return -1;745 if (tStack_contains(&poly->stack, note) >= 0) return -1;
744 else746 else
745 {747 {
746 tStack_add(&poly->stack, note);
747
748 alteredVoice = -1;748 alteredVoice = -1;
749 oBool found = OFALSE;749 oBool found = OFALSE;
750 for (int i = 0; i < poly->numVoices; i++)750 for (int i = 0; i < poly->numVoices; i++)
751 {751 {
752 if (poly->voices[i][0] < 0) // if inactive voice, give this note to voice752 if (poly->voices[i][0] == -1) // if inactive voice, give this note to voice
753 {753 {
754 754
755 found = OTRUE;755 found = OTRUE;
@@ -757,15 +757,37 @@ int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel) · 1 unmodified line
757 poly->voices[i][0] = note;757 poly->voices[i][0] = note;
758 poly->voices[i][1] = vel;758 poly->voices[i][1] = vel;
759 poly->notes[note][0] = i;759 poly->notes[note][0] = i;
760 760 poly->notes[note][1] = vel;
761 poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive)761 poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive)
762 762
763 alteredVoice = i;763 alteredVoice = i;
764 tStack_add(&poly->stack, note);
764 break;765 break;
765 }766 }
766 }767 }
768 if (!found)
769 {
770 //second preference is grabbing one that is in release phase but not finished sounding yet
771 for (int i = 0 ; i < poly->numVoices; i++)
772 {
773 if (poly->voices[i][0] == -2) // if voice is released but still sounding, take over this voice
774 {
767 775
768 if (!found) //steal776 found = OTRUE;
777
778 poly->voices[i][0] = note;
779 poly->voices[i][1] = vel;
780 poly->notes[note][0] = i;
781 poly->notes[note][1] = vel;
782 poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive)
783
784 alteredVoice = i;
785 tStack_add(&poly->stack, note);
786 break;
787 }
788 }
789 }
790 if ((!found) && (poly->stealing_on)) //steal
769 {791 {
770 for (int j = tStack_getSize(&poly->stack) - 1; j >= 0; j--)792 for (int j = tStack_getSize(&poly->stack) - 1; j >= 0; j--)
771 {793 {
@@ -776,14 +798,14 @@ int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel) · 4 unmodified lines
776 oldNote = poly->voices[whichVoice][0];798 oldNote = poly->voices[whichVoice][0];
777 poly->voices[whichVoice][0] = note;799 poly->voices[whichVoice][0] = note;
778 poly->voices[whichVoice][1] = vel;800 poly->voices[whichVoice][1] = vel;
779 poly->notes[oldNote][0] = -1; //mark the stolen voice as inactive (in the second dimension of the notes array)801 poly->notes[oldNote][0] = -3; //mark the stolen voice as stolen (in the second dimension of the notes array)
780 poly->notes[note][0] = whichVoice;802 poly->notes[note][0] = whichVoice;
781 poly->notes[note][1] = vel;803 poly->notes[note][1] = vel;
782 804
783 poly->voices[whichVoice][2] = note;805 poly->voices[whichVoice][2] = note;
784 806
785 alteredVoice = whichVoice;807 alteredVoice = whichVoice;
786 808 tStack_add(&poly->stack, note);
787 break;809 break;
788 }810 }
789 }811 }
@@ -794,17 +816,14 @@ int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel) · 4 unmodified lines
794 816
795 817
796 818
797
798int tSimplePoly_noteOff(tSimplePoly* const polyh, uint8_t note)819int tSimplePoly_noteOff(tSimplePoly* const polyh, uint8_t note)
799{820{
800 _tSimplePoly* poly = *polyh;821 _tSimplePoly* poly = *polyh;
801 int16_t noteToTest = -1;822 int16_t noteToTest = -1;
802 823
803
804 tStack_remove(&poly->stack, note);824 tStack_remove(&poly->stack, note);
805 poly->notes[note][0] = -1;825 poly->notes[note][0] = -1;
806 826
807
808 int deactivatedVoice = -1;827 int deactivatedVoice = -1;
809 for (int i = 0; i < poly->maxNumVoices; i++)828 for (int i = 0; i < poly->maxNumVoices; i++)
810 {829 {
@@ -817,22 +836,100 @@ int tSimplePoly_noteOff(tSimplePoly* const polyh, uint8_t note) · 6 unmodified lines
817 }836 }
818 }837 }
819 838
820 //grab old notes off the stack if there are notes waiting to replace the free voice839 if (poly->recover_stolen)
821 if (deactivatedVoice >= 0)
822 {840 {
823 for (int j = 0; j < tStack_getSize(&poly->stack); ++j)841 //grab old notes off the stack if there are notes waiting to replace the free voice
842 if (deactivatedVoice >= 0)
824 {843 {
825 noteToTest = tStack_get(&poly->stack, j);844 for (int j = 0; j < tStack_getSize(&poly->stack); ++j)
845 {
846 noteToTest = tStack_get(&poly->stack, j);
826 847
827 if (poly->notes[noteToTest][0] < 0) //if there is a stolen note waiting (marked inactive but on the stack)848 if (poly->notes[noteToTest][0] == -3) //if there is a stolen note waiting (marked inactive but on the stack)
849 {
850 poly->voices[deactivatedVoice][0] = noteToTest; //set the newly free voice to use the old stolen note
851 poly->voices[deactivatedVoice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note
852 poly->voices[deactivatedVoice][2] = noteToTest;
853 poly->notes[noteToTest][0] = deactivatedVoice; //mark that it is no longer stolen and is now active
854 return -1;
855 }
856 }
857 }
858 }
859 return deactivatedVoice;
860}
861
862
863void tSimplePoly_deactivateVoice(tSimplePoly* const polyh, uint8_t voice)
864{
865 _tSimplePoly* poly = *polyh;
866
867 if (poly->voices[voice][0] == -2) //only do this if the voice is waiting for deactivation (not already reassigned while waiting)
868 {
869 poly->voices[voice][0] = -1;
870 poly->voices[voice][1] = 0;
871 if (poly->recover_stolen)
872 {
873 //grab old notes off the stack if there are notes waiting to replace the free voice
874 for (int j = 0; j < tStack_getSize(&poly->stack); ++j)
828 {875 {
829 poly->voices[deactivatedVoice][0] = noteToTest; //set the newly free voice to use the old stolen note876 noteToTest = tStack_get(&poly->stack, j);
830 poly->voices[deactivatedVoice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note877
831 poly->voices[deactivatedVoice][2] = noteToTest;878 if (poly->notes[noteToTest][0] == -3) //if there is a stolen note waiting (marked inactive but on the stack)
832 poly->notes[noteToTest][0] = deactivatedVoice; //mark that it is no longer stolen and is now active879 {
833 return -1;880 poly->voices[voice][0] = noteToTest; //set the newly free voice to use the old stolen note
881 poly->voices[voice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note
882 poly->voices[voice][2] = noteToTest;
883 poly->notes[noteToTest][0] = voice; //mark that it is no longer stolen and is now active
884 }
885 }
886 }
887 }
888}
889
890int tSimplePoly_findVoiceAssignedToNote(tSimplePoly* const polyh, uint8_t note)
891{
892 _tSimplePoly* poly = *polyh;
893
894
895 int voiceWithThatNote = -1;
896 for (int i = 0; i < poly->maxNumVoices; i++)
897 {
898 if (poly->voices[i][0] == note)
899 {
900 voiceWithThatNote = i;
901 break;
902 }
903 }
904 return voiceWithThatNote;
905}
906
907
908int tSimplePoly_markPendingNoteOff(tSimplePoly* const polyh, uint8_t note)
909{
910 _tSimplePoly* poly = *polyh;
911 int deactivatedVoice = -1;
912
913 if (tStack_remove(&poly->stack, note))
914
915 {
916
917 poly->notes[note][0] = -2;
918
919
920
921 for (int i = 0; i < poly->maxNumVoices; i++)
922 {
923 if (poly->voices[i][0] == note)
924 {
925 poly->voices[i][0] = -2;
926 poly->voices[i][1] = 0;
927 deactivatedVoice = i;
928 break;
834 }929 }
835 }930 }
931
932
836 }933 }
837 return deactivatedVoice;934 return deactivatedVoice;
838}935}
@@ -863,6 +960,13 @@ int tSimplePoly_getPitch(tSimplePoly* const polyh, uint8_t voice) · 24 unmodified lines
863 return poly->voices[voice][2];960 return poly->voices[voice][2];
864}961}
865 962
963//this one returns negative one if the voice is inactive
964int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice)
965{
966 _tSimplePoly* poly = *polyh;
967 return poly->voices[voice][0];
968}
969
866int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice)970int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice)
867{971{
868 _tSimplePoly* poly = *polyh;972 _tSimplePoly* poly = *polyh;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t