diff --git a/dats/parser.c b/dats/parser.c index f1a39fd..1f541a9 100644 --- a/dats/parser.c +++ b/dats/parser.c @@ -39,7 +39,7 @@ extern void print_all_nr_t(nr_t *nr); static token_t tok; static symrec_t *staff; static int rule_match = 0; -dats_t *d; +static dats_t *d; /* Returns 0 if success. Non-zero if failed. */ static int parse_notes_rests() { @@ -472,7 +472,7 @@ static symrec_t *parse_pcm16(char *id) { } break; } else if (driver->options[i + 1].option_name == NULL) { - C_ERROR(d, "No such option, %s\n", tok_identifier); + C_ERROR(d, "no such option, '%s'", tok_identifier); return NULL; } } diff --git a/dats/scanner.c b/dats/scanner.c index 3d2fa45..80b0e71 100644 --- a/dats/scanner.c +++ b/dats/scanner.c @@ -150,7 +150,7 @@ symrec_t *symrec_tcpy(symrec_t *const s) { return copy; } -void print_debugging_info(const token_t tok, const dats_t *const d) { +void print_debugging_info(const token_t tok, dats_t *d) { switch (tok) { case TOK_IDENTIFIER: ERROR(", '%s'\n", tok_identifier); @@ -162,6 +162,16 @@ void print_debugging_info(const token_t tok, const dats_t *const d) { ERROR("\n"); } char buff[1000] = {0}; + if (d->scan_line[strlen(d->scan_line)-1] != '\n'){ + int ls = strlen(d->scan_line); + d->scan_line[ls] = '\n'; + d->scan_line[ls+1] = 0; + } + if (d->scan_line[strlen(d->scan_line)-2] != '\r'){ + int ls = strlen(d->scan_line); + memcpy(d->scan_line+(ls-2), d->scan_line+(ls-1), 2); + } + int length = sprintf(buff, " %d | %s", line_token_found, d->scan_line); ERROR("%s", buff); ERROR("%*s\n", column_token_found + (length - (int)strlen(d->scan_line)), diff --git a/dats/scanner.h b/dats/scanner.h index ade446e..68a2f88 100644 --- a/dats/scanner.h +++ b/dats/scanner.h @@ -23,7 +23,7 @@ EXTERN const char *token_t_to_str(const token_t t); EXTERN symrec_t *getsym(const dats_t *const t, char const *const id); EXTERN token_t read_next_tok_cur_dats_t(dats_t *const t); EXTERN void print_all_symrec_t_cur_dats_t(const dats_t *const t); -EXTERN void print_debugging_info(const token_t tok, const dats_t *const d); +EXTERN void print_debugging_info(const token_t tok, dats_t * d); EXTERN int line_token_found; EXTERN int column_token_found; diff --git a/libsynth/s_kpa.c b/libsynth/s_kpa.c index d1e9134..f98b3b0 100644 --- a/libsynth/s_kpa.c +++ b/libsynth/s_kpa.c @@ -45,7 +45,16 @@ static pcm16_t *synth(const symrec_t *restrict staff) { i + total < staff->value.staff.numsamples; i++) { wavetable[cur] = ((wavetable[cur] / 2) + (prev / 2)); - pcm[total + i] += wavetable[cur]; + pcm[total + i] += + (int16_t) + /* simple linear attack and linear decay filter */ + (double)wavetable[cur] * + (i < (uint32_t)nn->attack + ? (double)i / nn->attack + : (i > nn->duration - (uint32_t)nn->release + ? (-(double)i + (double)(nn->duration)) / nn->release + : 1.0)); + //pcm[total + i] += wavetable[cur]; prev = wavetable[cur]; cur++; cur %= (int)(44100.0 / nn->frequency); diff --git a/libsynth/s_sin.c b/libsynth/s_sin.c index 9e980e2..aa1851e 100644 --- a/libsynth/s_sin.c +++ b/libsynth/s_sin.c @@ -13,6 +13,12 @@ static DSOption options[] = { {DSOPTION_FLOAT, "vibrato_magnitude", "Vibrato magnitude", {.floatv = 0}}, {DSOPTION_INT, "attack_type", "Attack type (linear=0, exponential=1)", {.intv = 0}}, {DSOPTION_INT, "decay_type", "Decay type (linear=0, exponential=1)", {.intv = 0}}, + {DSOPTION_INT, "sustain_type", "Sustain type (linear=0, exponential=1)", {.intv = 0}}, + {DSOPTION_INT, "release_type", "Release type (linear=0, exponential=1)", {.intv = 0}}, + {DSOPTION_FLOAT, "attack_exp_coeff", "Attack exponential coefficiant", {.floatv = 0.0}}, + {DSOPTION_FLOAT, "decay_exp_coeff", "Attack exponential coefficiant", {.floatv = 0.0}}, + {DSOPTION_FLOAT, "sustain_exp_coeff", "Attack exponential coefficiant", {.floatv = 0.0}}, + {DSOPTION_FLOAT, "release_exp_coeff", "Decay exponential coefficiant", {.floatv = 0.0}}, /*{DSOPTION_INT, "attack_s", "Attack ending in samples", {.intv = 0}}, {DSOPTION_INT, "decay_s", "Decay begin in samples", {.intv= 0}},*/ {.option_name = NULL} @@ -30,7 +36,38 @@ static void free_string_options(void) { } } +static double linear_attack(double x, double n){ + return x / n; +} + +static double linear_release(double x, double n){ + return x / n; +} + +static double exponential_attack(double x, double n){ + return pow(M_E, x-n); +} +static double exponential_release(double x, double n){ + return pow(M_E, (-x-n)+1.0); +} static pcm16_t *synth(const symrec_t *staff) { + + double (*attack_ret)(double, double) = NULL; + double (*release_ret)(double, double) = NULL; + + switch (options[2].value.intv){ + case 0: attack_ret = linear_attack; break; + case 1: attack_ret = exponential_attack; break; + default: fprintf(stderr, "unknown attack type: %d\n", options[2].value.intv); + return NULL; + } + + switch (options[5].value.intv){ + case 0: release_ret = linear_release; break; + case 1: release_ret = exponential_release; break; + default: fprintf(stderr, "unknown attack type: %d\n", options[5].value.intv); + return NULL; + } int16_t *pcm = calloc(sizeof(int16_t), (size_t)staff->value.staff.numsamples); pcm16_t *pcm_ctx = malloc(sizeof(pcm16_t)); if (pcm_ctx == NULL || pcm == NULL) @@ -54,9 +91,9 @@ static pcm16_t *synth(const symrec_t *staff) { /* simple linear attack and linear decay filter */ (double)sample1 * (i < (uint32_t)nn->attack - ? (double)i / nn->attack + ? attack_ret((double)i, nn->attack) : (i > nn->duration - (uint32_t)nn->release - ? (-(double)i + (double)(nn->duration)) / nn->release + ? release_ret(-(double)i+nn->duration, nn->release) : 1.0)); } } diff --git a/libsynth/synth.h b/libsynth/synth.h index a0bdebb..0d07fa7 100644 --- a/libsynth/synth.h +++ b/libsynth/synth.h @@ -28,7 +28,7 @@ struct DSSynth { /* Possible options to be set for your synth. * Set this to NULL if there are none */ - DSOption *options; + DSOption *const options; /* Prints documentation on stdout. * This must always point to something, not NULL! */ diff --git a/test/canon-2.dats b/test/canon-2.dats index 2c809ae..91af045 100644 --- a/test/canon-2.dats +++ b/test/canon-2.dats @@ -1,5 +1,5 @@ staff m1 { - n 1, e4; + n 1, e4. ; n 1, d4; n 1, c4; n 1, b3; diff --git a/test/happyhchristmas.dats b/test/happyhchristmas.dats index d9de562..bf200a0 100644 --- a/test/happyhchristmas.dats +++ b/test/happyhchristmas.dats @@ -1,6 +1,6 @@ staff m1 { bpm = 120; - octave = 0; // raise a 0 octave + octave = 1; // raise an octave semitone = 0; // raise a 0 semitone // part 1 @@ -111,7 +111,7 @@ staff m1 { staff m2 { // part 1 octave = 0; - volume = 1200; + volume = 1100; n 12, d4; n 12, f#4; n 12, a4; @@ -343,8 +343,8 @@ staff m3 { master { pcm16 tr1 = mix((synth.sin(m1)[ - vibrato_frequency=8, vibrato_magnitude=2.0]), - (mix((synth.square(m2)),(mix((synth.sin(m2)), (synth.sin(m3))))))); - write("t.wav", tr1, tr1); + vibrato_frequency=8, vibrato_magnitude=3]), + (mix((synth.square(m2)),(synth.sin(m2))))); + write("t.wav", tr1); } diff --git a/test/t.dats b/test/t.dats index 54e2cc1..fa45381 100644 --- a/test/t.dats +++ b/test/t.dats @@ -191,7 +191,7 @@ master { *** hh */ /* pcm16 tmp1 = synth.kpa(apple);*/ - pcm16 track1 = synth.kpa(apple)[test="Al-buharie test l"], track1; + pcm16 track1 = synth.kpa(apple), track1; write("wj.wav", track1); }