| @@ -938,8 +938,7 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 937 unmodified lines |
| 938 | | 938 | |
| 939 | c->invSampleRate = leaf->invSampleRate; | 939 | c->invSampleRate = leaf->invSampleRate; |
| 940 | | 940 | |
| 941 | c->_init = true; | 941 | |
| 942 | c->amp = 1.0f; | | |
| 943 | c->freq = 440.f; | 942 | c->freq = 440.f; |
| 944 | c->lastsyncin = 0.0f; | 943 | c->lastsyncin = 0.0f; |
| 945 | c->sync = 0.0f; | 944 | c->sync = 0.0f; |
| @@ -948,6 +947,12 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 2 unmodified lines |
| 948 | c->waveform = 0.0f; | 947 | c->waveform = 0.0f; |
| 949 | c->_z = 0.0f; | 948 | c->_z = 0.0f; |
| 950 | c->_j = 0; | 949 | c->_j = 0; |
| | 950 | c->_p = 0.0f; /* phase [0, 1) */ |
| | 951 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| | 952 | c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */ |
| | 953 | c->_x = 0.5f; /* temporary output variable */ |
| | 954 | c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| | 955 | |
| 951 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); | 956 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); |
| 952 | } | 957 | } |
| 953 | | 958 | |
| @@ -962,11 +967,11 @@ float tMBPulse_tick(tMBPulse* const osc) · 8 unmodified lines |
| 962 | _tMBPulse* c = *osc; | 967 | _tMBPulse* c = *osc; |
| 963 | | 968 | |
| 964 | int j, k; | 969 | int j, k; |
| 965 | float freq, sync; | 970 | float sync; |
| 966 | float a, b, p, w, x, z, sw; | 971 | float b, p, w, x, z, sw; |
| 967 | | 972 | |
| 968 | sync = c->sync; | 973 | sync = c->sync; |
| 969 | freq = c->freq; | 974 | |
| 970 | p = c->_p; /* phase [0, 1) */ | 975 | p = c->_p; /* phase [0, 1) */ |
| 971 | w = c->_w; /* phase increment */ | 976 | w = c->_w; /* phase increment */ |
| 972 | b = c->_b; /* duty cycle (0, 1) */ | 977 | b = c->_b; /* duty cycle (0, 1) */ |
| @@ -974,30 +979,7 @@ float tMBPulse_tick(tMBPulse* const osc) · 1 unmodified line |
| 974 | z = c->_z; /* low pass filter state */ | 979 | z = c->_z; /* low pass filter state */ |
| 975 | j = c->_j; /* index into buffer _f */ | 980 | j = c->_j; /* index into buffer _f */ |
| 976 | k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ | 981 | k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| 977 | // | 982 | |
| 978 | if (c->_init) { | | |
| 979 | p = 0.0f; | | |
| 980 | | | |
| 981 | w = freq * c->invSampleRate; | | |
| 982 | b = 0.5f * (1.0f + c->waveform ); | | |
| 983 | | | |
| 984 | /* for variable-width rectangular wave, we could do DC compensation with: | | |
| 985 | * x = 1.0f - b; | | |
| 986 | * but that doesn't work well with highly modulated hard sync. Instead, | | |
| 987 | * we keep things in the range [-0.5f, 0.5f]. */ | | |
| 988 | x = 0.5f; | | |
| 989 | /* if we valued alias-free startup over low startup time, we could do: | | |
| 990 | * p -= w; | | |
| 991 | * place_step_dd(_f, j, 0.0f, w, 0.5f); */ | | |
| 992 | k = 0; | | |
| 993 | c->_init = false; | | |
| 994 | } | | |
| 995 | // | | |
| 996 | // a = 0.2 + 0.8 * vco->_port [FILT]; | | |
| 997 | a = 0.5f; // when a = 1, LPfilter is disabled | | |
| 998 | | | |
| 999 | w = freq * c->invSampleRate; | | |
| 1000 | b = 0.5f * (1.0f + c->waveform); | | |
| 1001 | | 983 | |
| 1002 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; | 984 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| 1003 | | 985 | |
| @@ -1163,8 +1145,8 @@ float tMBPulse_tick(tMBPulse* const osc) · 159 unmodified lines |
| 1163 | } | 1145 | } |
| 1164 | c->_f[j + DD_SAMPLE_DELAY] += x; | 1146 | c->_f[j + DD_SAMPLE_DELAY] += x; |
| 1165 | | 1147 | |
| 1166 | z += a * (c->_f[j] - z); | 1148 | z += 0.5f * (c->_f[j] - z); |
| 1167 | c->out = c->amp * z; | 1149 | c->out = z; |
| 1168 | | 1150 | |
| 1169 | if (++j == FILLEN) | 1151 | if (++j == FILLEN) |
| 1170 | { | 1152 | { |
| @@ -1188,6 +1170,7 @@ void tMBPulse_setFreq(tMBPulse* const osc, float f) · 17 unmodified lines |
| 1188 | { | 1170 | { |
| 1189 | _tMBPulse* c = *osc; | 1171 | _tMBPulse* c = *osc; |
| 1190 | c->freq = f; | 1172 | c->freq = f; |
| | 1173 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| 1191 | } | 1174 | } |
| 1192 | | 1175 | |
| 1193 | void tMBPulse_setWidth(tMBPulse* const osc, float w) | 1176 | void tMBPulse_setWidth(tMBPulse* const osc, float w) |
| @@ -1219,10 +1202,10 @@ void tMBPulse_setPhase(tMBPulse* const osc, float phase) · 25 unmodified lines |
| 1219 | } | 1202 | } |
| 1220 | | 1203 | |
| 1221 | //useful if you have several oscillators so the buffer refill is not synchronized | 1204 | //useful if you have several oscillators so the buffer refill is not synchronized |
| 1222 | void tMBPulse_setBufferOffset(tMBPulse* const osc, int offset) | 1205 | void tMBPulse_setBufferOffset(tMBPulse* const osc, uint32_t offset) |
| 1223 | { | 1206 | { |
| 1224 | _tMBPulse* c = *osc; | 1207 | _tMBPulse* c = *osc; |
| 1225 | offset = LEAF_clip(0,offset, FILLEN-1); | 1208 | offset = offset & (FILLEN-1); |
| 1226 | c->_j = offset; | 1209 | c->_j = offset; |
| 1227 | } | 1210 | } |
| 1228 | | 1211 | |
| @@ -1254,16 +1237,18 @@ void tMBTriangle_initToPool(tMBTriangle* const osc, tMempool* const pool) · 25 unmodified lines |
| 1254 | LEAF* leaf = c->mempool->leaf; | 1237 | LEAF* leaf = c->mempool->leaf; |
| 1255 | | 1238 | |
| 1256 | c->invSampleRate = leaf->invSampleRate; | 1239 | c->invSampleRate = leaf->invSampleRate; |
| 1257 | c->amp = 1.0f; | | |
| 1258 | c->freq = 440.f; | 1240 | c->freq = 440.f; |
| 1259 | c->lastsyncin = 0.0f; | 1241 | c->lastsyncin = 0.0f; |
| 1260 | c->sync = 0.0f; | 1242 | c->sync = 0.0f; |
| 1261 | c->syncdir = 1.0f; | 1243 | c->syncdir = 1.0f; |
| 1262 | c->softsync = 0; | 1244 | c->softsync = 0; |
| 1263 | c->waveform = 0.0f; | 1245 | c->waveform = 0.0f; |
| 1264 | c->_init = true; | | |
| 1265 | c->_z = 0.0f; | 1246 | c->_z = 0.0f; |
| 1266 | c->_j = 0; | 1247 | c->_j = 0; |
| | 1248 | c->_p = 0.0f; /* phase [0, 1) */ |
| | 1249 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| | 1250 | c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */ |
| | 1251 | c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| 1267 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); | 1252 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); |
| 1268 | } | 1253 | } |
| 1269 | | 1254 | |
| @@ -1277,41 +1262,27 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 7 unmodified lines |
| 1277 | { | 1262 | { |
| 1278 | _tMBTriangle* c = *osc; | 1263 | _tMBTriangle* c = *osc; |
| 1279 | | 1264 | |
| 1280 | int j, k, dir; | 1265 | int j, k; |
| 1281 | float freq, sync; | 1266 | float sync; |
| 1282 | float a, b, b1, p, w, sw, x, z; | 1267 | float b, b1, invB, invB1, p, w, sw, z; |
| | 1268 | float x = 0.5f; |
| 1283 | | 1269 | |
| 1284 | sync = c->sync; | 1270 | sync = c->sync; |
| 1285 | dir = c->syncdir; | 1271 | |
| 1286 | freq = c->freq; | 1272 | |
| 1287 | p = c->_p; /* phase [0, 1) */ | 1273 | p = c->_p; /* phase [0, 1) */ |
| 1288 | w = c->_w; /* phase increment */ | 1274 | w = c->_w; /* phase increment */ |
| 1289 | b = c->_b; /* duty cycle (0, 1) */ | 1275 | b = c->_b; /* duty cycle (0, 1) */ |
| | 1276 | invB = 1.0f / b; |
| 1290 | z = c->_z; /* low pass filter state */ | 1277 | z = c->_z; /* low pass filter state */ |
| 1291 | j = c->_j; /* index into buffer _f */ | 1278 | j = c->_j; /* index into buffer _f */ |
| 1292 | k = c->_k; /* output state, 0 = positive slope, 1 = negative slope */ | 1279 | k = c->_k; /* output state, 0 = positive slope, 1 = negative slope */ |
| 1293 | | 1280 | |
| 1294 | if (c->_init) { | | |
| 1295 | // w = (exp2ap (freq[1] + vco->_port[OCTN] + vco->_port[TUNE] + expm[1] * vco->_port[EXPG] + 8.03136) | | |
| 1296 | // + 1e3 * linm[1] * vco->_port[LING]) / SAMPLERATE; | | |
| 1297 | w = freq * c->invSampleRate; | | |
| 1298 | b = 0.5f * (1.0f + c->waveform); | | |
| 1299 | // p = 0.5f * b; | | |
| 1300 | p = 0.f; | | |
| 1301 | /* if we valued alias-free startup over low startup time, we could do: | | |
| 1302 | * p -= w; | | |
| 1303 | * place_slope_dd(_f, j, 0.0f, w, 1.0f / b); */ | | |
| 1304 | k = 0; | | |
| 1305 | c->_init = false; | | |
| 1306 | } | | |
| 1307 | | 1281 | |
| 1308 | // a = 0.2 + 0.8 * vco->_port [FILT]; | 1282 | |
| 1309 | a = 0.5f; // when a = 1, LPfilter is disabled | | |
| 1310 | | | |
| 1311 | w = freq * c->invSampleRate; | | |
| 1312 | b = 0.5f * (1.0f + c->waveform); | 1283 | b = 0.5f * (1.0f + c->waveform); |
| 1313 | b1 = 1.0f - b; | 1284 | b1 = 1.0f - b; |
| 1314 | | 1285 | invB1 = 1.0f / b1; |
| 1315 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; | 1286 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| 1316 | | 1287 | |
| 1317 | sw = w * c->syncdir; | 1288 | sw = w * c->syncdir; |
| @@ -1327,18 +1298,18 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 9 unmodified lines |
| 1327 | /* place any DDs that may have occurred in subsample before reset */ | 1298 | /* place any DDs that may have occurred in subsample before reset */ |
| 1328 | | 1299 | |
| 1329 | if (!k) { | 1300 | if (!k) { |
| 1330 | x = -0.5f + p_at_reset / b; | 1301 | x = -0.5f + p_at_reset * invB; |
| 1331 | if (sw > 0) | 1302 | if (sw > 0) |
| 1332 | { | 1303 | { |
| 1333 | if (p_at_reset >= b) { | 1304 | if (p_at_reset >= b) { |
| 1334 | x = 0.5f - (p_at_reset - b) / b1; | 1305 | x = 0.5f - (p_at_reset - b) * invB1; |
| 1335 | place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b); | 1306 | place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB); |
| 1336 | k = 1; | 1307 | k = 1; |
| 1337 | } | 1308 | } |
| 1338 | if (p_at_reset >= 1.0f) { | 1309 | if (p_at_reset >= 1.0f) { |
| 1339 | p_at_reset -= 1.0f; | 1310 | p_at_reset -= 1.0f; |
| 1340 | x = -0.5f + p_at_reset / b; | 1311 | x = -0.5f + p_at_reset * invB; |
| 1341 | place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1); | 1312 | place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1); |
| 1342 | k = 0; | 1313 | k = 0; |
| 1343 | } | 1314 | } |
| 1344 | } | 1315 | } |
| @@ -1346,43 +1317,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line |
| 1346 | { | 1317 | { |
| 1347 | if (p_at_reset < 0.0f) { | 1318 | if (p_at_reset < 0.0f) { |
| 1348 | p_at_reset += 1.0f; | 1319 | p_at_reset += 1.0f; |
| 1349 | x = 0.5f - (p_at_reset - b) / b1; | 1320 | x = 0.5f - (p_at_reset - b) * invB1; |
| 1350 | place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1); | 1321 | place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1); |
| 1351 | k = 1; | 1322 | k = 1; |
| 1352 | } | 1323 | } |
| 1353 | if (k && p_at_reset < b) { | 1324 | if (k && p_at_reset < b) { |
| 1354 | x = -0.5f + p_at_reset / b; | 1325 | x = -0.5f + p_at_reset * invB; |
| 1355 | place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b); | 1326 | place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB); |
| 1356 | k = 0; | 1327 | k = 0; |
| 1357 | } | 1328 | } |
| 1358 | } | 1329 | } |
| 1359 | } else { | 1330 | } else { |
| 1360 | x = 0.5f - (p_at_reset - b) / b1; | 1331 | x = 0.5f - (p_at_reset - b) * invB1; |
| 1361 | if (sw > 0) | 1332 | if (sw > 0) |
| 1362 | { | 1333 | { |
| 1363 | if (p_at_reset >= 1.0f) { | 1334 | if (p_at_reset >= 1.0f) { |
| 1364 | p_at_reset -= 1.0f; | 1335 | p_at_reset -= 1.0f; |
| 1365 | x = -0.5f + p_at_reset / b; | 1336 | x = -0.5f + p_at_reset * invB; |
| 1366 | place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1); | 1337 | place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1); |
| 1367 | k = 0; | 1338 | k = 0; |
| 1368 | } | 1339 | } |
| 1369 | if (!k && p_at_reset >= b) { | 1340 | if (!k && p_at_reset >= b) { |
| 1370 | x = 0.5f - (p_at_reset - b) / b1; | 1341 | x = 0.5f - (p_at_reset - b) * invB1; |
| 1371 | place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b); | 1342 | place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB); |
| 1372 | k = 1; | 1343 | k = 1; |
| 1373 | } | 1344 | } |
| 1374 | } | 1345 | } |
| 1375 | else if (sw < 0) | 1346 | else if (sw < 0) |
| 1376 | { | 1347 | { |
| 1377 | if (p_at_reset < b) { | 1348 | if (p_at_reset < b) { |
| 1378 | x = -0.5f + p_at_reset / b; | 1349 | x = -0.5f + p_at_reset * invB; |
| 1379 | place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b); | 1350 | place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB); |
| 1380 | k = 0; | 1351 | k = 0; |
| 1381 | } | 1352 | } |
| 1382 | if (p_at_reset < 0.0f) { | 1353 | if (p_at_reset < 0.0f) { |
| 1383 | p_at_reset += 1.0f; | 1354 | p_at_reset += 1.0f; |
| 1384 | x = 0.5f - (p_at_reset - b) / b1; | 1355 | x = 0.5f - (p_at_reset - b) * invB1; |
| 1385 | place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1); | 1356 | place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1); |
| 1386 | k = 1; | 1357 | k = 1; |
| 1387 | } | 1358 | } |
| 1388 | } | 1359 | } |
| @@ -1392,43 +1363,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 3 unmodified lines |
| 1392 | if (sw > 0) | 1363 | if (sw > 0) |
| 1393 | { | 1364 | { |
| 1394 | if (k) | 1365 | if (k) |
| 1395 | place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1); | 1366 | place_slope_dd(c->_f, j, p, sw, invB + invB1); |
| 1396 | place_step_dd(c->_f, j, p, sw, -0.5f - x); | 1367 | place_step_dd(c->_f, j, p, sw, -0.5f - x); |
| 1397 | x = -0.5f + p / b; | 1368 | x = -0.5f + p * invB; |
| 1398 | k = 0; | 1369 | k = 0; |
| 1399 | if (p >= b) { | 1370 | if (p >= b) { |
| 1400 | x = 0.5f - (p - b) / b1; | 1371 | x = 0.5f - (p - b) * invB1; |
| 1401 | place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); | 1372 | place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1402 | k = 1; | 1373 | k = 1; |
| 1403 | } | 1374 | } |
| 1404 | } | 1375 | } |
| 1405 | else if (sw < 0) | 1376 | else if (sw < 0) |
| 1406 | { | 1377 | { |
| 1407 | if (!k) | 1378 | if (!k) |
| 1408 | place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1); | 1379 | place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1); |
| 1409 | place_step_dd(c->_f, j, 1.0f - p, -sw, -0.5f - x); | 1380 | place_step_dd(c->_f, j, 1.0f - p, -sw, -0.5f - x); |
| 1410 | x = 0.5f - (p - b) / b1; | 1381 | x = 0.5f - (p - b) * invB1; |
| 1411 | k = 1; | 1382 | k = 1; |
| 1412 | if (p < b) { | 1383 | if (p < b) { |
| 1413 | x = -0.5f + p / b; | 1384 | x = -0.5f + p * invB; |
| 1414 | place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); | 1385 | place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1415 | k = 0; | 1386 | k = 0; |
| 1416 | } | 1387 | } |
| 1417 | } | 1388 | } |
| 1418 | } else if (!k) { /* normal operation, slope currently up */ | 1389 | } else if (!k) { /* normal operation, slope currently up */ |
| 1419 | | 1390 | |
| 1420 | x = -0.5f + p / b; | 1391 | x = -0.5f + p * invB; |
| 1421 | if (sw > 0) | 1392 | if (sw > 0) |
| 1422 | { | 1393 | { |
| 1423 | if (p >= b) { | 1394 | if (p >= b) { |
| 1424 | x = 0.5f - (p - b) / b1; | 1395 | x = 0.5f - (p - b) * invB1;; |
| 1425 | place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); | 1396 | place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1426 | k = 1; | 1397 | k = 1; |
| 1427 | } | 1398 | } |
| 1428 | if (p >= 1.0f) { | 1399 | if (p >= 1.0f) { |
| 1429 | p -= 1.0f; | 1400 | p -= 1.0f; |
| 1430 | x = -0.5f + p / b; | 1401 | x = -0.5f + p * invB; |
| 1431 | place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1); | 1402 | place_slope_dd(c->_f, j, p, sw, invB + invB1); |
| 1432 | k = 0; | 1403 | k = 0; |
| 1433 | } | 1404 | } |
| 1434 | } | 1405 | } |
| @@ -1436,53 +1407,53 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line |
| 1436 | { | 1407 | { |
| 1437 | if (p < 0.0f) { | 1408 | if (p < 0.0f) { |
| 1438 | p += 1.0f; | 1409 | p += 1.0f; |
| 1439 | x = 0.5f - (p - b) / b1; | 1410 | x = 0.5f - (p - b) * invB1; |
| 1440 | place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1); | 1411 | place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1); |
| 1441 | k = 1; | 1412 | k = 1; |
| 1442 | } | 1413 | } |
| 1443 | if (k && p < b) { | 1414 | if (k && p < b) { |
| 1444 | x = -0.5f + p / b; | 1415 | x = -0.5f + p * invB; |
| 1445 | place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); | 1416 | place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1446 | k = 0; | 1417 | k = 0; |
| 1447 | } | 1418 | } |
| 1448 | } | 1419 | } |
| 1449 | | 1420 | |
| 1450 | } else { /* normal operation, slope currently down */ | 1421 | } else { /* normal operation, slope currently down */ |
| 1451 | | 1422 | |
| 1452 | x = 0.5f - (p - b) / b1; | 1423 | x = 0.5f - (p - b) * invB1; |
| 1453 | if (sw > 0) | 1424 | if (sw > 0) |
| 1454 | { | 1425 | { |
| 1455 | if (p >= 1.0f) { | 1426 | if (p >= 1.0f) { |
| 1456 | p -= 1.0f; | 1427 | p -= 1.0f; |
| 1457 | x = -0.5f + p / b; | 1428 | x = -0.5f + p * invB; |
| 1458 | place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1); | 1429 | place_slope_dd(c->_f, j, p, sw, invB + invB1); |
| 1459 | k = 0; | 1430 | k = 0; |
| 1460 | } | 1431 | } |
| 1461 | if (!k && p >= b) { | 1432 | if (!k && p >= b) { |
| 1462 | x = 0.5f - (p - b) / b1; | 1433 | x = 0.5f - (p - b) * invB1; |
| 1463 | place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); | 1434 | place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1464 | k = 1; | 1435 | k = 1; |
| 1465 | } | 1436 | } |
| 1466 | } | 1437 | } |
| 1467 | else if (sw < 0) | 1438 | else if (sw < 0) |
| 1468 | { | 1439 | { |
| 1469 | if (p < b) { | 1440 | if (p < b) { |
| 1470 | x = -0.5f + p / b; | 1441 | x = -0.5f + p * invB; |
| 1471 | place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); | 1442 | place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1472 | k = 0; | 1443 | k = 0; |
| 1473 | } | 1444 | } |
| 1474 | if (p < 0.0f) { | 1445 | if (p < 0.0f) { |
| 1475 | p += 1.0f; | 1446 | p += 1.0f; |
| 1476 | x = 0.5f - (p - b) / b1; | 1447 | x = 0.5f - (p - b) * invB1; |
| 1477 | place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1); | 1448 | place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1); |
| 1478 | k = 1; | 1449 | k = 1; |
| 1479 | } | 1450 | } |
| 1480 | } | 1451 | } |
| 1481 | } | 1452 | } |
| 1482 | c->_f[j + DD_SAMPLE_DELAY] += x; | 1453 | c->_f[j + DD_SAMPLE_DELAY] += x; |
| 1483 | | 1454 | |
| 1484 | z += a * (c->_f[j] - z); | 1455 | z += 0.5f * (c->_f[j] - z); |
| 1485 | c->out = c->amp * z; | 1456 | c->out = z; |
| 1486 | | 1457 | |
| 1487 | if (++j == FILLEN) | 1458 | if (++j == FILLEN) |
| 1488 | { | 1459 | { |
| @@ -1505,6 +1476,7 @@ void tMBTriangle_setFreq(tMBTriangle* const osc, float f) · 16 unmodified lines |
| 1505 | { | 1476 | { |
| 1506 | _tMBTriangle* c = *osc; | 1477 | _tMBTriangle* c = *osc; |
| 1507 | c->freq = f; | 1478 | c->freq = f; |
| | 1479 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| 1508 | } | 1480 | } |
| 1509 | | 1481 | |
| 1510 | void tMBTriangle_setWidth(tMBTriangle* const osc, float w) | 1482 | void tMBTriangle_setWidth(tMBTriangle* const osc, float w) |
| @@ -1542,10 +1514,10 @@ void tMBTriangle_setSyncMode(tMBTriangle* const osc, int hardOrSoft) · 31 unmodified lines |
| 1542 | } | 1514 | } |
| 1543 | | 1515 | |
| 1544 | //useful if you have several oscillators so the buffer refill is not synchronized | 1516 | //useful if you have several oscillators so the buffer refill is not synchronized |
| 1545 | void tMBTriangle_setBufferOffset(tMBTriangle* const osc, int offset) | 1517 | void tMBTriangle_setBufferOffset(tMBTriangle* const osc, uint32_t offset) |
| 1546 | { | 1518 | { |
| 1547 | _tMBTriangle* c = *osc; | 1519 | _tMBTriangle* c = *osc; |
| 1548 | offset = LEAF_clip(0,offset, FILLEN-1); | 1520 | offset = offset & (FILLEN-1); |
| 1549 | c->_j = offset; | 1521 | c->_j = offset; |
| 1550 | } | 1522 | } |
| 1551 | | 1523 | |
| @@ -1571,8 +1543,6 @@ void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const pool) · 19 unmodified lines |
| 1571 | LEAF* leaf = c->mempool->leaf; | 1543 | LEAF* leaf = c->mempool->leaf; |
| 1572 | | 1544 | |
| 1573 | c->invSampleRate = leaf->invSampleRate; | 1545 | c->invSampleRate = leaf->invSampleRate; |
| 1574 | c->_init = true; | | |
| 1575 | c->amp = 1.0f; | | |
| 1576 | c->freq = 440.f; | 1546 | c->freq = 440.f; |
| 1577 | c->lastsyncin = 0.0f; | 1547 | c->lastsyncin = 0.0f; |
| 1578 | c->sync = 0.0f; | 1548 | c->sync = 0.0f; |
| @@ -1580,6 +1550,9 @@ void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const pool) · 1 unmodified line |
| 1580 | c->softsync = 0; | 1550 | c->softsync = 0; |
| 1581 | c->_z = 0.0f; | 1551 | c->_z = 0.0f; |
| 1582 | c->_j = 0; | 1552 | c->_j = 0; |
| | 1553 | c->_p = 0.0f; /* phase [0, 1) */ |
| | 1554 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| | 1555 | |
| 1583 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); | 1556 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); |
| 1584 | } | 1557 | } |
| 1585 | | 1558 | |
| @@ -1594,45 +1567,30 @@ float tMBSaw_tick(tMBSaw* const osc) · 8 unmodified lines |
| 1594 | _tMBSaw* c = *osc; | 1567 | _tMBSaw* c = *osc; |
| 1595 | | 1568 | |
| 1596 | int j; | 1569 | int j; |
| 1597 | float freq, sync; | 1570 | float sync; |
| 1598 | float a, p, w, sw, z; | 1571 | float p, w, sw, z; |
| 1599 | | 1572 | |
| 1600 | sync = c->sync; | 1573 | sync = c->sync; |
| 1601 | freq = c->freq; | 1574 | |
| 1602 | | 1575 | |
| 1603 | p = c->_p; /* phase [0, 1) */ | 1576 | p = c->_p; /* phase [0, 1) */ |
| 1604 | w = c->_w; /* phase increment */ | 1577 | w = c->_w; /* phase increment */ |
| 1605 | z = c->_z; /* low pass filter state */ | 1578 | z = c->_z; /* low pass filter state */ |
| 1606 | j = c->_j; /* index into buffer _f */ | 1579 | j = c->_j; /* index into buffer _f */ |
| 1607 | | 1580 | |
| 1608 | if (c->_init) { | | |
| 1609 | // p = 0.5f; | | |
| 1610 | p = 0.f; | | |
| 1611 | w = freq * c->invSampleRate; | | |
| 1612 | | | |
| 1613 | /* if we valued alias-free startup over low startup time, we could do: | | |
| 1614 | * p -= w; | | |
| 1615 | * place_slope_dd(_f, j, 0.0f, w, -1.0f); */ | | |
| 1616 | c->_init = false; | | |
| 1617 | } | | |
| 1618 | | | |
| 1619 | //a = 0.2 + 0.8 * vco->_port [FILT]; | | |
| 1620 | a = 0.5f; // when a = 1, LPfilter is disabled | | |
| 1621 | | | |
| 1622 | w = freq * c->invSampleRate; | | |
| 1623 | | 1581 | |
| 1624 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; | 1582 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| 1625 | // Should insert minblep for softsync? | 1583 | // Should insert minblep for softsync? |
| 1626 | // if (p_at_reset >= 1.0f) { | 1584 | // if (p_at_reset >= 1.0f) { |
| 1627 | // p_at_reset -= (int)p_at_reset; | 1585 | // p_at_reset -= (int)p_at_reset; |
| 1628 | // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f); | 1586 | // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f); |
| 1629 | // } | 1587 | // } |
| 1630 | // if (p_at_reset < 0.0f) { | 1588 | // if (p_at_reset < 0.0f) { |
| 1631 | // p_at_reset += 1.0f - (int)p_at_reset; | 1589 | // p_at_reset += 1.0f - (int)p_at_reset; |
| 1632 | // place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -2.0f); | 1590 | // place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -2.0f); |
| 1633 | // } | 1591 | // } |
| 1634 | // if (sw > 0) place_slope_dd(c->_f, j, p, sw, 2.0f); | 1592 | // if (sw > 0) place_slope_dd(c->_f, j, p, sw, 2.0f); |
| 1635 | // else if (sw < 0) place_slope_dd(c->_f, j, 1.0f - p, -sw, -2.0f); | 1593 | // else if (sw < 0) place_slope_dd(c->_f, j, 1.0f - p, -sw, -2.0f); |
| 1636 | | 1594 | |
| 1637 | sw = w * c->syncdir; | 1595 | sw = w * c->syncdir; |
| 1638 | p += sw - (int)sw; | 1596 | p += sw - (int)sw; |
| @@ -1670,8 +1628,8 @@ float tMBSaw_tick(tMBSaw* const osc) · 31 unmodified lines |
| 1670 | } | 1628 | } |
| 1671 | c->_f[j + DD_SAMPLE_DELAY] += 0.5f - p; | 1629 | c->_f[j + DD_SAMPLE_DELAY] += 0.5f - p; |
| 1672 | | 1630 | |
| 1673 | z += a * (c->_f[j] - z); // LP filtering | 1631 | z += 0.5f * (c->_f[j] - z); // LP filtering |
| 1674 | c->out = c->amp * z; | 1632 | c->out = z; |
| 1675 | | 1633 | |
| 1676 | if (++j == FILLEN) | 1634 | if (++j == FILLEN) |
| 1677 | { | 1635 | { |
| @@ -1692,6 +1650,8 @@ void tMBSaw_setFreq(tMBSaw* const osc, float f) · 14 unmodified lines |
| 1692 | { | 1650 | { |
| 1693 | _tMBSaw* c = *osc; | 1651 | _tMBSaw* c = *osc; |
| 1694 | c->freq = f; | 1652 | c->freq = f; |
| | 1653 | |
| | 1654 | c->_w = c->freq * c->invSampleRate; |
| 1695 | } | 1655 | } |
| 1696 | | 1656 | |
| 1697 | float tMBSaw_sync(tMBSaw* const osc, float value) | 1657 | float tMBSaw_sync(tMBSaw* const osc, float value) |
| @@ -1723,10 +1683,10 @@ void tMBSaw_setSyncMode(tMBSaw* const osc, int hardOrSoft) · 25 unmodified lines |
| 1723 | } | 1683 | } |
| 1724 | | 1684 | |
| 1725 | //useful if you have several oscillators so the buffer refill is not synchronized | 1685 | //useful if you have several oscillators so the buffer refill is not synchronized |
| 1726 | void tMBSaw_setBufferOffset(tMBSaw* const osc, int offset) | 1686 | void tMBSaw_setBufferOffset(tMBSaw* const osc, uint32_t offset) |
| 1727 | { | 1687 | { |
| 1728 | _tMBSaw* c = *osc; | 1688 | _tMBSaw* c = *osc; |
| 1729 | offset = LEAF_clip(0,offset, FILLEN-1); | 1689 | offset = offset & (FILLEN-1); |
| 1730 | c->_j = offset; | 1690 | c->_j = offset; |
| 1731 | } | 1691 | } |
| 1732 | | 1692 | |
| @@ -1737,6 +1697,336 @@ void tMBSaw_setSampleRate(tMBSaw* const osc, float sr) · 4 unmodified lines |
| 1737 | } | 1697 | } |
| 1738 | | 1698 | |
| 1739 | | 1699 | |
| | 1700 | //================================================================================================== |
| | 1701 | |
| | 1702 | void tMBSawPulse_init(tMBSawPulse* const osc, LEAF* const leaf) |
| | 1703 | { |
| | 1704 | tMBSawPulse_initToPool(osc, &leaf->mempool); |
| | 1705 | } |
| | 1706 | |
| | 1707 | void tMBSawPulse_initToPool(tMBSawPulse* const osc, tMempool* const pool) |
| | 1708 | { |
| | 1709 | _tMempool* m = *pool; |
| | 1710 | _tMBSawPulse* c = *osc = (_tMBSawPulse*) mpool_alloc(sizeof(_tMBSawPulse), m); |
| | 1711 | c->mempool = m; |
| | 1712 | LEAF* leaf = c->mempool->leaf; |
| | 1713 | |
| | 1714 | c->invSampleRate = leaf->invSampleRate; |
| | 1715 | c->freq = 440.f; |
| | 1716 | c->lastsyncin = 0.0f; |
| | 1717 | c->sync = 0.0f; |
| | 1718 | c->syncdir = 1.0f; |
| | 1719 | c->softsync = 0; |
| | 1720 | c->waveform = 0.0f; |
| | 1721 | c->_z = 0.0f; |
| | 1722 | c->_j = 0; |
| | 1723 | c->_p = 0.0f; /* phase [0, 1) */ |
| | 1724 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| | 1725 | c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */ |
| | 1726 | c->_x = 0.5f; /* temporary output variable */ |
| | 1727 | c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| | 1728 | |
| | 1729 | memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float)); |
| | 1730 | } |
| | 1731 | |
| | 1732 | void tMBSawPulse_free(tMBSawPulse* const osc) |
| | 1733 | { |
| | 1734 | _tMBSawPulse* c = *osc; |
| | 1735 | mpool_free((char*)c, c->mempool); |
| | 1736 | } |
| | 1737 | |
| | 1738 | |
| | 1739 | |
| | 1740 | |
| | 1741 | |
| | 1742 | |
| | 1743 | |
| | 1744 | float tMBSawPulse_tick(tMBSawPulse* const osc) |
| | 1745 | { |
| | 1746 | _tMBSawPulse* c = *osc; |
| | 1747 | |
| | 1748 | int j, k; |
| | 1749 | float sync; |
| | 1750 | float b, p, w, x, z, sw; |
| | 1751 | float shape = c->shape; |
| | 1752 | float sawShape = 1.0f - c->shape; |
| | 1753 | sync = c->sync; |
| | 1754 | p = c->_p; /* phase [0, 1) */ |
| | 1755 | w = c->_w; /* phase increment */ |
| | 1756 | b = c->_b; /* duty cycle (0, 1) */ |
| | 1757 | x = c->_x; /* temporary output variable */ |
| | 1758 | z = c->_z; /* low pass filter state */ |
| | 1759 | j = c->_j; /* index into buffer _f */ |
| | 1760 | k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| | 1761 | |
| | 1762 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| | 1763 | |
| | 1764 | sw = w * c->syncdir; |
| | 1765 | p += sw - (int)sw; |
| | 1766 | |
| | 1767 | if (sync > 0.0f && c->softsync == 0) |
| | 1768 | { /* sync to master */ |
| | 1769 | float eof_offset = sync * sw; |
| | 1770 | float p_at_reset = p - eof_offset; |
| | 1771 | |
| | 1772 | if (sw > 0) p = eof_offset; |
| | 1773 | else if (sw < 0) p = 1.0f - eof_offset; |
| | 1774 | |
| | 1775 | //pulse stuff |
| | 1776 | /* place any DDs that may have occurred in subsample before reset */ |
| | 1777 | if (!k) |
| | 1778 | { |
| | 1779 | if (sw > 0) |
| | 1780 | { |
| | 1781 | if (p_at_reset >= b) |
| | 1782 | { |
| | 1783 | place_step_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f * shape); |
| | 1784 | k = 1; |
| | 1785 | x = -0.5f; |
| | 1786 | } |
| | 1787 | if (p_at_reset >= 1.0f) |
| | 1788 | { |
| | 1789 | p_at_reset -= 1.0f; |
| | 1790 | place_step_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f); |
| | 1791 | k = 0; |
| | 1792 | x = 0.5f; |
| | 1793 | } |
| | 1794 | } |
| | 1795 | else if (sw < 0) |
| | 1796 | { |
| | 1797 | if (p_at_reset < 0.0f) |
| | 1798 | { |
| | 1799 | p_at_reset += 1.0f; |
| | 1800 | place_step_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -1.0f); |
| | 1801 | k = 1; |
| | 1802 | x = -0.5f; |
| | 1803 | } |
| | 1804 | if (k && p_at_reset < b) |
| | 1805 | { |
| | 1806 | place_step_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, 1.0f * shape); |
| | 1807 | k = 0; |
| | 1808 | x = 0.5f; |
| | 1809 | } |
| | 1810 | } |
| | 1811 | } |
| | 1812 | else |
| | 1813 | { |
| | 1814 | if (sw > 0) |
| | 1815 | { |
| | 1816 | if (p_at_reset >= 1.0f) |
| | 1817 | { |
| | 1818 | p_at_reset -= 1.0f; |
| | 1819 | place_step_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f); |
| | 1820 | k = 0; |
| | 1821 | x = 0.5f; |
| | 1822 | } |
| | 1823 | if (!k && p_at_reset >= b) |
| | 1824 | { |
| | 1825 | place_step_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f * shape); |
| | 1826 | k = 1; |
| | 1827 | x = -0.5f; |
| | 1828 | } |
| | 1829 | } |
| | 1830 | else if (sw < 0) |
| | 1831 | { |
| | 1832 | if (p_at_reset < b) |
| | 1833 | { |
| | 1834 | place_step_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, 1.0f * shape); |
| | 1835 | k = 0; |
| | 1836 | x = 0.5f; |
| | 1837 | } |
| | 1838 | if (p_at_reset < 0.0f) |
| | 1839 | { |
| | 1840 | p_at_reset += 1.0f; |
| | 1841 | place_step_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -1.0f); |
| | 1842 | k = 1; |
| | 1843 | x = -0.5f; |
| | 1844 | } |
| | 1845 | } |
| | 1846 | } |
| | 1847 | |
| | 1848 | |
| | 1849 | /* now place reset DD for pulse */ |
| | 1850 | if (sw > 0) |
| | 1851 | { |
| | 1852 | if (k) { |
| | 1853 | place_step_dd(c->_f, j, p, sw, 1.0f * shape); |
| | 1854 | k = 0; |
| | 1855 | x = 0.5f; |
| | 1856 | } |
| | 1857 | if (p >= b) { |
| | 1858 | place_step_dd(c->_f, j, p - b, sw, -1.0f * shape); |
| | 1859 | k = 1; |
| | 1860 | x = -0.5f; |
| | 1861 | } |
| | 1862 | } |
| | 1863 | else if (sw < 0) |
| | 1864 | { |
| | 1865 | if (!k) { |
| | 1866 | place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f * shape); |
| | 1867 | k = 1; |
| | 1868 | x = -0.5f; |
| | 1869 | } |
| | 1870 | if (p < b) { |
| | 1871 | place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape); |
| | 1872 | k = 0; |
| | 1873 | x = 0.5f; |
| | 1874 | } |
| | 1875 | } |
| | 1876 | /* now place reset DD for saw*/ |
| | 1877 | if (sw > 0) |
| | 1878 | place_step_dd(c->_f, j, p, sw, p_at_reset * sawShape); |
| | 1879 | else if (sw < 0) |
| | 1880 | place_step_dd(c->_f, j, 1.0f - p, -sw, -p_at_reset * sawShape); |
| | 1881 | |
| | 1882 | } |
| | 1883 | |
| | 1884 | |
| | 1885 | else if (!k) |
| | 1886 | { /* normal operation for pulse, signal currently high */ |
| | 1887 | |
| | 1888 | if (sw > 0) |
| | 1889 | { |
| | 1890 | if (p >= b) { |
| | 1891 | place_step_dd(c->_f, j, p - b, sw, -1.0f * shape); |
| | 1892 | k = 1; |
| | 1893 | x = -0.5f; |
| | 1894 | } |
| | 1895 | if (p >= 1.0f) { |
| | 1896 | p -= 1.0f; |
| | 1897 | place_step_dd(c->_f, j, p, sw, 1.0f); |
| | 1898 | k = 0; |
| | 1899 | x = 0.5f; |
| | 1900 | } |
| | 1901 | } |
| | 1902 | else if (sw < 0) |
| | 1903 | { |
| | 1904 | if (p < 0.0f) { |
| | 1905 | p += 1.0f; |
| | 1906 | place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f); |
| | 1907 | k = 1; |
| | 1908 | x = -0.5f; |
| | 1909 | } |
| | 1910 | if (k && p < b) { |
| | 1911 | place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape); |
| | 1912 | k = 0; |
| | 1913 | x = 0.5f; |
| | 1914 | } |
| | 1915 | } |
| | 1916 | |
| | 1917 | } else { /* normal operation, signal currently low */ |
| | 1918 | |
| | 1919 | if (sw > 0) |
| | 1920 | { |
| | 1921 | if (p >= 1.0f) { |
| | 1922 | p -= 1.0f; |
| | 1923 | place_step_dd(c->_f, j, p, sw, 1.0f); |
| | 1924 | k = 0; |
| | 1925 | x = 0.5f; |
| | 1926 | } |
| | 1927 | if (!k && p >= b) { |
| | 1928 | place_step_dd(c->_f, j, p - b, sw, -1.0f * shape); |
| | 1929 | k = 1; |
| | 1930 | x = -0.5f; |
| | 1931 | } |
| | 1932 | } |
| | 1933 | else if (sw < 0) |
| | 1934 | { |
| | 1935 | if (p < b) { |
| | 1936 | place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape); |
| | 1937 | k = 0; |
| | 1938 | x = 0.5f; |
| | 1939 | } |
| | 1940 | if (p < 0.0f) { |
| | 1941 | p += 1.0f; |
| | 1942 | place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f); |
| | 1943 | k = 1; |
| | 1944 | x = -0.5f; |
| | 1945 | } |
| | 1946 | } |
| | 1947 | } |
| | 1948 | |
| | 1949 | c->_f[j + DD_SAMPLE_DELAY] += ((0.5f - p) * sawShape); //saw |
| | 1950 | |
| | 1951 | c->_f[j + DD_SAMPLE_DELAY] += (x * shape);//pulse |
| | 1952 | |
| | 1953 | z += 0.5f * (c->_f[j] - z); // LP filtering |
| | 1954 | c->out = z; |
| | 1955 | |
| | 1956 | if (++j == FILLEN) |
| | 1957 | { |
| | 1958 | j = 0; |
| | 1959 | memcpy (c->_f, c->_f + FILLEN, STEP_DD_PULSE_LENGTH * sizeof (float)); |
| | 1960 | memset (c->_f + STEP_DD_PULSE_LENGTH, 0, FILLEN * sizeof (float)); |
| | 1961 | } |
| | 1962 | |
| | 1963 | c->_p = p; |
| | 1964 | c->_w = w; |
| | 1965 | c->_b = b; |
| | 1966 | c->_x = x; |
| | 1967 | c->_z = z; |
| | 1968 | c->_j = j; |
| | 1969 | c->_k = k; |
| | 1970 | |
| | 1971 | return -c->out; |
| | 1972 | } |
| | 1973 | |
| | 1974 | void tMBSawPulse_setFreq(tMBSawPulse* const osc, float f) |
| | 1975 | { |
| | 1976 | _tMBSawPulse* c = *osc; |
| | 1977 | c->freq = f; |
| | 1978 | c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| | 1979 | } |
| | 1980 | |
| | 1981 | float tMBSawPulse_sync(tMBSawPulse* const osc, float value) |
| | 1982 | { |
| | 1983 | _tMBSawPulse* c = *osc; |
| | 1984 | |
| | 1985 | //based on https://github.com/VCVRack/Fundamental/blob/5799ee2a9b21492b42ebcb9b65d5395ef5c1cbe2/src/VCO.cpp#L123 |
| | 1986 | float last = c->lastsyncin; |
| | 1987 | float delta = value - last; |
| | 1988 | float crossing = -last / delta; |
| | 1989 | c->lastsyncin = value; |
| | 1990 | if ((0.f < crossing) && (crossing <= 1.f) && (value >= 0.f)) |
| | 1991 | c->sync = (1.f - crossing) * delta; |
| | 1992 | else c->sync = 0.f; |
| | 1993 | |
| | 1994 | return value; |
| | 1995 | } |
| | 1996 | |
| | 1997 | void tMBSawPulse_setPhase(tMBSawPulse* const osc, float phase) |
| | 1998 | { |
| | 1999 | _tMBSawPulse* c = *osc; |
| | 2000 | c->_p = phase; |
| | 2001 | } |
| | 2002 | |
| | 2003 | void tMBSawPulse_setShape(tMBSawPulse* const osc, float shape) |
| | 2004 | { |
| | 2005 | _tMBSawPulse* c = *osc; |
| | 2006 | c->shape = shape; |
| | 2007 | } |
| | 2008 | |
| | 2009 | void tMBSawPulse_setSyncMode(tMBSawPulse* const osc, int hardOrSoft) |
| | 2010 | { |
| | 2011 | _tMBSawPulse* c = *osc; |
| | 2012 | c->softsync = hardOrSoft > 0 ? 1 : 0; |
| | 2013 | } |
| | 2014 | |
| | 2015 | //useful if you have several oscillators so the buffer refill is not synchronized |
| | 2016 | void tMBSawPulse_setBufferOffset(tMBSawPulse* const osc, uint32_t offset) |
| | 2017 | { |
| | 2018 | _tMBSawPulse* c = *osc; |
| | 2019 | offset = offset & (FILLEN-1); |
| | 2020 | c->_j = offset; |
| | 2021 | } |
| | 2022 | |
| | 2023 | void tMBSawPulse_setSampleRate(tMBSawPulse* const osc, float sr) |
| | 2024 | { |
| | 2025 | _tMBSawPulse* c = *osc; |
| | 2026 | c->invSampleRate = 1.0f/sr; |
| | 2027 | } |
| | 2028 | |
| | 2029 | |
| 1740 | // WaveTable | 2030 | // WaveTable |
| 1741 | void tTable_init(tTable* const cy, float* waveTable, int size, LEAF* const leaf) | 2031 | void tTable_init(tTable* const cy, float* waveTable, int size, LEAF* const leaf) |
| 1742 | { | 2032 | { |