2 Commits

Author SHA1 Message Date
cea20608ea feat: synth operations through single object 2023-06-18 18:29:14 +04:00
a6816e33ca fix: rename oscillator struct 2023-06-18 16:09:30 +04:00
3 changed files with 56 additions and 39 deletions

77
main.c
View File

@@ -16,6 +16,12 @@
// Synth // Synth
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
typedef struct Synth {
OscillatorArray oscillators;
Note current_note;
SynthSound* out_signal;
} Synth;
static int get_semitone_shift_internal(char* root_note, char* target_note) { static int get_semitone_shift_internal(char* root_note, char* target_note) {
char* pitch_classes[12] = char* pitch_classes[12] =
{ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
@@ -68,38 +74,39 @@ int get_semitone_shift(char* target_note) {
return get_semitone_shift_internal("A4", target_note); return get_semitone_shift_internal("A4", target_note);
} }
SynthSound note(int semitone, float beats) { static OscillatorArray init_osc_array() {
float hz = get_hz_by_semitone(semitone); Oscillator first = {
float duration = beats * BEAT_DURATION;
OscillatorParameter first = {
.osc = Square, .osc = Square,
.freq = hz .freq = 440.f
}; };
OscillatorParameter second = { Oscillator* oscArray = malloc(sizeof(Oscillator*) * 1);
.osc = Saw, oscArray[0] = first;
.freq = hz + 0.5
};
OscillatorParameter third = { OscillatorArray oscillators = {
.osc = Saw,
.freq = hz - 1.f
};
OscillatorParameter oscArray[] = { first/*, second, third */};
OscillatorParameterList parameters = {
.array = oscArray, .array = oscArray,
.count = 1 .count = 1
}; };
return freq(duration, parameters); return oscillators;
} }
SynthSound get_note_sound(Note input) { SynthSound note(Synth* synth, int semitone, float beats) {
float hz = get_hz_by_semitone(semitone);
float duration = beats * BEAT_DURATION;
// will change after oscillator starts to be more autonomous
for (size_t i = 0; i < synth->oscillators.count; i++) {
synth->oscillators.array[i].freq = hz;
}
return freq(duration, synth->oscillators);
}
SynthSound get_note_sound(Synth* synth, Note input) {
float length = 1.f / input.length; float length = 1.f / input.length;
int semitone_shift = get_semitone_shift(input.name); int semitone_shift = get_semitone_shift(input.name);
return note(semitone_shift, length); return note(synth, semitone_shift, length);
} }
//------------------------------------------------------- //-------------------------------------------------------
@@ -145,14 +152,22 @@ int main(int argc, char **argv) {
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SeeSynth - v0.1"); InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SeeSynth - v0.1");
SetTargetFPS(60); SetTargetFPS(60);
Note current_note = { //todo: move that variables to Synth declaration
Note g_current_note = {
.length = 1, .length = 1,
.name = malloc(sizeof(char) * 3) .name = malloc(sizeof(char) * 3)
}; };
SynthSound sound = { SynthSound g_sound = {
.sample_count = 0 .sample_count = 0
}; };
Synth synth = {
.current_note = g_current_note,
.out_signal = &g_sound,
.oscillators = init_osc_array()
};
int sound_played_count = 0; int sound_played_count = 0;
float temp_buffer[STREAM_BUFFER_SIZE]; float temp_buffer[STREAM_BUFFER_SIZE];
RingBuffer ring_buffer = ring_buffer_init(STREAM_BUFFER_SIZE); RingBuffer ring_buffer = ring_buffer_init(STREAM_BUFFER_SIZE);
@@ -172,25 +187,26 @@ int main(int argc, char **argv) {
// Update Audio states // Update Audio states
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Fill ring buffer from current sound // Fill ring buffer from current sound
SynthSound* sound = synth.out_signal;
size_t size_for_buffer = 0; size_t size_for_buffer = 0;
if (!ring_buffer.is_full && sound.sample_count != sound_played_count) { if (!ring_buffer.is_full && sound->sample_count != sound_played_count) {
write_log("[INFO] IsFull:%d Samples:%zu Played:%zu\n", write_log("[INFO] IsFull:%d Samples:%zu Played:%zu\n",
ring_buffer.is_full, ring_buffer.is_full,
sound.sample_count, sound->sample_count,
sound_played_count); sound_played_count);
// how many samples need write // how many samples need write
size_t size_to_fill = 0; size_t size_to_fill = 0;
if ((sound.sample_count - sound_played_count) > ring_buffer.size) { if ((sound->sample_count - sound_played_count) > ring_buffer.size) {
size_to_fill = ring_buffer.size; size_to_fill = ring_buffer.size;
} else { } else {
size_to_fill = sound.sample_count - sound_played_count; size_to_fill = sound->sample_count - sound_played_count;
} }
write_log("[INFO] SizeToFill:%zu\n", size_to_fill); write_log("[INFO] SizeToFill:%zu\n", size_to_fill);
for (size_t i = 0; i < size_to_fill; i++) { for (size_t i = 0; i < size_to_fill; i++) {
temp_buffer[i] = sound.samples[i]; temp_buffer[i] = sound->samples[i];
} }
ring_buffer_write(&ring_buffer, temp_buffer, size_to_fill); ring_buffer_write(&ring_buffer, temp_buffer, size_to_fill);
@@ -207,7 +223,7 @@ int main(int argc, char **argv) {
// can try the SetAudioStreamCallback // can try the SetAudioStreamCallback
UpdateAudioStream(synth_stream, temp_buffer, size_to_read); UpdateAudioStream(synth_stream, temp_buffer, size_to_read);
// can overwrite the ring buffer to avoid that // can overwrite the ring buffer to avoid that
if (sound.sample_count == sound_played_count) { if (sound->sample_count == sound_played_count) {
ring_buffer_reset(&ring_buffer); ring_buffer_reset(&ring_buffer);
} }
} }
@@ -215,8 +231,9 @@ int main(int argc, char **argv) {
// Update On Input // Update On Input
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
Note current_note = synth.current_note;
if (detect_note_pressed(&current_note)) { if (detect_note_pressed(&current_note)) {
sound = get_note_sound(current_note); *sound = get_note_sound(&synth, current_note);
sound_played_count = 0; sound_played_count = 0;
write_log("Note played: %s\n", current_note.name); write_log("Note played: %s\n", current_note.name);
} }
@@ -242,7 +259,7 @@ int main(int argc, char **argv) {
SynthSound* sounds = malloc(sizeof(SynthSound) * note_array.count); SynthSound* sounds = malloc(sizeof(SynthSound) * note_array.count);
for (size_t i = 0; i < note_array.count; i++) { for (size_t i = 0; i < note_array.count; i++) {
Note note = note_array.notes[i]; Note note = note_array.notes[i];
sounds[i] = get_note_sound(note); sounds[i] = get_note_sound(&synth, note);
} }
SynthSound song = concat_sounds(sounds, note_array.count); SynthSound song = concat_sounds(sounds, note_array.count);

View File

@@ -46,7 +46,7 @@ static float sawosc(float hz, float x) {
float multiosc(OscillatorGenerationParameter param) { float multiosc(OscillatorGenerationParameter param) {
float osc_sample = 0.f; float osc_sample = 0.f;
for (size_t i = 0; i < param.oscillators.count; i++) { for (size_t i = 0; i < param.oscillators.count; i++) {
OscillatorParameter osc = param.oscillators.array[i]; Oscillator osc = param.oscillators.array[i];
switch (osc.osc) { switch (osc.osc) {
case Sine: case Sine:
osc_sample += sineosc(osc.freq, param.sample); osc_sample += sineosc(osc.freq, param.sample);
@@ -66,7 +66,7 @@ float multiosc(OscillatorGenerationParameter param) {
return osc_sample; return osc_sample;
} }
SynthSound freq(float duration, OscillatorParameterList osc) { SynthSound freq(float duration, OscillatorArray osc) {
SynthSound samples = get_init_samples(duration); SynthSound samples = get_init_samples(duration);
// SynthSound attack = get_attack_samples(); // SynthSound attack = get_attack_samples();

View File

@@ -10,23 +10,23 @@ typedef enum {
Square Square
} OscillatorType; } OscillatorType;
typedef struct OscillatorParameter { typedef struct Oscillator {
OscillatorType osc; OscillatorType osc;
float freq; float freq;
} OscillatorParameter; } Oscillator;
typedef struct OscillatorParameterList { typedef struct OscillatorArray {
OscillatorParameter* array; Oscillator* array;
size_t count; size_t count;
} OscillatorParameterList; } OscillatorArray;
typedef struct OscillatorGenerationParameter { typedef struct OscillatorGenerationParameter {
OscillatorParameterList oscillators; OscillatorArray oscillators;
float sample; float sample;
} OscillatorGenerationParameter; } OscillatorGenerationParameter;
float multiosc(OscillatorGenerationParameter param); float multiosc(OscillatorGenerationParameter param);
SynthSound freq(float duration, OscillatorParameterList osc); SynthSound freq(float duration, OscillatorArray osc);