74 lines
1.8 KiB
C++
74 lines
1.8 KiB
C++
#include <SDL/SDL.h>
|
|
#include <iostream>
|
|
#include "sound_server.h"
|
|
|
|
// Naive example of 1-bit audio mixing employing PPM technique
|
|
// Adrian Scripca <benishor@gmail.com>
|
|
|
|
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;
|
|
} |