| 1402 | FastHighpass fasthp_c[2]; |
| 1403 | |
| 1404 | virtual void play(int argc, char ** argv) override |
| 1405 | { |
| 1406 | const auto defaultAudioDeviceConfigurations = GetDefaultAudioDeviceConfiguration(); |
| 1407 | context = lab::MakeRealtimeAudioContext(defaultAudioDeviceConfigurations.second, defaultAudioDeviceConfigurations.first); |
| 1408 | lab::AudioContext& ac = *context.get(); |
| 1409 | |
| 1410 | std::shared_ptr<FunctionNode> grooveBox; |
| 1411 | std::shared_ptr<ADSRNode> envelope; |
| 1412 | |
| 1413 | float songLenSeconds = 12.0f; |
| 1414 | { |
| 1415 | double elapsedTime = 0.; |
| 1416 | |
| 1417 | envelope = std::make_shared<ADSRNode>(ac); |
| 1418 | envelope->set(6.0f, 0.75f, 0.125, 14.0f, 0.0f, songLenSeconds); |
| 1419 | |
| 1420 | float lfo_a, lfo_b, lfo_c; |
| 1421 | float bassWaveform, percussiveWaveform, bassSample; |
| 1422 | float padWaveform, padSample; |
| 1423 | float kickWaveform, kickSample; |
| 1424 | float synthWaveform, synthPercussive, synthDegradedWaveform, synthSample; |
| 1425 | |
| 1426 | grooveBox = std::make_shared<FunctionNode>(ac, 2); |
| 1427 | grooveBox->setFunction([&](ContextRenderLock & r, FunctionNode * self, int channel, float * samples, size_t framesToProcess) { |
| 1428 | float dt = 1.f / r.context()->sampleRate(); // time duration of one sample |
| 1429 | float now = static_cast<float>(self->now()); |
| 1430 | |
| 1431 | int nextMeasure = int((now / 2)) % bassline.size(); |
| 1432 | auto bm = bassline[nextMeasure]; |
| 1433 | |
| 1434 | int nextNote = int((now * 4.f)) % bm.size(); |
| 1435 | float bn = note(bm[nextNote], 0); |
| 1436 | |
| 1437 | auto p = chords[int(now / 4) % chords.size()]; |
| 1438 | |
| 1439 | auto mn = note(melody[int(now * 3.f) % melody.size()], int(2 - (now * 3)) % 4); |
| 1440 | |
| 1441 | for (size_t i = 0; i < framesToProcess; ++i) |
| 1442 | { |
| 1443 | lfo_a = quickSin(2.0f, now); |
| 1444 | lfo_b = quickSin(1.0f / 32.0f, now); |
| 1445 | lfo_c = quickSin(1.0f / 128.0f, now); |
| 1446 | |
| 1447 | // Bass |
| 1448 | bassWaveform = quickSaw(bn, now) * 1.9f + quickSqr(bn / 2.f, now) * 1.0f + quickSin(bn / 2.f, now) * 2.2f + quickSqr(bn * 3.f, now) * 3.f; |
| 1449 | percussiveWaveform = perc(bassWaveform / 3.f, 48.0f, fmod(now, 0.125f), now) * 1.0f; |
| 1450 | bassSample = lp_a[channel].process(1000.f + (lfo_b * 140.f), quickSin(0.5f, now + 0.75f) * 0.2f, percussiveWaveform, r.context()->sampleRate()); |
| 1451 | |
| 1452 | // Pad |
| 1453 | padWaveform = 5.1f * quickSaw(note(p[0], 1), now) + 3.9f * quickSaw(note(p[1], 2), now) + 4.0f * quickSaw(note(p[2], 1), now) + 3.0f * quickSqr(note(p[3], 0), now); |
| 1454 | padSample = 1.0f - ((quickSin(2.0f, now) * 0.28f) + 0.5f) * fasthp_c[channel](0.5f, lp_c[channel].process(1100.f + (lfo_a * 150.f), 0.05f, padWaveform * 0.03f, r.context()->sampleRate())); |
| 1455 | |
| 1456 | // Kick |
| 1457 | kickWaveform = hardClip(0.37f, quickSin(note(7, -1), now)) * 2.0f + hardClip(0.07f, quickSaw(note(7, -1), now * 0.2f)) * 4.00f; |
| 1458 | kickSample = quickSaw(2.f, now) * 0.054f + fastlp_a[channel](240.0f, perc(hardClip(0.6f, kickWaveform), 54.f, fmod(now, 0.5f), now)) * 2.f; |
| 1459 | |
| 1460 | // Synth |
| 1461 | synthWaveform = quickSaw(mn, now + 1.0f) + quickSqr(mn * 2.02f, now) * 0.4f + quickSqr(mn * 3.f, now + 2.f); |
nothing calls this directly
no test coverage detected