From cc7564b00d04331bcdef5905512a795c4d816f50 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Sun, 11 Jul 2021 23:55:24 +0800 Subject: instrument: try to simulate violin But apparently it still sounds very bad. --- instrument.c | 101 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/instrument.c b/instrument.c index edb2f76..097ede4 100644 --- a/instrument.c +++ b/instrument.c @@ -179,20 +179,36 @@ UH_ATTR Pulse violin_sound_internal(Instrument *in, float theta) { - /* return -1.0f*fmod(theta, 2.0f*M_PI)/M_PI + 1.0f; */ + return -1.0f*fmod(theta, 2.0f*M_PI)/M_PI + 1.0f; /* return (*(in->sin_coefs)*sin(theta)+ * *(in->sin_coefs+1)*sin(2.0f*theta)+ * *(in->sin_coefs+2)*sin(3.0f*theta)+ * *(in->sin_coefs+3)*sin(4.0f*theta)+ * *(in->sin_coefs+4)*sin(5.0f*theta)); */ - Pulse result = 0.0f; - for (int i = 0; i < 26; i++) - result += *(in->sin_coefs+i) * sin((float) (i+1)*theta); + /* Pulse result = 0.0f; + * for (int i = 0; i < 4; i++) + * result += *(in->sin_coefs+i) * sin((float) (i+1)*theta); */ /* result = sin(theta); */ - return result; + /* return result; */ } +UH_ATTR +float violin_adsr(Instrument *violin, float t) +{ + if (t <= 0.0f || t > 1.0f) + return 0.0f; + + if (t <= violin->adsr.attack_p) + return log(1.0f + 2.7f*(t / violin->adsr.attack_p)); + else if (t <= violin->adsr.decay_p+violin->adsr.attack_p) + return (t - violin->adsr.attack_p) / violin->adsr.decay_p; + else if (t <= 1.0f - violin->adsr.release_p) + return violin->adsr.sustain_level; + else + return 1.0f - (1.0f - t) / violin->adsr.release_p; +} + UH_ATTR WaveFrag violin_sound(void * in, Volume v, Hertz h, Seconds s) @@ -205,52 +221,51 @@ violin_sound(void * in, Volume v, Hertz h, Seconds s) float step = (float) (h * 2 * M_PI) / SAMPLE_RATE; LENT sample_num = (LENT) floor(SAMPLE_RATE * s); - float attack_step = 1.0f / (float) (sample_num * violin->adsr.attack_p); - float decay_step = 1.0f / (float) (sample_num * violin->adsr.decay_p); - float sustain_step = 1.0f / (float) (sample_num * violin->adsr.sustain_p); - float release_step = 1.0f / (float) (sample_num * violin->adsr.release_p); + /* float attack_step = 1.0f / (float) (sample_num * violin->adsr.attack_p); + * float decay_step = 1.0f / (float) (sample_num * violin->adsr.decay_p); + * float sustain_step = 1.0f / (float) (sample_num * violin->adsr.sustain_p); + * float release_step = 1.0f / (float) (sample_num * violin->adsr.release_p); */ Wave w = MYALLOC(Pulse, sizeof(*w) * sample_num); float theta = 0.0f, temp = 0.0f, adsrcounter = 0.0f; - unsigned char phase = 0, sustain_flag = 0; - for (LENT i = 0; i < sample_num; i++, theta += step) { temp = violin_sound_internal(violin, theta); + adsrcounter = violin_adsr(violin, (float) i / sample_num); /* temp += temp*temp*temp; */ /* *(w+i) = (float) v * temp * ((sustain_flag) ? SUSTAIN_LEVEL : adsrcounter); */ - *(w+i) = (float) v * temp; + *(w+i) = (float) v * temp * adsrcounter; - switch (phase) { - case 0: /* attack phase */ - adsrcounter += attack_step; - if (adsrcounter >= 1.0f) { - adsrcounter = 1.0f; - phase++; - } - break; - case 1: /* decay phase */ - adsrcounter -= decay_step; - if (adsrcounter <= SUSTAIN_LEVEL) { - adsrcounter = 0.0f; - sustain_flag = 1; - phase++; - } - break; - case 2: /* sustain phase */ - adsrcounter += sustain_step; - if (adsrcounter >= 1.0f) { - adsrcounter = SUSTAIN_LEVEL; - sustain_flag = 0; - phase++; - } - break; - default: /* release phase */ - adsrcounter -= release_step; - if (adsrcounter <= 0.0f) adsrcounter = 0.0f; - break; - } + /* switch (phase) { + * case 0: /\* attack phase *\/ + * adsrcounter += attack_step; + * if (adsrcounter >= 1.0f) { + * adsrcounter = 1.0f; + * phase++; + * } + * break; + * case 1: /\* decay phase *\/ + * adsrcounter -= decay_step; + * if (adsrcounter <= SUSTAIN_LEVEL) { + * adsrcounter = 0.0f; + * sustain_flag = 1; + * phase++; + * } + * break; + * case 2: /\* sustain phase *\/ + * adsrcounter += sustain_step; + * if (adsrcounter >= 1.0f) { + * adsrcounter = SUSTAIN_LEVEL; + * sustain_flag = 0; + * phase++; + * } + * break; + * default: /\* release phase *\/ + * adsrcounter -= release_step; + * if (adsrcounter <= 0.0f) adsrcounter = 0.0f; + * break; + * } */ } return (WaveFrag) { w, sample_num }; @@ -341,8 +356,8 @@ make_violin() violin->adsr.pred = 1; violin->reverb = 0.01f; - violin->adsr.attack_p = 0.55; - violin->adsr.release_p = 0.25; + violin->adsr.attack_p = 0.09; + violin->adsr.release_p = 0.09; violin->adsr.decay_p = 0.05; violin->adsr.sustain_p = max(1.0f - (violin->adsr.attack_p+ violin->adsr.decay_p+ -- cgit v1.2.3-18-g5258