poly2.c 2.01 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#include "dac.h"
#include "poly2.h"
#include "gate.h"
#include "voice.h"
#include "vibrato.h"
#include "midi.h"
#include "list.h"
#include "notes.h"

static uint8_t playing[NUM_VOICES];
static uint16_t current_bend;

13 14
INIT_LIST(avail, NUM_VOICES);
INIT_LIST(want_play, NUM_NOTES);
15 16 17 18 19 20

void poly2_update_playing(void);

void
poly2_init(void)
{
21 22
	l_flush(want_play);
	l_flush(avail);
Jacob Vosmaer's avatar
Jacob Vosmaer committed
23
	for_each_voice(i) {
24
		playing[i] = NUM_NOTES;
25
		l_push(avail, i);
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
	}

	current_bend = BEND_CENTER;
}

void
poly2_set_pitch(uint8_t v, uint8_t note)
{
	dac_set_note2(v, note, vibrato_detune(), current_bend);
}

void
poly2_note_on(uint8_t note)
{
	if (note >= NUM_NOTES) {
		return; // should never happen
	}

44
	l_append(want_play, note);
45 46 47 48 49 50
	poly2_update_playing();
}

static uint8_t
poly2_is_playing(uint8_t note)
{
Jacob Vosmaer's avatar
Jacob Vosmaer committed
51
	for_each_voice(v) {
52 53 54 55 56 57 58 59 60 61 62
		if (playing[v] == note) {
			return 1;
		}
	}

	return 0;
}

void
poly2_update_playing(void)
{
Jacob Vosmaer's avatar
Jacob Vosmaer committed
63
	for_each_voice(v) {
64
		if ((playing[v] < NUM_NOTES) && !(l_index(want_play, playing[v]) < NUM_VOICES)) {
65 66
			gate_off(v);
			playing[v] = NUM_NOTES;
67
			l_push(avail, v);
68 69 70 71
		}
	}

	uint8_t want_play_i = 0;
72
	for (uint8_t j = want_play->head; (want_play_i < NUM_VOICES) && (j != want_play->sup); want_play_i++, (j = l_succ(want_play, j))) {
73 74 75 76
		if (poly2_is_playing(j)) {
			continue;
		}

77 78
		uint8_t v = l_last(avail);
		if (v == avail->sup) {
79 80 81 82 83 84 85
			// no voices available
			continue;
		}

		poly2_set_pitch(v, j);
		gate_on(v);
		playing[v] = j;
86
		l_delete(avail, v);
87 88 89 90 91 92 93 94 95 96
	}
}

void
poly2_note_off(uint8_t note)
{
	if (note >= NUM_NOTES) {
		return; // should never happen
	}

97
	l_delete(want_play, note);
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	poly2_update_playing();
}

void
poly2_control_change(uint8_t ctl, uint8_t val)
{
	switch (ctl) {
	case CC_MOD_WHEEL:
		vibrato_set_depth(val);
		break;
	case CC_VIB_RATE:
		vibrato_set_rate(val);
		break;
	}
}

void
poly2_pitch_bend(uint16_t bend)
{
	current_bend = bend;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
118
	for_each_voice(v) {
119 120 121 122 123 124 125 126
		poly2_set_pitch(v, playing[v]);
	}
}

void
poly2_update_clock(uint8_t delta)
{
	vibrato_update(delta);
Jacob Vosmaer's avatar
Jacob Vosmaer committed
127
	for_each_voice(v) {
128 129 130
		poly2_set_pitch(v, playing[v]);
	}
}