summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-07-12 16:46:54 +0800
committerJSDurand <mmemmew@gmail.com>2021-07-12 16:46:54 +0800
commit05ce8e10cda54daecc52fd0e04972b28cc811668 (patch)
tree96d5c94a1373a09a4ccce3f1bb8a36297e09cfbc /parser.c
parent8d1acd562f16e8420c66e1f920912ecfa2fc0bda (diff)
Volume changing commandHEADmaster
Now the sheets can contain commands to change volumes for the channels.
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/parser.c b/parser.c
index 3b0d30c..1764f86 100644
--- a/parser.c
+++ b/parser.c
@@ -13,12 +13,16 @@
/* A note of type BEAT_DURATION_TYPE stores the new bpm in the secs
field. */
+/* A note of type VOLUME_TYPE stores the new volume in the secs
+ field. */
+
typedef enum {
NONE_TYPE,
NOTE_TYPE,
SILENT_TYPE,
INSTRUMENT_TYPE,
- BEAT_DURATION_TYPE
+ BEAT_DURATION_TYPE,
+ VOLUME_TYPE
} PType;
struct PNote_s {
@@ -103,6 +107,11 @@ print_note(const PNote note)
"%.3f beats per minute.\n",
note.secs);
break;
+ case VOLUME_TYPE:
+ fprintf(stderr, "a note of the type that changes the volume to "
+ "%.3f times.\n",
+ note.secs);
+ break;
}
}
@@ -267,6 +276,28 @@ read_sheet(const char *str, LENT len)
if (*(str+counter) == ' ') {
/* Just skip spaces so that they don't block us reading anchor
chars. */
+ } else if (*(str+counter) == 'v') {
+ /* changing volume note */
+
+ counter++;
+
+ for (;*(str+counter) == ' ';) counter++;
+
+ if (*(str+counter) != '\n' &&
+ *(str+counter) != 13 &&
+ sscanf(str+counter, "%lf%n",
+ &local, &num_chars_read) == 1) {
+ temp_note = (PNote) {
+ NULL, local,
+ 0, VOLUME_TYPE, NULL
+ };
+
+ /* fprintf(stderr, "print a note\n");
+ * print_note(temp_note); */
+
+ counter += num_chars_read-1;
+ }
+ *(current_unit.notes+channel_num) = temp_note;
} else if (*(str+counter) == 'b') {
/* changing bpm note */
@@ -528,6 +559,10 @@ play_sheet(const PSheet sh, const Volume v)
Beats dur = BEAT_DUR;
+ /* Each channel can specify its sound. */
+
+ Volume *volume_per_channel = MYALLOC(Volume, channel_num);;
+
#ifdef DEBUG
fprintf(stderr, "before finding num\n");
#endif
@@ -550,12 +585,14 @@ play_sheet(const PSheet sh, const Volume v)
#endif
*(temp+i) = MYALLOC(WaveFrag, *(num_notes_per_channel+i));
+
+ *(channel_num_array+i) = 0;
+
+ *(volume_per_channel+i) = 1.0;
}
war = MYALLOC(WaveFrag, channel_num);
- for (LENT i = 0; i < channel_num;) *(channel_num_array+i++) = 0;
-
#ifdef DEBUG
fprintf(stderr, "before for loop\n");
#endif
@@ -575,7 +612,8 @@ play_sheet(const PSheet sh, const Volume v)
if (pn.type != NOTE_TYPE &&
pn.type != SILENT_TYPE &&
- pn.type != BEAT_DURATION_TYPE) continue;
+ pn.type != BEAT_DURATION_TYPE &&
+ pn.type != VOLUME_TYPE) continue;
if (pn.len >= 10) {
fprintf(stderr, "A note cannot have more than 10 semitones together.\n");
@@ -590,17 +628,24 @@ play_sheet(const PSheet sh, const Volume v)
switch (pn.type) {
case NOTE_TYPE:
for (LENT k = 0; k < pn.len; k++) {
- *(st_temp+k) = make_sound(inst, v * ((k==1) ? 0.3 : 1.0),
+ *(st_temp+k) = make_sound(inst, v * *(volume_per_channel+j),
stoh(*(pn.tones+k)), pn.secs * dur);
}
break;
case BEAT_DURATION_TYPE:
dur = 60.0 / pn.secs;
break;
- default:
- /* SILENT_TYPE */
+ case VOLUME_TYPE:
+ *(volume_per_channel+j) = pn.secs;
+ break;
+ case SILENT_TYPE:
*(st_temp) = silent_note(pn.secs, dur);
break;
+ default:
+ /* Not goint to happen */
+ fprintf(stderr, "something weird happens in play_sheet.\n");
+ exit(1);
+ break;
}
#ifdef DEBUG
@@ -644,6 +689,7 @@ play_sheet(const PSheet sh, const Volume v)
free(temp);
free(num_notes_per_channel);
free(channel_num_array);
+ free(volume_per_channel);
#ifdef DEBUG
fprintf(stderr, "after merging\n");