#include #include #include "sound_server.h" // Naive example of 1-bit audio mixing employing PPM technique // Adrian Scripca struct oscillator { void init(uint16_t sr) { samplerate = sr; } void set_frequency(uint16_t frequency) { samples_per_cycle = samplerate / frequency; // phase = 0; // hard sync } bool tick() { phase = (phase + 1) % samples_per_cycle; return phase < (samples_per_cycle / 2 * duty_cycle / 100); } uint16_t samples_per_cycle; uint16_t duty_cycle = 4; // percentage uint32_t phase = 0; uint16_t samplerate; }; struct synth : sound_producer_1bit { explicit synth(uint16_t samplerate) { for (auto& o : oscs) { o.init(samplerate); } } bool tick() override { return oscs[0].tick() | oscs[1].tick() | oscs[2].tick() | oscs[3].tick(); } void major_chord(float root) { oscs[0].set_frequency(root); oscs[1].set_frequency(root * 5.0f / 4.0f); // major third oscs[2].set_frequency(root * 3.0f / 2.0f); // perfect fifth oscs[3].set_frequency(root * 2.0f); // octave } void minor_chord(float root) { oscs[0].set_frequency(root); oscs[1].set_frequency(root * 6.0f / 5.0f); // minor third oscs[2].set_frequency(root * 3.0f / 2.0f); // perfect fifth oscs[3].set_frequency(root * 2.0f); // octave } oscillator oscs[4]; }; int main(int argc, char* argv[]) { std::cout << "1bit PPM technique example" << std::endl; // setup const uint16_t SampleRate = 44100; synth instrument{SampleRate}; sound_server_1bit sound_server{SampleRate, instrument}; // fool around. Gmaj, Cmaj, Emaj (la bamba) instrument.major_chord(98); SDL_Delay(1000); instrument.major_chord(130.81); SDL_Delay(1000); instrument.major_chord(146.83); SDL_Delay(1000); return 0; }