summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-07-11 23:55:24 +0800
committerJSDurand <mmemmew@gmail.com>2021-07-11 23:55:24 +0800
commitcc7564b00d04331bcdef5905512a795c4d816f50 (patch)
tree9d1be1b61b9346ba2b35ac2927770d0bb54d6a95
parent43d5fc19e5caf8a50b547efb1bde05a5cf158311 (diff)
instrument: try to simulate violin
But apparently it still sounds very bad.
-rw-r--r--instrument.c101
1 files changed, 58 insertions, 43 deletions
diff --git a/instrument.c b/instrument.c
index edb2f76..097ede4 100644
--- a/instrument.c
+++ b/instrument.c
@@ -179,21 +179,37 @@ 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+