| @@ -938,8 +938,7 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 937 unmodified lines |
| 938 | 938 | |
| 939 | 939 | c->invSampleRate = leaf->invSampleRate; |
| 940 | 940 | |
| 941 | | − c->_init = true; |
| 942 | | − c->amp = 1.0f; |
| 941 | + |
| 943 | 942 | c->freq = 440.f; |
| 944 | 943 | c->lastsyncin = 0.0f; |
| 945 | 944 | c->sync = 0.0f; |
| @@ -948,6 +947,12 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 2 unmodified lines |
| 948 | 947 | c->waveform = 0.0f; |
| 949 | 948 | c->_z = 0.0f; |
| 950 | 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 | 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 | 967 | _tMBPulse* c = *osc; |
| 963 | 968 | |
| 964 | 969 | int j, k; |
| 965 | | − float freq, sync; |
| 966 | | − float a, b, p, w, x, z, sw; |
| 970 | + float sync; |
| 971 | + float b, p, w, x, z, sw; |
| 967 | 972 | |
| 968 | 973 | sync = c->sync; |
| 969 | | − freq = c->freq; |
| 974 | + |
| 970 | 975 | p = c->_p; /* phase [0, 1) */ |
| 971 | 976 | w = c->_w; /* phase increment */ |
| 972 | 977 | b = c->_b; /* duty cycle (0, 1) */ |
| @@ -974,30 +979,7 @@ float tMBPulse_tick(tMBPulse* const osc) · 1 unmodified line |
| 974 | 979 | z = c->_z; /* low pass filter state */ |
| 975 | 980 | j = c->_j; /* index into buffer _f */ |
| 976 | 981 | k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */ |
| 977 | | − // |
| 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); |
| 982 | + |
| 1001 | 983 | |
| 1002 | 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 | 1146 | c->_f[j + DD_SAMPLE_DELAY] += x; |
| 1165 | 1147 | |
| 1166 | | − z += a * (c->_f[j] - z); |
| 1167 | | − c->out = c->amp * z; |
| 1148 | + z += 0.5f * (c->_f[j] - z); |
| 1149 | + c->out = z; |
| 1168 | 1150 | |
| 1169 | 1151 | if (++j == FILLEN) |
| 1170 | 1152 | { |
| @@ -1188,6 +1170,7 @@ void tMBPulse_setFreq(tMBPulse* const osc, float f) · 17 unmodified lines |
| 1188 | 1170 | { |
| 1189 | 1171 | _tMBPulse* c = *osc; |
| 1190 | 1172 | c->freq = f; |
| 1173 | + c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| 1191 | 1174 | } |
| 1192 | 1175 | |
| 1193 | 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 | 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 | 1207 | _tMBPulse* c = *osc; |
| 1225 | | − offset = LEAF_clip(0,offset, FILLEN-1); |
| 1208 | + offset = offset & (FILLEN-1); |
| 1226 | 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 | 1237 | LEAF* leaf = c->mempool->leaf; |
| 1255 | 1238 | |
| 1256 | 1239 | c->invSampleRate = leaf->invSampleRate; |
| 1257 | | − c->amp = 1.0f; |
| 1258 | 1240 | c->freq = 440.f; |
| 1259 | 1241 | c->lastsyncin = 0.0f; |
| 1260 | 1242 | c->sync = 0.0f; |
| 1261 | 1243 | c->syncdir = 1.0f; |
| 1262 | 1244 | c->softsync = 0; |
| 1263 | 1245 | c->waveform = 0.0f; |
| 1264 | | − c->_init = true; |
| 1265 | 1246 | c->_z = 0.0f; |
| 1266 | 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 | 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 | 1263 | _tMBTriangle* c = *osc; |
| 1279 | 1264 | |
| 1280 | | − int j, k, dir; |
| 1281 | | − float freq, sync; |
| 1282 | | − float a, b, b1, p, w, sw, x, z; |
| 1265 | + int j, k; |
| 1266 | + float sync; |
| 1267 | + float b, b1, invB, invB1, p, w, sw, z; |
| 1268 | + float x = 0.5f; |
| 1283 | 1269 | |
| 1284 | 1270 | sync = c->sync; |
| 1285 | | − dir = c->syncdir; |
| 1286 | | − freq = c->freq; |
| 1271 | + |
| 1272 | + |
| 1287 | 1273 | p = c->_p; /* phase [0, 1) */ |
| 1288 | 1274 | w = c->_w; /* phase increment */ |
| 1289 | 1275 | b = c->_b; /* duty cycle (0, 1) */ |
| 1276 | + invB = 1.0f / b; |
| 1290 | 1277 | z = c->_z; /* low pass filter state */ |
| 1291 | 1278 | j = c->_j; /* index into buffer _f */ |
| 1292 | 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]; |
| 1309 | | − a = 0.5f; // when a = 1, LPfilter is disabled |
| 1310 | | − |
| 1311 | | − w = freq * c->invSampleRate; |
| 1282 | + |
| 1312 | 1283 | b = 0.5f * (1.0f + c->waveform); |
| 1313 | 1284 | b1 = 1.0f - b; |
| 1314 | | − |
| 1285 | + invB1 = 1.0f / b1; |
| 1315 | 1286 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| 1316 | 1287 | |
| 1317 | 1288 | sw = w * c->syncdir; |
| @@ -1327,18 +1298,18 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 9 unmodified lines |
| 1327 | 1298 | /* place any DDs that may have occurred in subsample before reset */ |
| 1328 | 1299 | |
| 1329 | 1300 | if (!k) { |
| 1330 | | − x = -0.5f + p_at_reset / b; |
| 1301 | + x = -0.5f + p_at_reset * invB; |
| 1331 | 1302 | if (sw > 0) |
| 1332 | 1303 | { |
| 1333 | 1304 | if (p_at_reset >= b) { |
| 1334 | | − x = 0.5f - (p_at_reset - b) / b1; |
| 1335 | | − place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b); |
| 1305 | + x = 0.5f - (p_at_reset - b) * invB1; |
| 1306 | + place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB); |
| 1336 | 1307 | k = 1; |
| 1337 | 1308 | } |
| 1338 | 1309 | if (p_at_reset >= 1.0f) { |
| 1339 | 1310 | p_at_reset -= 1.0f; |
| 1340 | | − x = -0.5f + p_at_reset / b; |
| 1341 | | − place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1); |
| 1311 | + x = -0.5f + p_at_reset * invB; |
| 1312 | + place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1); |
| 1342 | 1313 | k = 0; |
| 1343 | 1314 | } |
| 1344 | 1315 | } |
| @@ -1346,43 +1317,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line |
| 1346 | 1317 | { |
| 1347 | 1318 | if (p_at_reset < 0.0f) { |
| 1348 | 1319 | p_at_reset += 1.0f; |
| 1349 | | − x = 0.5f - (p_at_reset - b) / b1; |
| 1350 | | − place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1); |
| 1320 | + x = 0.5f - (p_at_reset - b) * invB1; |
| 1321 | + place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1); |
| 1351 | 1322 | k = 1; |
| 1352 | 1323 | } |
| 1353 | 1324 | if (k && p_at_reset < b) { |
| 1354 | | − x = -0.5f + p_at_reset / b; |
| 1355 | | − place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b); |
| 1325 | + x = -0.5f + p_at_reset * invB; |
| 1326 | + place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB); |
| 1356 | 1327 | k = 0; |
| 1357 | 1328 | } |
| 1358 | 1329 | } |
| 1359 | 1330 | } else { |
| 1360 | | − x = 0.5f - (p_at_reset - b) / b1; |
| 1331 | + x = 0.5f - (p_at_reset - b) * invB1; |
| 1361 | 1332 | if (sw > 0) |
| 1362 | 1333 | { |
| 1363 | 1334 | if (p_at_reset >= 1.0f) { |
| 1364 | 1335 | p_at_reset -= 1.0f; |
| 1365 | | − x = -0.5f + p_at_reset / b; |
| 1366 | | − place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1); |
| 1336 | + x = -0.5f + p_at_reset * invB; |
| 1337 | + place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1); |
| 1367 | 1338 | k = 0; |
| 1368 | 1339 | } |
| 1369 | 1340 | if (!k && p_at_reset >= b) { |
| 1370 | | − x = 0.5f - (p_at_reset - b) / b1; |
| 1371 | | − place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b); |
| 1341 | + x = 0.5f - (p_at_reset - b) * invB1; |
| 1342 | + place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB); |
| 1372 | 1343 | k = 1; |
| 1373 | 1344 | } |
| 1374 | 1345 | } |
| 1375 | 1346 | else if (sw < 0) |
| 1376 | 1347 | { |
| 1377 | 1348 | if (p_at_reset < b) { |
| 1378 | | − x = -0.5f + p_at_reset / b; |
| 1379 | | − place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b); |
| 1349 | + x = -0.5f + p_at_reset * invB; |
| 1350 | + place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB); |
| 1380 | 1351 | k = 0; |
| 1381 | 1352 | } |
| 1382 | 1353 | if (p_at_reset < 0.0f) { |
| 1383 | 1354 | p_at_reset += 1.0f; |
| 1384 | | − x = 0.5f - (p_at_reset - b) / b1; |
| 1385 | | − place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1); |
| 1355 | + x = 0.5f - (p_at_reset - b) * invB1; |
| 1356 | + place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1); |
| 1386 | 1357 | k = 1; |
| 1387 | 1358 | } |
| 1388 | 1359 | } |
| @@ -1392,43 +1363,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 3 unmodified lines |
| 1392 | 1363 | if (sw > 0) |
| 1393 | 1364 | { |
| 1394 | 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 | 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 | 1369 | k = 0; |
| 1399 | 1370 | if (p >= b) { |
| 1400 | | − x = 0.5f - (p - b) / b1; |
| 1401 | | − place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); |
| 1371 | + x = 0.5f - (p - b) * invB1; |
| 1372 | + place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1402 | 1373 | k = 1; |
| 1403 | 1374 | } |
| 1404 | 1375 | } |
| 1405 | 1376 | else if (sw < 0) |
| 1406 | 1377 | { |
| 1407 | 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 | 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 | 1382 | k = 1; |
| 1412 | 1383 | if (p < b) { |
| 1413 | | − x = -0.5f + p / b; |
| 1414 | | − place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); |
| 1384 | + x = -0.5f + p * invB; |
| 1385 | + place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1415 | 1386 | k = 0; |
| 1416 | 1387 | } |
| 1417 | 1388 | } |
| 1418 | 1389 | } else if (!k) { /* normal operation, slope currently up */ |
| 1419 | 1390 | |
| 1420 | | − x = -0.5f + p / b; |
| 1391 | + x = -0.5f + p * invB; |
| 1421 | 1392 | if (sw > 0) |
| 1422 | 1393 | { |
| 1423 | 1394 | if (p >= b) { |
| 1424 | | − x = 0.5f - (p - b) / b1; |
| 1425 | | − place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); |
| 1395 | + x = 0.5f - (p - b) * invB1;; |
| 1396 | + place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1426 | 1397 | k = 1; |
| 1427 | 1398 | } |
| 1428 | 1399 | if (p >= 1.0f) { |
| 1429 | 1400 | p -= 1.0f; |
| 1430 | | − x = -0.5f + p / b; |
| 1431 | | − place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1); |
| 1401 | + x = -0.5f + p * invB; |
| 1402 | + place_slope_dd(c->_f, j, p, sw, invB + invB1); |
| 1432 | 1403 | k = 0; |
| 1433 | 1404 | } |
| 1434 | 1405 | } |
| @@ -1436,53 +1407,53 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line |
| 1436 | 1407 | { |
| 1437 | 1408 | if (p < 0.0f) { |
| 1438 | 1409 | p += 1.0f; |
| 1439 | | − x = 0.5f - (p - b) / b1; |
| 1440 | | − place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1); |
| 1410 | + x = 0.5f - (p - b) * invB1; |
| 1411 | + place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1); |
| 1441 | 1412 | k = 1; |
| 1442 | 1413 | } |
| 1443 | 1414 | if (k && p < b) { |
| 1444 | | − x = -0.5f + p / b; |
| 1445 | | − place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); |
| 1415 | + x = -0.5f + p * invB; |
| 1416 | + place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1446 | 1417 | k = 0; |
| 1447 | 1418 | } |
| 1448 | 1419 | } |
| 1449 | 1420 | |
| 1450 | 1421 | } else { /* normal operation, slope currently down */ |
| 1451 | 1422 | |
| 1452 | | − x = 0.5f - (p - b) / b1; |
| 1423 | + x = 0.5f - (p - b) * invB1; |
| 1453 | 1424 | if (sw > 0) |
| 1454 | 1425 | { |
| 1455 | 1426 | if (p >= 1.0f) { |
| 1456 | 1427 | p -= 1.0f; |
| 1457 | | − x = -0.5f + p / b; |
| 1458 | | − place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1); |
| 1428 | + x = -0.5f + p * invB; |
| 1429 | + place_slope_dd(c->_f, j, p, sw, invB + invB1); |
| 1459 | 1430 | k = 0; |
| 1460 | 1431 | } |
| 1461 | 1432 | if (!k && p >= b) { |
| 1462 | | − x = 0.5f - (p - b) / b1; |
| 1463 | | − place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b); |
| 1433 | + x = 0.5f - (p - b) * invB1; |
| 1434 | + place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB); |
| 1464 | 1435 | k = 1; |
| 1465 | 1436 | } |
| 1466 | 1437 | } |
| 1467 | 1438 | else if (sw < 0) |
| 1468 | 1439 | { |
| 1469 | 1440 | if (p < b) { |
| 1470 | | − x = -0.5f + p / b; |
| 1471 | | − place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b); |
| 1441 | + x = -0.5f + p * invB; |
| 1442 | + place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB); |
| 1472 | 1443 | k = 0; |
| 1473 | 1444 | } |
| 1474 | 1445 | if (p < 0.0f) { |
| 1475 | 1446 | p += 1.0f; |
| 1476 | | − x = 0.5f - (p - b) / b1; |
| 1477 | | − place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1); |
| 1447 | + x = 0.5f - (p - b) * invB1; |
| 1448 | + place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1); |
| 1478 | 1449 | k = 1; |
| 1479 | 1450 | } |
| 1480 | 1451 | } |
| 1481 | 1452 | } |
| 1482 | 1453 | c->_f[j + DD_SAMPLE_DELAY] += x; |
| 1483 | 1454 | |
| 1484 | | − z += a * (c->_f[j] - z); |
| 1485 | | − c->out = c->amp * z; |
| 1455 | + z += 0.5f * (c->_f[j] - z); |
| 1456 | + c->out = z; |
| 1486 | 1457 | |
| 1487 | 1458 | if (++j == FILLEN) |
| 1488 | 1459 | { |
| @@ -1505,6 +1476,7 @@ void tMBTriangle_setFreq(tMBTriangle* const osc, float f) · 16 unmodified lines |
| 1505 | 1476 | { |
| 1506 | 1477 | _tMBTriangle* c = *osc; |
| 1507 | 1478 | c->freq = f; |
| 1479 | + c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| 1508 | 1480 | } |
| 1509 | 1481 | |
| 1510 | 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 | 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 | 1519 | _tMBTriangle* c = *osc; |
| 1548 | | − offset = LEAF_clip(0,offset, FILLEN-1); |
| 1520 | + offset = offset & (FILLEN-1); |
| 1549 | 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 | 1543 | LEAF* leaf = c->mempool->leaf; |
| 1572 | 1544 | |
| 1573 | 1545 | c->invSampleRate = leaf->invSampleRate; |
| 1574 | | − c->_init = true; |
| 1575 | | − c->amp = 1.0f; |
| 1576 | 1546 | c->freq = 440.f; |
| 1577 | 1547 | c->lastsyncin = 0.0f; |
| 1578 | 1548 | c->sync = 0.0f; |
| @@ -1580,6 +1550,9 @@ void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const pool) · 1 unmodified line |
| 1580 | 1550 | c->softsync = 0; |
| 1581 | 1551 | c->_z = 0.0f; |
| 1582 | 1552 | c->_j = 0; |
| 1553 | + c->_p = 0.0f; /* phase [0, 1) */ |
| 1554 | + c->_w = c->freq * c->invSampleRate; /* phase increment */ |
| 1555 | + |
| 1583 | 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 | 1567 | _tMBSaw* c = *osc; |
| 1595 | 1568 | |
| 1596 | 1569 | int j; |
| 1597 | | − float freq, sync; |
| 1598 | | − float a, p, w, sw, z; |
| 1570 | + float sync; |
| 1571 | + float p, w, sw, z; |
| 1599 | 1572 | |
| 1600 | 1573 | sync = c->sync; |
| 1601 | | − freq = c->freq; |
| 1574 | + |
| 1602 | 1575 | |
| 1603 | 1576 | p = c->_p; /* phase [0, 1) */ |
| 1604 | 1577 | w = c->_w; /* phase increment */ |
| 1605 | 1578 | z = c->_z; /* low pass filter state */ |
| 1606 | 1579 | j = c->_j; /* index into buffer _f */ |
| 1607 | | − |
| 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; |
| 1580 | + |
| 1623 | 1581 | |
| 1624 | 1582 | if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir; |
| 1625 | 1583 | // Should insert minblep for softsync? |
| 1626 | | − // if (p_at_reset >= 1.0f) { |
| 1627 | | − // p_at_reset -= (int)p_at_reset; |
| 1628 | | − // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f); |
| 1629 | | − // } |
| 1630 | | − // if (p_at_reset < 0.0f) { |
| 1631 | | − // 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); |
| 1633 | | − // } |
| 1634 | | − // 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); |
| 1584 | + // if (p_at_reset >= 1.0f) { |
| 1585 | + // p_at_reset -= (int)p_at_reset; |
| 1586 | + // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f); |
| 1587 | + // } |
| 1588 | + // if (p_at_reset < 0.0f) { |
| 1589 | + // p_at_reset += 1.0f - (int)p_at_reset; |
| 1590 | + // place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -2.0f); |
| 1591 | + // } |
| 1592 | + // if (sw > 0) place_slope_dd(c->_f, j, p, sw, 2.0f); |
| 1593 | + // else if (sw < 0) place_slope_dd(c->_f, j, 1.0f - p, -sw, -2.0f); |
| 1636 | 1594 | |
| 1637 | 1595 | sw = w * c->syncdir; |
| 1638 | 1596 | p += sw - (int)sw; |
| @@ -1670,8 +1628,8 @@ float tMBSaw_tick(tMBSaw* const osc) · 31 unmodified lines |
| 1670 | 1628 | } |
| 1671 | 1629 | c->_f[j + DD_SAMPLE_DELAY] += 0.5f - p; |
| 1672 | 1630 | |
| 1673 | | − z += a * (c->_f[j] - z); // LP filtering |
| 1674 | | − c->out = c->amp * z; |
| 1631 | + z += 0.5f * (c->_f[j] - z); // LP filtering |
| 1632 | + c->out = z; |
| 1675 | 1633 | |
| 1676 | 1634 | if (++j == FILLEN) |
| 1677 | 1635 | { |
| @@ -1692,6 +1650,8 @@ void tMBSaw_setFreq(tMBSaw* const osc, float f) · 14 unmodified lines |
| 1692 | 1650 | { |
| 1693 | 1651 | _tMBSaw* c = *osc; |
| 1694 | 1652 | c->freq = f; |
| 1653 | + |
| 1654 | + c->_w = c->freq * c->invSampleRate; |
| 1695 | 1655 | } |
| 1696 | 1656 | |
| 1697 | 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 | 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 | 1688 | _tMBSaw* c = *osc; |
| 1729 | | − offset = LEAF_clip(0,offset, FILLEN-1); |
| 1689 | + offset = offset & (FILLEN-1); |
| 1730 | 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 | 2030 | // WaveTable |
| 1741 | 2031 | void tTable_init(tTable* const cy, float* waveTable, int size, LEAF* const leaf) |
| 1742 | 2032 | { |