summaryrefslogtreecommitdiff
path: root/mmband/instrument.c
diff options
context:
space:
mode:
Diffstat (limited to 'mmband/instrument.c')
-rw-r--r--mmband/instrument.c108
1 files changed, 107 insertions, 1 deletions
diff --git a/mmband/instrument.c b/mmband/instrument.c
index 96a8952..38c7d43 100644
--- a/mmband/instrument.c
+++ b/mmband/instrument.c
@@ -1,4 +1,110 @@
+#include <math.h>
+#include <stdlib.h>
+
#include <mmband/api/instrument.h>
#include <mmband/api/adsr.h>
-struct instrument { };
+#include <mmband/waves/waveform.h>
+
+struct oscillation {
+ enum osc_type type;
+
+ float frequency;
+ float phase;
+ float amplitude;
+};
+
+struct instrument {
+ struct oscillation carrier;
+ struct oscillation modulator;
+
+ float frequency_ratio;
+};
+
+float osc_tick (struct oscillation *osc, int sample_rate) {
+ float sample = 0.0;
+
+ switch (osc->type) {
+ case OSC_NONE:
+ sample = osc->amplitude * none(osc->phase);
+ break;
+ case OSC_SINE:
+ sample = osc->amplitude * sine(osc->phase);
+ break;
+ case OSC_SQUARE:
+ sample = osc->amplitude * square(osc->phase);
+ break;
+ case OSC_SAW:
+ sample = osc->amplitude * saw(osc->phase);
+ break;
+ case OSC_TRIANGLE:
+ sample = osc->amplitude * triangle(osc->phase);
+ break;
+ }
+
+ osc->phase = fmod(osc->phase + osc->frequency * 2.0 * M_PI / sample_rate, 2.0 * M_PI);
+ return sample;
+}
+
+// Currently default to ring modulation
+// TODO: add others
+float modulate (struct oscillation *carrier, struct oscillation *modulator, int sample_rate) {
+ return osc_tick(carrier, sample_rate) * osc_tick(modulator, sample_rate);
+}
+
+instrument_ref ins_new () {
+ instrument_ref instrument = malloc(sizeof(struct instrument));
+
+ instrument->frequency_ratio = 1.0;
+
+ instrument->carrier.type = OSC_SINE;
+ instrument->carrier.amplitude = 0.0;
+ instrument->carrier.frequency = 0.0;
+ instrument->carrier.phase = 0.0;
+
+ instrument->modulator.type = OSC_SINE;
+ instrument->carrier.amplitude = 0.0;
+ instrument->carrier.frequency = 0.0;
+ instrument->carrier.phase = 0.0;
+
+ return instrument;
+}
+
+void ins_free (instrument_ref instrument) {
+ free(instrument);
+}
+
+void ins_set_carrier (instrument_ref instrument, enum osc_type osc) {
+ instrument->carrier.type = osc;
+ instrument->carrier.amplitude = 0.0;
+ instrument->carrier.frequency = 0.0;
+ instrument->carrier.phase = 0.0;
+}
+
+void ins_set_modulator (instrument_ref instrument, enum osc_type osc) {
+ instrument->modulator.type = osc;
+ instrument->modulator.amplitude = 0.0;
+ instrument->modulator.frequency = 0.0;
+ instrument->modulator.phase = 0.0;
+}
+
+void ins_set_carrier_amplitude (instrument_ref instrument, float amplitude) {
+ instrument->carrier.amplitude = amplitude;
+}
+
+void ins_set_modulator_aplitude (instrument_ref instrument, float amplitude) {
+ instrument->modulator.amplitude = amplitude;
+}
+
+void ins_set_frequency_ratio (instrument_ref instrument, float frequency_ratio) {
+ instrument->frequency_ratio = frequency_ratio;
+}
+
+void ins_set_frequency (instrument_ref instrument, float frequency) {
+ instrument->carrier.frequency = frequency;
+ instrument->modulator.frequency = frequency * instrument->frequency_ratio;
+}
+
+float ins_tick (instrument_ref instrument, int sample_rate) {
+ return modulate(&instrument->carrier, &instrument->modulator, sample_rate);
+}