From f65baf7b2472cf4963866f925651dc6c61be4f11 Mon Sep 17 00:00:00 2001 From: Angel Ortega Date: Tue, 1 Feb 2011 16:30:05 +0100 Subject: [PATCH] Massive code reformatting. --- compiler.l | 111 ++--- compiler.y | 809 ++++++++++++++++----------------- main.c | 528 +++++++++++----------- midi_song.c | 753 ++++++++++++++++--------------- midiin.c | 207 +++++---- sha1.c | 329 +++++++------- song.c | 823 +++++++++++++++++++--------------- ss_core.c | 399 ++++++++--------- ss_eff.c | 314 ++++++------- ss_gen.c | 250 ++++++----- ss_input.c | 1427 ++++++++++++++++++++++++++++++----------------------------- ss_ins.c | 221 +++++---- ss_outdev.c | 609 ++++++++++++------------- ss_output.c | 213 ++++----- ss_song.c | 1219 +++++++++++++++++++++++++------------------------- stress.c | 47 +- support.c | 380 ++++++++-------- 17 files changed, 4407 insertions(+), 4232 deletions(-) rewrite main.c (78%) rewrite midi_song.c (72%) rewrite sha1.c (64%) rewrite song.c (62%) rewrite ss_input.c (72%) rewrite ss_song.c (84%) rewrite stress.c (89%) diff --git a/compiler.l b/compiler.l index 2c51550..a8b6092 100644 --- a/compiler.l +++ b/compiler.l @@ -33,7 +33,7 @@ #include "ahxm.h" void yyerror(const char *s); -int yy_input_for_flex(char * buf, int max); +int yy_input_for_flex(char *buf, int max); /* the notes */ static const char *ascii_notes = "ccddeffggaab"; @@ -43,8 +43,8 @@ static const char *ascii_notes = "ccddeffggaab"; #define YY_INPUT(b,r,m) (r = yy_input_for_flex(b,m)) struct code_stack { - const char *code; /* code string */ - int offset; /* current offset */ + const char *code; /* code string */ + int offset; /* current offset */ }; static struct code_stack *code_stack = NULL; @@ -52,14 +52,18 @@ static int code_stack_i = -1; /* dynamic string manipulation macros */ #ifndef ds_init -struct ds { char *d; int p; int s; }; +struct ds { + char *d; + int p; + int s; +}; #define ds_init(x) do { x.d = (char *)0; x.p = x.s = 0; } while(0) #define ds_rewind(x) x.p = 0; #define ds_free(x) do { if (x.d) free(x.d); ds_init(x); } while(0) #define ds_redim(x) do { if (x.p >= x.s) x.d = realloc(x.d, x.s += 32); } while(0) #define ds_poke(x,c) do { ds_redim(x); x.d[x.p++] = c; } while(0) #define ds_pokes(x,t) do { char *p = t; while (*p) ds_poke(x, *p++); } while(0) -#endif /* ds_init */ +#endif /* ds_init */ /* block dynstring */ static struct ds ds_blk; @@ -332,87 +336,90 @@ L[^ \t\n]+ { %% -int yywrap(void) { return(1); } +int yywrap(void) +{ + return 1; +} -char * ds_load(const char * file) +char *ds_load(const char *file) { - struct ds s; - int c; - FILE * f; + struct ds s; + int c; + FILE *f; - if ((f = libpath_fopen(file, "rb")) == NULL) - return(NULL); + if ((f = libpath_fopen(file, "rb")) == NULL) + return (NULL); - ds_init(s); + ds_init(s); - while ((c = fgetc(f)) != EOF) - ds_poke(s, c); + while ((c = fgetc(f)) != EOF) + ds_poke(s, c); - ds_poke(s, '\0'); - fclose(f); + ds_poke(s, '\0'); + fclose(f); - return s.d; + return s.d; } -int push_code(const char * code) +int push_code(const char *code) { - struct code_stack * cs; + struct code_stack *cs; - code_stack_i++; - GROW(code_stack, code_stack_i, struct code_stack); + code_stack_i++; + GROW(code_stack, code_stack_i, struct code_stack); - cs = &code_stack[code_stack_i]; + cs = &code_stack[code_stack_i]; - cs->code = code; - cs->offset = 0; + cs->code = code; + cs->offset = 0; - return 1; + return 1; } -int push_code_from_file(const char * file) +int push_code_from_file(const char *file) { - char * c; + char *c; - if ((c = ds_load(file)) == NULL) - return 0; + if ((c = ds_load(file)) == NULL) + return 0; - push_code(c); - return 1; + push_code(c); + return 1; } int code_getchar(void) { - struct code_stack * cs; - int c = '\0'; + struct code_stack *cs; + int c = '\0'; - while (c == '\0' && code_stack_i > -1) { - /* get current char */ - cs = &code_stack[code_stack_i]; - c = cs->code[cs->offset++]; + while (c == '\0' && code_stack_i > -1) { + /* get current char */ + cs = &code_stack[code_stack_i]; + c = cs->code[cs->offset++]; - /* end of code? */ - if (c == '\0') { - /* free */ - free((char *) cs->code); + /* end of code? */ + if (c == '\0') { + /* free */ + free((char *) cs->code); - /* move to previous */ - code_stack_i--; + /* move to previous */ + code_stack_i--; - /* in any case, return a separator */ - c = ' '; - } - } + /* in any case, return a separator */ + c = ' '; + } + } - return c; + return c; } -int yy_input_for_flex(char * buf, int max) +int yy_input_for_flex(char *buf, int max) { - buf[0] = code_getchar(); + buf[0] = code_getchar(); - return buf[0] == '\0' ? 0 : 1; + return buf[0] == '\0' ? 0 : 1; } diff --git a/compiler.y b/compiler.y index 2a9f948..3944365 100644 --- a/compiler.y +++ b/compiler.y @@ -33,16 +33,15 @@ #include "ahxm.h" -/******************* - Data -********************/ + +/** data **/ int yylex(void); -void yyerror(const char * s); +void yyerror(const char *s); /* injecting code functions (defined in compiler.l) */ -int push_code(const char * code); -int push_code_from_file(const char * file); +int push_code(const char *code); +int push_code_from_file(const char *file); /* current track */ int track; @@ -69,43 +68,43 @@ static double gliss; /* blocks */ struct block { - const char * name; - int n_sblocks; - char ** sblocks; + const char *name; + int n_sblocks; + char **sblocks; }; -static struct block * blocks = NULL; +static struct block *blocks = NULL; static int n_blocks = 0; /* group info */ struct group { - double start; - double gliss; - double max; + double start; + double gliss; + double max; }; -static struct group * groups = NULL; +static struct group *groups = NULL; static int n_groups = 0; static int groups_size = 0; /* mark info */ struct mark { - const char * name; - double time; + const char *name; + double time; }; -static struct mark * marks = NULL; +static struct mark *marks = NULL; static int n_marks = 0; /* arpeggiator */ struct arp { - double delay; - int transpose; - sample_t volume; - int track_off; + double delay; + int transpose; + sample_t volume; + int track_off; }; -static struct arp * arps = NULL; +static struct arp *arps = NULL; static int n_arps = 0; static int arps_size = 0; @@ -128,163 +127,162 @@ unsigned int volume_seed = 0; /* solo track (-1, no solo) */ int solo_track = -1; -/******************* - Code -********************/ -unsigned int ah_rnd(unsigned int * seed) +/** code **/ + +unsigned int ah_rnd(unsigned int *seed) /* special randomizer */ { - *seed = (*seed * 58321) + 11113; + *seed = (*seed * 58321) + 11113; - return *seed >> 16; + return *seed >> 16; } -void c_err(const char * e1, const char * e2, const char * e3) +void c_err(const char *e1, const char *e2, const char *e3) /* reports an error from the compiler */ { - printf("ahxm:"); + printf("ahxm:"); - if (e1 != NULL) - printf(" %s", e1); - if (e2 != NULL) - printf(" %s", e2); - if (e3 != NULL) - printf(" %s", e3); + if (e1 != NULL) + printf(" %s", e1); + if (e2 != NULL) + printf(" %s", e2); + if (e3 != NULL) + printf(" %s", e3); - printf(" in line %d\n", yyline); + printf(" in line %d\n", yyline); - compiler_error++; + compiler_error++; } static void forward(double step) /* moves forward current time */ { - /* add step */ - cur_time += step; + /* add step */ + cur_time += step; - /* quantizations could be done here */ + /* quantizations could be done here */ } static sample_t volume(void) { - sample_t f; + sample_t f; - if (volume_from == volume_to) - f = volume_from; - else { - unsigned int r = ah_rnd(&volume_seed) % 1000; + if (volume_from == volume_to) + f = volume_from; + else { + unsigned int r = ah_rnd(&volume_seed) % 1000; - f = volume_from + (volume_to - volume_from) * - (((sample_t) r) / 1000.0); - } + f = volume_from + (volume_to - volume_from) * + (((sample_t) r) / 1000.0); + } - return f; + return f; } /* blocks */ -static int find_block(const char * name) +static int find_block(const char *name) /* finds a block */ { - int n; + int n; - for (n = 0; n < n_blocks; n++) { - if (strcmp(name, blocks[n].name) == 0) - return n; - } + for (n = 0; n < n_blocks; n++) { + if (strcmp(name, blocks[n].name) == 0) + return n; + } - return -1; + return -1; } -static int set_block(const char * name, char * block) +static int set_block(const char *name, char *block) /* defines a block */ { - int n; - struct block * b; - char * start; - char * stop; + int n; + struct block *b; + char *start; + char *stop; - /* if block already exists, free it */ - if ((n = find_block(name)) >= 0) { - b = &blocks[n]; + /* if block already exists, free it */ + if ((n = find_block(name)) >= 0) { + b = &blocks[n]; - /* free all subblocks */ - for (n = 0; n < b->n_sblocks; n++) - free(b->sblocks[n]); + /* free all subblocks */ + for (n = 0; n < b->n_sblocks; n++) + free(b->sblocks[n]); - /* free the subblock array */ - free(b->sblocks); - } - else { - GROW(blocks, n_blocks, struct block); - b = &blocks[n_blocks++]; + /* free the subblock array */ + free(b->sblocks); + } + else { + GROW(blocks, n_blocks, struct block); + b = &blocks[n_blocks++]; - b->name = strdup(name); - } + b->name = strdup(name); + } - /* reset */ - b->n_sblocks = 0; - b->sblocks = NULL; + /* reset */ + b->n_sblocks = 0; + b->sblocks = NULL; - /* now split in subblocks (delimited by : ) */ - start = block; + /* now split in subblocks (delimited by : ) */ + start = block; - while ((stop = strchr(start, ':')) != NULL) { - /* break there */ - *stop = '\0'; + while ((stop = strchr(start, ':')) != NULL) { + /* break there */ + *stop = '\0'; - /* add the subblock */ - GROW(b->sblocks, b->n_sblocks, char *); - b->sblocks[b->n_sblocks++] = strdup(start); + /* add the subblock */ + GROW(b->sblocks, b->n_sblocks, char *); + b->sblocks[b->n_sblocks++] = strdup(start); - start = stop + 1; - } + start = stop + 1; + } - /* no more separators? store the rest */ - GROW(b->sblocks, b->n_sblocks, char *); - b->sblocks[b->n_sblocks++] = strdup(start); + /* no more separators? store the rest */ + GROW(b->sblocks, b->n_sblocks, char *); + b->sblocks[b->n_sblocks++] = strdup(start); - /* the original block is no longer needed */ - free(block); + /* the original block is no longer needed */ + free(block); - return 1; + return 1; } -static void insert_block(const char * name) +static void insert_block(const char *name) /* inserts a block */ { - int n; + int n; - if ((n = find_block(name)) >= 0) { - struct block * b; + if ((n = find_block(name)) >= 0) { + struct block *b; - b = &blocks[n]; + b = &blocks[n]; - /* get one of them, randomly */ - n = ah_rnd(&block_seed) % b->n_sblocks; + /* get one of them, randomly */ + n = ah_rnd(&block_seed) % b->n_sblocks; - push_code(strdup(b->sblocks[n])); - } - else - c_err("block-not-found", name, NULL); + push_code(strdup(b->sblocks[n])); + } + else + c_err("block-not-found", name, NULL); } -static int insert_file(const char * filename) +static int insert_file(const char *filename) { - if (!push_code_from_file(filename)) { - c_err("script-not-found", filename, NULL); - return 1; - } + if (!push_code_from_file(filename)) { + c_err("script-not-found", filename, NULL); + return 1; + } - return 0; + return 0; } @@ -293,121 +291,120 @@ static int insert_file(const char * filename) static int push_group(void) /* starts a new group of notes */ { - struct group * g; + struct group *g; - if (n_groups == groups_size) { - GROW(groups, groups_size, struct group); - groups_size ++; - } + if (n_groups == groups_size) { + GROW(groups, groups_size, struct group); + groups_size++; + } - g = &groups[n_groups++]; + g = &groups[n_groups++]; - g->start = cur_time; - g->gliss = 0.0; - g->max = 0.0; + g->start = cur_time; + g->gliss = 0.0; + g->max = 0.0; - return 1; + return 1; } static int next_group_part(void) /* part delimiter */ { - struct group * g; + struct group *g; - if (n_groups == 0) { - c_err("missing-start-of-group", NULL, NULL); - return 0; - } + if (n_groups == 0) { + c_err("missing-start-of-group", NULL, NULL); + return 0; + } - g = &groups[n_groups - 1]; + g = &groups[n_groups - 1]; - /* store maximum frame */ - if (g->max < cur_time) - g->max = cur_time; + /* store maximum frame */ + if (g->max < cur_time) + g->max = cur_time; - /* add glissando delay */ - g->gliss += gliss; + /* add glissando delay */ + g->gliss += gliss; - /* rewind */ - cur_time = g->start + g->gliss; + /* rewind */ + cur_time = g->start + g->gliss; - return 1; + return 1; } static int pop_group(void) /* finishes a group, moving the frame to the end of the longer part */ { - if (n_groups == 0) { - c_err("missing-start-of-group", NULL, NULL); - return 0; - } + if (n_groups == 0) { + c_err("missing-start-of-group", NULL, NULL); + return 0; + } - n_groups--; + n_groups--; - /* if other parts of group were longer than the last one, - move pointer there */ - if (groups[n_groups].max > cur_time) - cur_time = groups[n_groups].max; + /* if other parts of group were longer than the last one, + move pointer there */ + if (groups[n_groups].max > cur_time) + cur_time = groups[n_groups].max; - return 1; + return 1; } /* marks */ -static int seek_mark(const char * name) +static int seek_mark(const char *name) /* seeks a mark by name; returns its offset or -1 */ { - int n; + int n; - for (n = 0; n < n_marks; n++) - if (strcmp(marks[n].name, name) == 0) - return n; + for (n = 0; n < n_marks; n++) + if (strcmp(marks[n].name, name) == 0) + return n; - return -1; + return -1; } -static void add_mark(const char * name) +static void add_mark(const char *name) /* creates a new mark */ { - int n; + int n; - if ((n = seek_mark(name)) == -1) { - n = n_marks++; - GROW(marks, n, struct mark); - marks[n].name = strdup(name); - } + if ((n = seek_mark(name)) == -1) { + n = n_marks++; + GROW(marks, n, struct mark); + marks[n].name = strdup(name); + } - marks[n].time = cur_time; + marks[n].time = cur_time; } -static void find_mark(const char * name, int set) +static void find_mark(const char *name, int set) /* finds a mark by name, optionally moving time cursor there */ { - int n; - - if ((n = seek_mark(name)) != -1) { - if (set) { - if (cur_time > marks[n].time) { - /* if mark is not END, fail */ - if (strcmp(name, "END") != 0) - c_err("mark-overpassed", name, NULL); - } - else - cur_time = marks[n].time; - } - else - if (cur_time != marks[n].time) - c_err("mark-mismatch", name, NULL); - - return; - } - - c_err("mark-not-found", name, NULL); + int n; + + if ((n = seek_mark(name)) != -1) { + if (set) { + if (cur_time > marks[n].time) { + /* if mark is not END, fail */ + if (strcmp(name, "END") != 0) + c_err("mark-overpassed", name, NULL); + } + else + cur_time = marks[n].time; + } + else if (cur_time != marks[n].time) + c_err("mark-mismatch", name, NULL); + + return; + } + + c_err("mark-not-found", name, NULL); } @@ -416,341 +413,343 @@ static void find_mark(const char * name, int set) static void arp_default(void) /* resets arpeggiator values to the default ones */ { - arp_delay = 0.0; - arp_transpose = 0; - arp_volume = 1.0; - arp_track_off = 0; + arp_delay = 0.0; + arp_transpose = 0; + arp_volume = 1.0; + arp_track_off = 0; } static void add_arp(void) /* adds an arpeggiator note */ { - struct arp * a; + struct arp *a; - /* if the note is exactly the same, do nothing */ - if (arp_delay == 0.0 && arp_transpose == 0 && - arp_volume == 1.0 && arp_track_off == 0) - return; + /* if the note is exactly the same, do nothing */ + if (arp_delay == 0.0 && arp_transpose == 0 && + arp_volume == 1.0 && arp_track_off == 0) + return; - if (n_arps == arps_size) { - GROW(arps, arps_size, struct arp); - arps_size ++; - } + if (n_arps == arps_size) { + GROW(arps, arps_size, struct arp); + arps_size++; + } - a = &arps[n_arps]; + a = &arps[n_arps]; - a->delay = arp_delay; - a->transpose = arp_transpose; - a->volume = arp_volume; - a->track_off = arp_track_off; + a->delay = arp_delay; + a->transpose = arp_transpose; + a->volume = arp_volume; + a->track_off = arp_track_off; - n_arps++; - arp_default(); + n_arps++; + arp_default(); } -static void set_alteration(const char * altstr) +static void set_alteration(const char *altstr) /* sets the alterations from altstr */ { - int n, steps[] = { 2, 0, 2, 0, 1, 2, 0, 2, 0, 2, 0, 1 }; - - /* reset alterations */ - for (n = 0; n < 12; n++) - alterations[n] = 0; - - /* changed according the altstr spec */ - for (n = 0; *altstr != '\0' && n < 12; altstr++) { - switch (*altstr) { - case '&': - alterations[n] = -1; - break; - - case '#': - alterations[n] = 1; - break; - } - - /* move to next natural note */ - n += steps[n]; - } + int n, steps[] = { 2, 0, 2, 0, 1, 2, 0, 2, 0, 2, 0, 1 }; + + /* reset alterations */ + for (n = 0; n < 12; n++) + alterations[n] = 0; + + /* changed according the altstr spec */ + for (n = 0; *altstr != '\0' && n < 12; altstr++) { + switch (*altstr) { + case '&': + alterations[n] = -1; + break; + + case '#': + alterations[n] = 1; + break; + } + + /* move to next natural note */ + n += steps[n]; + } } /* song events */ -static struct song_ev * add_song_ev(song_ev_type type) +static struct song_ev *add_song_ev(song_ev_type type) { - struct song_ev * r; + struct song_ev *r; - r = add_event(&song, &n_song_ev); + r = add_event(&song, &n_song_ev); - r->type = type; - r->time = cur_time; - r->trk_id = track; - r->event_id = n_song_ev - 1; + r->type = type; + r->time = cur_time; + r->trk_id = track; + r->event_id = n_song_ev - 1; - return r; + return r; } static void add_note_event(int note) /* adds a note event */ { - int n; - int np; - struct song_ev *e; + int n; + int np; + struct song_ev *e; - /* sum the alteration */ - if ((n = note % 12) < 0) - n += 12; + /* sum the alteration */ + if ((n = note % 12) < 0) + n += 12; - note += alterations[n]; + note += alterations[n]; - /* calculate the note */ - np = note + transpose + (octave * 12); + /* calculate the note */ + np = note + transpose + (octave * 12); - /* is note out of range? */ - if (np < 0 || np > 127) { - c_err("note-out-of-range", NULL, NULL); - return; - } + /* is note out of range? */ + if (np < 0 || np > 127) { + c_err("note-out-of-range", NULL, NULL); + return; + } - e = add_song_ev(SONG_EV_NOTE); + e = add_song_ev(SONG_EV_NOTE); - e->value = np; - e->len = length * staccato; - e->vol = volume(); + e->value = np; + e->len = length * staccato; + e->vol = volume(); - /* add arpeggiator repetitions */ - for (n = 0; n < n_arps; n++) { + /* add arpeggiator repetitions */ + for (n = 0; n < n_arps; n++) { - e = add_song_ev(SONG_EV_NOTE); + e = add_song_ev(SONG_EV_NOTE); - e->time = cur_time + arps[n].delay; - e->trk_id = track + arps[n].track_off; - e->value = np + arps[n].transpose; - e->len = length * staccato; - e->vol = volume() * arps[n].volume; - } + e->time = cur_time + arps[n].delay; + e->trk_id = track + arps[n].track_off; + e->value = np + arps[n].transpose; + e->len = length * staccato; + e->vol = volume() * arps[n].volume; + } } static void add_back_event(void) { - struct song_ev *e = add_song_ev(SONG_EV_BACK); + struct song_ev *e = add_song_ev(SONG_EV_BACK); - e->len = length; + e->len = length; } static void add_tempo_event(int trk_id, double tempo) { - struct song_ev *e = add_song_ev(SONG_EV_TEMPO); + struct song_ev *e = add_song_ev(SONG_EV_TEMPO); - e->trk_id = trk_id; - e->amount = tempo; + e->trk_id = trk_id; + e->amount = tempo; } static void add_meter_event(int trk_id, int num, int den) { - struct song_ev *e = add_song_ev(SONG_EV_METER); + struct song_ev *e = add_song_ev(SONG_EV_METER); - e->trk_id = trk_id; - e->min = num; - e->max = den; + e->trk_id = trk_id; + e->min = num; + e->max = den; } static void add_measure_event(void) { - struct song_ev *e = add_song_ev(SONG_EV_MEASURE); + struct song_ev *e = add_song_ev(SONG_EV_MEASURE); - e->trk_id = -1; - e->value = yyline; + e->trk_id = -1; + e->value = yyline; } static void add_ss_sustain_event(double sustain) { - struct song_ev *e = add_song_ev(SONG_EV_SS_SUSTAIN); + struct song_ev *e = add_song_ev(SONG_EV_SS_SUSTAIN); - e->amount = sustain; + e->amount = sustain; } static void add_ss_attack_event(double attack) { - struct song_ev *e = add_song_ev(SONG_EV_SS_ATTACK); + struct song_ev *e = add_song_ev(SONG_EV_SS_ATTACK); - e->amount = attack; + e->amount = attack; } static void add_ss_vibrato_event(double depth, double freq) { - struct song_ev *e = add_song_ev(SONG_EV_SS_VIBRATO); + struct song_ev *e = add_song_ev(SONG_EV_SS_VIBRATO); - e->depth = depth; - e->freq = freq; + e->depth = depth; + e->freq = freq; } static void add_ss_portamento_event(double portamento) { - struct song_ev *e = add_song_ev(SONG_EV_SS_PORTAMENTO); + struct song_ev *e = add_song_ev(SONG_EV_SS_PORTAMENTO); - e->amount = portamento; + e->amount = portamento; } static void add_ss_channel_event(int channel, sample_t vol) { - struct song_ev *e = add_song_ev(SONG_EV_SS_CHANNEL); + struct song_ev *e = add_song_ev(SONG_EV_SS_CHANNEL); - e->channel = channel; - e->vol = vol; + e->channel = channel; + e->vol = vol; } -static void add_ss_wav_event(const char * wav_file, int base, int min, int max, - double loop_start, double loop_end, int first_channel, int skip_channels) +static void add_ss_wav_event(const char *wav_file, int base, int min, + int max, double loop_start, double loop_end, + int first_channel, int skip_channels) { - struct song_ev *e = add_song_ev(SONG_EV_SS_WAV); - - e->name = wav_file; - e->value = base; - e->min = min; - e->max = max; - e->start = loop_start; - e->end = loop_end; - e->channel = first_channel; - e->skip_channels = skip_channels; + struct song_ev *e = add_song_ev(SONG_EV_SS_WAV); + + e->name = wav_file; + e->value = base; + e->min = min; + e->max = max; + e->start = loop_start; + e->end = loop_end; + e->channel = first_channel; + e->skip_channels = skip_channels; } -static void add_ss_pat_event(const char * pat_file) +static void add_ss_pat_event(const char *pat_file) { - struct song_ev *e = add_song_ev(SONG_EV_SS_PAT); + struct song_ev *e = add_song_ev(SONG_EV_SS_PAT); - e->name = pat_file; + e->name = pat_file; } -static void add_ss_sf2_event(const char * sf2_file, const char *insname) +static void add_ss_sf2_event(const char *sf2_file, const char *insname) { - struct song_ev *e = add_song_ev(SONG_EV_SS_SF2); + struct song_ev *e = add_song_ev(SONG_EV_SS_SF2); - e->name = sf2_file; - e->str2 = insname; + e->name = sf2_file; + e->str2 = insname; } -static void add_ss_eff_event(int type, int channel, double size, sample_t gain, - double depth, double freq, double phase, sample_t initial, sample_t final) +static void add_ss_eff_event(int type, int channel, double size, + sample_t gain, double depth, double freq, + double phase, sample_t initial, + sample_t final) { - struct song_ev *e = add_song_ev(type); - - e->channel = channel; - e->len = size; - e->vol = gain; - e->depth = depth; - e->freq = freq; - e->phase = phase; - e->initial = initial; - e->final = final; + struct song_ev *e = add_song_ev(type); + + e->channel = channel; + e->len = size; + e->vol = gain; + e->depth = depth; + e->freq = freq; + e->phase = phase; + e->initial = initial; + e->final = final; } static void add_ss_pitch_stretch(int note, double len, sample_t vol) { - struct song_ev *e = add_song_ev(SONG_EV_SS_PITCH_STRETCH); + struct song_ev *e = add_song_ev(SONG_EV_SS_PITCH_STRETCH); - e->value = note; - e->len = len; - e->vol = vol; + e->value = note; + e->len = len; + e->vol = vol; } static void add_ss_print_wave_tempo(int note, double len) { - struct song_ev *e = add_song_ev(SONG_EV_SS_PRINT_WAVE_TEMPO); + struct song_ev *e = add_song_ev(SONG_EV_SS_PRINT_WAVE_TEMPO); - e->value = note; - e->len = len; + e->value = note; + e->len = len; } static void add_ss_master_volume(sample_t vol) { - struct song_ev *e = add_song_ev(SONG_EV_SS_MASTER_VOLUME); + struct song_ev *e = add_song_ev(SONG_EV_SS_MASTER_VOLUME); - e->trk_id = -1; - e->vol = vol; + e->trk_id = -1; + e->vol = vol; } static void add_midi_channel_event(int channel) { - struct song_ev *e = add_song_ev(SONG_EV_MIDI_CHANNEL); + struct song_ev *e = add_song_ev(SONG_EV_MIDI_CHANNEL); - e->channel = channel - 1; + e->channel = channel - 1; } static void add_midi_program_event(int program) { - struct song_ev *e = add_song_ev(SONG_EV_MIDI_PROGRAM); + struct song_ev *e = add_song_ev(SONG_EV_MIDI_PROGRAM); - e->value = program; + e->value = program; } -static void add_song_info_event(const char * author, const char * name) +static void add_song_info_event(const char *author, const char *name) { - struct song_ev *e = add_song_ev(SONG_EV_SONG_INFO); + struct song_ev *e = add_song_ev(SONG_EV_SONG_INFO); - e->str2 = author; - e->name = name; + e->str2 = author; + e->name = name; } static void init_track(void) /* sets the default values for a new track */ { - int n; - - /* is there an end time? test if this is longer */ - if (cur_time > end_time) { - add_mark("END"); - end_time = cur_time; - } - - cur_time = 0.0; - length = 0.0; - transpose = 0; - staccato = 0.8; - volume_from = volume_to = 0.75; - octave = 5; - gliss = 0; - - /* groups should not cross track boundaries */ - n_groups = 0; - - /* reset arpeggiator */ - n_arps = 0; - arp_default(); - - /* is there a START mark? if so, move there */ - if ((n = seek_mark("START")) != -1) - cur_time = marks[n].time; - - /* reset alterations */ - for (n = 0; n < 12; n++) - alterations[n] = 0; + int n; + + /* is there an end time? test if this is longer */ + if (cur_time > end_time) { + add_mark("END"); + end_time = cur_time; + } + + cur_time = 0.0; + length = 0.0; + transpose = 0; + staccato = 0.8; + volume_from = volume_to = 0.75; + octave = 5; + gliss = 0; + + /* groups should not cross track boundaries */ + n_groups = 0; + + /* reset arpeggiator */ + n_arps = 0; + arp_default(); + + /* is there a START mark? if so, move there */ + if ((n = seek_mark("START")) != -1) + cur_time = marks[n].time; + + /* reset alterations */ + for (n = 0; n < 12; n++) + alterations[n] = 0; } - %} %union { @@ -1259,9 +1258,9 @@ xc_cmd: %% -void yyerror(const char * s) +void yyerror(const char *s) { - c_err(s, NULL, NULL); + c_err(s, NULL, NULL); } @@ -1269,58 +1268,70 @@ void yyerror(const char * s) static void compile_startup(void) { - track = 0; - yyline = 1; - compiler_error = 0; - - /* default settings */ - add_tempo_event(-2, 120.0); - add_meter_event(-2, 4, 4); - init_track(); - - /* standard tonalities */ - set_block_d("CM", "A"); set_block_d("Am", "$CM"); - set_block_d("C#M", "A#######"); set_block_d("A#m", "$C#M"); - set_block_d("DM", "A#--#---"); set_block_d("Bm", "$DM"); - set_block_d("E&M", "A--&--&&"); set_block_d("Cm", "$E&M"); - set_block_d("EM", "A##-##--"); set_block_d("C#m", "$EM"); - set_block_d("FM", "A------&"); set_block_d("Dm", "$FM"); - set_block_d("F#M", "A######-"); set_block_d("D#m", "$F#M"); - set_block_d("GM", "A---#---"); set_block_d("Em", "$GM"); - set_block_d("A&M", "A-&&--&&"); set_block_d("Fm", "$A&M"); - set_block_d("AM", "A#--##--"); set_block_d("F#m", "$AM"); - set_block_d("B&M", "A--&---&"); set_block_d("Gm", "$B&M"); - set_block_d("BM", "A##-###-"); set_block_d("G#m", "$BM"); + track = 0; + yyline = 1; + compiler_error = 0; + + /* default settings */ + add_tempo_event(-2, 120.0); + add_meter_event(-2, 4, 4); + init_track(); + + /* standard tonalities */ + set_block_d("CM", "A"); + set_block_d("Am", "$CM"); + set_block_d("C#M", "A#######"); + set_block_d("A#m", "$C#M"); + set_block_d("DM", "A#--#---"); + set_block_d("Bm", "$DM"); + set_block_d("E&M", "A--&--&&"); + set_block_d("Cm", "$E&M"); + set_block_d("EM", "A##-##--"); + set_block_d("C#m", "$EM"); + set_block_d("FM", "A------&"); + set_block_d("Dm", "$FM"); + set_block_d("F#M", "A######-"); + set_block_d("D#m", "$F#M"); + set_block_d("GM", "A---#---"); + set_block_d("Em", "$GM"); + set_block_d("A&M", "A-&&--&&"); + set_block_d("Fm", "$A&M"); + set_block_d("AM", "A#--##--"); + set_block_d("F#m", "$AM"); + set_block_d("B&M", "A--&---&"); + set_block_d("Gm", "$B&M"); + set_block_d("BM", "A##-###-"); + set_block_d("G#m", "$BM"); } static int do_parse(void) { - int r = yyparse() + compiler_error; + int r = yyparse() + compiler_error; - if (solo_track != -1) - mute_tracks(-solo_track); + if (solo_track != -1) + mute_tracks(-solo_track); - return r; + return r; } -int compile_ahs_string(const char * code) +int compile_ahs_string(const char *code) { - compile_startup(); + compile_startup(); - push_code(strdup(code)); + push_code(strdup(code)); - return do_parse(); + return do_parse(); } -int compile_ahs(const char * file) +int compile_ahs(const char *file) { - compile_startup(); + compile_startup(); - if (insert_file(file)) - return 1; + if (insert_file(file)) + return 1; - return do_parse(); + return do_parse(); } diff --git a/main.c b/main.c dissimilarity index 78% index 66e98a5..35b32c7 100644 --- a/main.c +++ b/main.c @@ -1,261 +1,267 @@ -/* - - Ann Hell Ex Machina - Music Software - Copyright (C) 2003/2008 Angel Ortega - - main.c - Miscellaneous functions and startup - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.triptico.com - -*/ - -#include "config.h" - -#include -#include -#include -#include - -#include "ahxm.h" - -/******************* - Data -********************/ - -/* output information */ - -static char *devfile = NULL; -static char *driver = "default"; - -/* seconds to skip */ -static int skip_secs = 0; - -/******************* - Code -********************/ - -static void read_config(void) -{ -} - - -static int main_usage(void) -{ - printf("Ann Hell Ex Machina %s - Music Writing Software\n", VERSION); - printf("Copyright (C) 2003-2008 Angel Ortega \n"); - printf("This software is covered by the GPL license. NO WARRANTY.\n\n"); - printf("Usage: ahxm [options] {script.ahs}\n\n"); - printf("Options:\n\n"); - printf("-o {output file or device} Set output file [default: driver dependent].\n"); - printf("-d {driver} Output driver [default: 'default'].\n"); - printf("-L {path} Add path to script / data library search path.\n"); - printf("-r {sampling rate} Set sampling rate [default: %d]\n", ss_frequency); - printf("-c {# of channels} Force number of channels [default: use all]\n"); - printf("-v {master volume} Set master volume [default: %02.02f]\n", - ss_master_volume); - printf("-s {seconds to skip} Seconds to skip from the start of the song.\n"); - printf(" [default: 0, start from the beginning]\n"); - printf("-z {track number} Play track number in a solo\n"); - printf("-i {interpolation} Set interpolation algorithm\n"); - printf(" (0, none; 1, linear; 2, cubic spline,\n"); - printf(" 3, Lagrange) [default: %d]\n", ss_interpolation); - printf("-b {size in frames} Set maximum wave buffer size in frames, so\n"); - printf(" wave files bigger than this will be paged\n"); - printf(" (-1, load full wave in memory) [default: %d]\n", - ss_page_size); - printf("-D {number} Verbosity level (0-3) [default: %d].\n", verbose); - printf("-C {cue file name} Generate .cue file.\n"); - printf("-T Show tracing information.\n"); - printf - ("-M Output song to MIDI device instead of softsynth.\n"); - printf("-I Interactive; read from MIDI device and\n"); - printf(" use {script} as instrument (UNIMPLEMENTED).\n"); - printf("\n"); - printf("Internal sample size: %d bytes (floating point)\n", (int) sizeof(sample_t)); - printf("Library path: "); - libpath_print(); - printf("\n"); - - return 1; -} - - -static int main_interactive(char *script_or_ins) -{ - printf("UNIMPLEMENTED; use the 'midiin' program instead.\n"); - return 0; -} - - -static int main_midi(char *script) -{ - if (compile_ahs(script)) - return 3; - - if (midi_device_open(devfile) < 0) { - printf("Error: can't open MIDI device\n"); - return 2; - } - - midi_song_play(skip_secs); - - midi_device_close(); - - return 0; -} - - -static int main_ss(char *script) -{ - char *ptr; - - /* is it an .sf2? create an ad-hoc mini program to list it */ - if ((ptr = strrchr(script, '.')) != NULL && strcmp(ptr, ".sf2") == 0) { - char tmp[4096]; - - snprintf(tmp, sizeof(tmp), "{ sf2 \"%s\" }", script); - if (compile_ahs_string(tmp)) - return 4; - } - else - if (compile_ahs(script)) - return 3; - - ss_song_render(skip_secs, driver, devfile); - - if (verbose >= 1) - printf("clipped: %d optimal volume: %f\n", - ss_output_clipped, ss_optimal_volume); - - return 0; -} - - -static int ahxm_main(int argc, char *argv[]) -{ - int ret = 1; - int n = 1; - char *opt = NULL; - char *script = NULL; - int midi = 0; - int interactive = 0; - - read_config(); - - /* default path */ - libpath_add("~/ahxmlib", 0); - - /* specific converters */ - transconv_add(".flac", ".wav", "flac -d -s -o '%s' '%s'"); - transconv_add(".mp3", ".wav", "mpg321 -q -w '%s' '%s'"); - - /* fallout converter */ - transconv_add(".*", ".wav", "ffmpeg '%s' -i '%s'"); - - if (argc == 1) - return main_usage(); - - while (n < argc - 1) { - opt = argv[n++]; - - if (strcmp(opt, "-o") == 0) { - /* set output device or file */ - devfile = argv[n++]; - } - else if (strcmp(opt, "-d") == 0) { - /* set driver */ - driver = argv[n++]; - } - else if (strcmp(opt, "-L") == 0) { - /* add path to library */ - libpath_add(argv[n++], 0); - } - else if (strcmp(opt, "-r") == 0) { - /* set sampling rate */ - ss_frequency = atoi(argv[n++]); - } - else if (strcmp(opt, "-c") == 0) { - /* set number of channels */ - ss_nchannels = atoi(argv[n++]); - } - else if (strcmp(opt, "-v") == 0) { - /* set master volume */ - ss_master_volume = (double) atof(argv[n++]); - } - else if (strcmp(opt, "-i") == 0) { - /* set interpolation type */ - ss_interpolation = atoi(argv[n++]); - } - else if (strcmp(opt, "-s") == 0) { - /* seconds to skip */ - skip_secs = atoi(argv[n++]); - } - else if (strcmp(opt, "-I") == 0) { - /* activate interactive mode */ - interactive = 1; - } - else if (strcmp(opt, "-M") == 0) { - /* activate MIDI mode */ - midi = 1; - } - else if (strcmp(opt, "-z") == 0) { - /* set solo track */ - solo_track = atoi(argv[n++]); - } - else if (strcmp(opt, "-b") == 0) { - /* set page size */ - ss_page_size = atoi(argv[n++]); - - /* if it's -1, set as 'no limit' */ - if (ss_page_size < 0) - ss_page_size = INT_MAX; - } - else if (strcmp(opt, "-D") == 0) { - /* debug information */ - verbose = atoi(argv[n++]); - } - else if (strcmp(opt, "-C") == 0) { - /* set cue file name */ - ss_cue_file_name = argv[n++]; - } - else if (strcmp(opt, "-T") == 0) - trace = 1; - else - return main_usage(); - - } - - script = argv[argc - 1]; - - if (*script == '-') - return main_usage(); - - if (interactive) - ret = main_interactive(script); - else if (midi) - ret = main_midi(script); - else - ret = main_ss(script); - - return ret; -} - - -int main(int argc, char *argv[]) -{ - return ahxm_main(argc, argv); -} +/* + + Ann Hell Ex Machina - Music Software + Copyright (C) 2003/2008 Angel Ortega + + main.c - Miscellaneous functions and startup + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.triptico.com + +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include "ahxm.h" + + +/** data **/ + +/* output information */ + +static char *devfile = NULL; +static char *driver = "default"; + +/* seconds to skip */ +static int skip_secs = 0; + + +/** code **/ + +static void read_config(void) +{ +} + + +static int main_usage(void) +{ + printf("Ann Hell Ex Machina %s - Music Writing Software\n", VERSION); + printf("Copyright (C) 2003-2008 Angel Ortega \n"); + printf("This software is covered by the GPL license. NO WARRANTY.\n\n"); + printf("Usage: ahxm [options] {script.ahs}\n\n"); + printf("Options:\n\n"); + printf("-o {output file or device} Set output file [default: driver dependent].\n"); + printf("-d {driver} Output driver [default: 'default'].\n"); + printf("-L {path} Add path to script / data library search path.\n"); + printf("-r {sampling rate} Set sampling rate [default: %d]\n", + ss_frequency); + printf("-c {# of channels} Force number of channels [default: use all]\n"); + printf("-v {master volume} Set master volume [default: %02.02f]\n", + ss_master_volume); + printf("-s {seconds to skip} Seconds to skip from the start of the song.\n"); + printf(" [default: 0, start from the beginning]\n"); + printf("-z {track number} Play track number in a solo\n"); + printf("-i {interpolation} Set interpolation algorithm\n"); + printf(" (0, none; 1, linear; 2, cubic spline,\n"); + printf(" 3, Lagrange) [default: %d]\n", + ss_interpolation); + printf + ("-b {size in frames} Set maximum wave buffer size in frames, so\n"); + printf + (" wave files bigger than this will be paged\n"); + printf + (" (-1, load full wave in memory) [default: %d]\n", + ss_page_size); + printf + ("-D {number} Verbosity level (0-3) [default: %d].\n", + verbose); + printf("-C {cue file name} Generate .cue file.\n"); + printf("-T Show tracing information.\n"); + printf + ("-M Output song to MIDI device instead of softsynth.\n"); + printf + ("-I Interactive; read from MIDI device and\n"); + printf + (" use {script} as instrument (UNIMPLEMENTED).\n"); + printf("\n"); + printf("Internal sample size: %d bytes (floating point)\n", + (int) sizeof(sample_t)); + printf("Library path: "); + libpath_print(); + printf("\n"); + + return 1; +} + + +static int main_interactive(char *script_or_ins) +{ + printf("UNIMPLEMENTED; use the 'midiin' program instead.\n"); + return 0; +} + + +static int main_midi(char *script) +{ + if (compile_ahs(script)) + return 3; + + if (midi_device_open(devfile) < 0) { + printf("Error: can't open MIDI device\n"); + return 2; + } + + midi_song_play(skip_secs); + + midi_device_close(); + + return 0; +} + + +static int main_ss(char *script) +{ + char *ptr; + + /* is it an .sf2? create an ad-hoc mini program to list it */ + if ((ptr = strrchr(script, '.')) != NULL && strcmp(ptr, ".sf2") == 0) { + char tmp[4096]; + + snprintf(tmp, sizeof(tmp), "{ sf2 \"%s\" }", script); + if (compile_ahs_string(tmp)) + return 4; + } + else if (compile_ahs(script)) + return 3; + + ss_song_render(skip_secs, driver, devfile); + + if (verbose >= 1) + printf("clipped: %d optimal volume: %f\n", + ss_output_clipped, ss_optimal_volume); + + return 0; +} + + +static int ahxm_main(int argc, char *argv[]) +{ + int ret = 1; + int n = 1; + char *opt = NULL; + char *script = NULL; + int midi = 0; + int interactive = 0; + + read_config(); + + /* default path */ + libpath_add("~/ahxmlib", 0); + + /* specific converters */ + transconv_add(".flac", ".wav", "flac -d -s -o '%s' '%s'"); + transconv_add(".mp3", ".wav", "mpg321 -q -w '%s' '%s'"); + + /* fallout converter */ + transconv_add(".*", ".wav", "ffmpeg '%s' -i '%s'"); + + if (argc == 1) + return main_usage(); + + while (n < argc - 1) { + opt = argv[n++]; + + if (strcmp(opt, "-o") == 0) { + /* set output device or file */ + devfile = argv[n++]; + } + else if (strcmp(opt, "-d") == 0) { + /* set driver */ + driver = argv[n++]; + } + else if (strcmp(opt, "-L") == 0) { + /* add path to library */ + libpath_add(argv[n++], 0); + } + else if (strcmp(opt, "-r") == 0) { + /* set sampling rate */ + ss_frequency = atoi(argv[n++]); + } + else if (strcmp(opt, "-c") == 0) { + /* set number of channels */ + ss_nchannels = atoi(argv[n++]); + } + else if (strcmp(opt, "-v") == 0) { + /* set master volume */ + ss_master_volume = (double) atof(argv[n++]); + } + else if (strcmp(opt, "-i") == 0) { + /* set interpolation type */ + ss_interpolation = atoi(argv[n++]); + } + else if (strcmp(opt, "-s") == 0) { + /* seconds to skip */ + skip_secs = atoi(argv[n++]); + } + else if (strcmp(opt, "-I") == 0) { + /* activate interactive mode */ + interactive = 1; + } + else if (strcmp(opt, "-M") == 0) { + /* activate MIDI mode */ + midi = 1; + } + else if (strcmp(opt, "-z") == 0) { + /* set solo track */ + solo_track = atoi(argv[n++]); + } + else if (strcmp(opt, "-b") == 0) { + /* set page size */ + ss_page_size = atoi(argv[n++]); + + /* if it's -1, set as 'no limit' */ + if (ss_page_size < 0) + ss_page_size = INT_MAX; + } + else if (strcmp(opt, "-D") == 0) { + /* debug information */ + verbose = atoi(argv[n++]); + } + else if (strcmp(opt, "-C") == 0) { + /* set cue file name */ + ss_cue_file_name = argv[n++]; + } + else if (strcmp(opt, "-T") == 0) + trace = 1; + else + return main_usage(); + } + + script = argv[argc - 1]; + + if (*script == '-') + return main_usage(); + + if (interactive) + ret = main_interactive(script); + else if (midi) + ret = main_midi(script); + else + ret = main_ss(script); + + return ret; +} + + +int main(int argc, char *argv[]) +{ + return ahxm_main(argc, argv); +} diff --git a/midi_song.c b/midi_song.c dissimilarity index 72% index e36f3b7..2be1f33 100644 --- a/midi_song.c +++ b/midi_song.c @@ -1,378 +1,375 @@ -/* - - Ann Hell Ex Machina - Music Software - Copyright (C) 2003/2008 Angel Ortega - - midi_song.c - MIDI song event stream management - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.triptico.com - -*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ahxm.h" - -/******************* - Data -********************/ - -/* the MIDI song stream */ - -static struct song_ev *midi_song = NULL; -static int n_midi_ev = 0; - -/* the MIDI tracks: just a track/channel table */ - -#define MIDI_TRACK_NUM 256 -static int track_channel[MIDI_TRACK_NUM]; - -/* MIDI message types */ - -#define MIDI_MSG_NOTE_ON 0x90 -#define MIDI_MSG_NOTE_OFF 0x80 -#define MIDI_MSG_CONTROLLER 0xB0 -#define MIDI_MSG_PROGRAM 0xC0 - -/* MIDI device fd */ -int midi_fd = -1; - - -/******************* - Code -********************/ - -static struct song_ev * add_midi_ev(struct song_ev *e) -/* adds a MIDI song event */ -{ - if (e->channel < 0) - return NULL; - - return copy_event(&midi_song, &n_midi_ev, e); -} - - -static int msecs_type_cmp(const void *v1, const void *v2) -/* MIDI song event compare function for qsort(), by time (for playing) */ -{ - struct song_ev *e1; - struct song_ev *e2; - - e1 = (struct song_ev *) v1; - e2 = (struct song_ev *) v2; - - if (e1->msecs == e2->msecs) - return e1->type - e2->type; - - return e1->msecs - e2->msecs; -} - - -static void midi_song_convert_events(void) -/* converts generic song_ev events to MIDI events */ -{ - struct song_ev *e; - int msecs, msecs_ac, f_msecs; - double time_ac, time_ac_m; - int num, den; - double mspw; - int n; - - /* resets the MIDI stream */ - if (midi_song != NULL) { - free(midi_song); - midi_song = NULL; - } - - n_midi_ev = 0; - - /* sorts the song */ - song_sort(); - - mspw = 0; - msecs = msecs_ac = f_msecs = 0; - time_ac = time_ac_m = 0; - num = den = 4; - - /* by default, all channels are 'mute' until - a channel is explicitly set */ - for (n = 0; n < MIDI_TRACK_NUM; n++) - track_channel[n] = -1; - - /* travels the song events generating MIDI song events */ - for (n = 0; n < n_song_ev; n++) { - /* gets the song event */ - e = &song[n]; - - /* calculates the msecs */ - msecs = ((e->time - time_ac) * mspw) + msecs_ac; - e->msecs = msecs; - - /* if it's not a generic message, set MIDI channel */ - if (e->trk_id >= 0) - e->channel = track_channel[e->trk_id]; - - switch (e->type) { - case SONG_EV_TEMPO: - - /* updates accumulations */ - msecs_ac = msecs; - time_ac = e->time; - - /* calculates milliseconds-per-whole based on new tempo */ - mspw = 1000.0 * 60.0; - mspw /= (e->amount / 4.0); - - break; - - case SONG_EV_METER: - - /* just store the values */ - num = e->min; - den = e->max; - time_ac_m = e->time; - - break; - - case SONG_EV_MEASURE: - - song_test_measure_boundary(e->time - time_ac_m, - num, den, e->value); - break; - - case SONG_EV_MIDI_CHANNEL: - - /* stores the channel for this track */ - track_channel[e->trk_id] = e->channel; - break; - - case SONG_EV_NOTE: - - /* convert to note on / off pairs */ - - e->vel = (int) (e->vol * 127.0); - - add_midi_ev(e); - - e = add_midi_ev(e); - e->type = SONG_EV_NOTE_OFF; - - msecs += (int) (e->len * mspw); - e->msecs = msecs; - - break; - - case SONG_EV_BACK: - - /* move the cursor back */ - msecs_ac -= (int) (e->len * mspw); - break; - - case SONG_EV_MIDI_PROGRAM: - - add_midi_ev(e); - break; - - case SONG_EV_SS_PITCH_STRETCH: - case SONG_EV_SS_PRINT_WAVE_TEMPO: - case SONG_EV_SS_WAV: - case SONG_EV_SS_PAT: - case SONG_EV_SS_SF2: - case SONG_EV_SS_SUSTAIN: - case SONG_EV_SS_ATTACK: - case SONG_EV_SS_VIBRATO: - case SONG_EV_SS_PORTAMENTO: - case SONG_EV_SS_CHANNEL: - case SONG_EV_SS_EFF_DELAY: - case SONG_EV_SS_EFF_ECHO: - case SONG_EV_SS_EFF_COMB: - case SONG_EV_SS_EFF_ALLPASS: - case SONG_EV_SS_EFF_FLANGER: - case SONG_EV_SS_EFF_WOBBLE: - case SONG_EV_SS_EFF_SQWOBBLE: - case SONG_EV_SS_EFF_HFWOBBLE: - case SONG_EV_SS_EFF_FADER: - case SONG_EV_SS_EFF_REVERB: - case SONG_EV_SS_EFF_FOLDBACK: - case SONG_EV_SS_EFF_ATAN: - case SONG_EV_SS_EFF_DISTORT: - case SONG_EV_SS_EFF_OVERDRIVE: - case SONG_EV_SS_EFF_OFF: - case SONG_EV_SS_MASTER_VOLUME: - case SONG_EV_NOP: - - /* ignored */ - break; - - case SONG_EV_SONG_INFO: - - /* song info should be used */ - break; - - case SONG_EV_EOT: - - /* end of track; trigger possible cleaning */ - break; - - case SONG_EV_NOTE_OFF: - case SONG_EV_END: - - /* never found in generic song streams */ - break; - } - - /* store the further time seen */ - if (f_msecs < msecs) - f_msecs = msecs; - } - - /* generates an end of event mark, a time after the last one */ - e = add_event(&midi_song, &n_midi_ev); - - e->type = SONG_EV_END; - e->msecs = f_msecs + 1000; -} - - -int midi_song_play(int skip_secs) -{ -#ifdef CONFOPT_NANOSLEEP - struct song_ev *e; - int msecs, msecs_p, msecs_d; - int go; - struct timespec ts; - unsigned char midimsg[1024]; - int mi; - int skip_msecs; - - /* convert the song to MIDI events */ - midi_song_convert_events(); - - /* sort by time */ - qsort(midi_song, n_midi_ev, sizeof(struct song_ev), msecs_type_cmp); - - msecs = msecs_p = 0; - go = 1; - e = midi_song; - - /* calculate the millisecond to start playing */ - skip_msecs = skip_secs * 1000; - - /* loop the events */ - while (go) { - /* clear buffer */ - mi = 0; - - if (verbose >= 1 && msecs % 1000 == 0) { - int m = msecs / 1000; - printf("[%02d:%02d]\r", m / 60, m % 60); - fflush(stdout); - } - - /* process all events for this exact time */ - while (e->msecs == msecs) { - switch (e->type) { - case SONG_EV_NOTE: - - midimsg[mi++] = MIDI_MSG_NOTE_ON | e->channel; - midimsg[mi++] = e->value; - midimsg[mi++] = e->vel; - - break; - - case SONG_EV_NOTE_OFF: - - midimsg[mi++] = MIDI_MSG_NOTE_OFF | e->channel; - midimsg[mi++] = e->value; - midimsg[mi++] = 0; - - break; - - case SONG_EV_MIDI_PROGRAM: - - midimsg[mi++] = MIDI_MSG_PROGRAM | e->channel; - midimsg[mi++] = e->value; - - break; - - case SONG_EV_END: - - go = 0; - break; - - default: - /* ignore the rest */ - break; - } - - /* next event */ - e++; - } - - if (!go) - break; - - /* get time of next event */ - msecs_p = msecs; - msecs = e->msecs; - msecs_d = msecs - msecs_p; - - if (msecs >= skip_msecs) { - /* if there are pending messages, write them */ - if (mi) - write(midi_fd, midimsg, mi); - - /* calculate the time to sleep */ - ts.tv_sec = (time_t) msecs_d / 1000; - ts.tv_nsec = (long) ((msecs_d * 1000000) % 1000000000); - - nanosleep(&ts, NULL); - } - } - - if (verbose >= 1) - printf("\n"); - -#endif /* CONFOPT_NANOSLEEP */ - - return 0; -} - - -int midi_device_open(char *devfile) -{ - if (devfile == NULL) - devfile = "/dev/midi"; - - return (midi_fd = open(devfile, O_WRONLY)); -} - - -void midi_device_close(void) -{ - close(midi_fd); -} +/* + + Ann Hell Ex Machina - Music Software + Copyright (C) 2003/2008 Angel Ortega + + midi_song.c - MIDI song event stream management + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.triptico.com + +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ahxm.h" + + +/** data **/ + +/* the MIDI song stream */ + +static struct song_ev *midi_song = NULL; +static int n_midi_ev = 0; + +/* the MIDI tracks: just a track/channel table */ + +#define MIDI_TRACK_NUM 256 +static int track_channel[MIDI_TRACK_NUM]; + +/* MIDI message types */ + +#define MIDI_MSG_NOTE_ON 0x90 +#define MIDI_MSG_NOTE_OFF 0x80 +#define MIDI_MSG_CONTROLLER 0xB0 +#define MIDI_MSG_PROGRAM 0xC0 + +/* MIDI device fd */ +int midi_fd = -1; + + +/** code **/ + +static struct song_ev *add_midi_ev(struct song_ev *e) +/* adds a MIDI song event */ +{ + if (e->channel < 0) + return NULL; + + return copy_event(&midi_song, &n_midi_ev, e); +} + + +static int msecs_type_cmp(const void *v1, const void *v2) +/* MIDI song event compare function for qsort(), by time (for playing) */ +{ + struct song_ev *e1; + struct song_ev *e2; + + e1 = (struct song_ev *) v1; + e2 = (struct song_ev *) v2; + + if (e1->msecs == e2->msecs) + return e1->type - e2->type; + + return e1->msecs - e2->msecs; +} + + +static void midi_song_convert_events(void) +/* converts generic song_ev events to MIDI events */ +{ + struct song_ev *e; + int msecs, msecs_ac, f_msecs; + double time_ac, time_ac_m; + int num, den; + double mspw; + int n; + + /* resets the MIDI stream */ + if (midi_song != NULL) { + free(midi_song); + midi_song = NULL; + } + + n_midi_ev = 0; + + /* sorts the song */ + song_sort(); + + mspw = 0; + msecs = msecs_ac = f_msecs = 0; + time_ac = time_ac_m = 0; + num = den = 4; + + /* by default, all channels are 'mute' until + a channel is explicitly set */ + for (n = 0; n < MIDI_TRACK_NUM; n++) + track_channel[n] = -1; + + /* travels the song events generating MIDI song events */ + for (n = 0; n < n_song_ev; n++) { + /* gets the song event */ + e = &song[n]; + + /* calculates the msecs */ + msecs = ((e->time - time_ac) * mspw) + msecs_ac; + e->msecs = msecs; + + /* if it's not a generic message, set MIDI channel */ + if (e->trk_id >= 0) + e->channel = track_channel[e->trk_id]; + + switch (e->type) { + case SONG_EV_TEMPO: + + /* updates accumulations */ + msecs_ac = msecs; + time_ac = e->time; + + /* calculates milliseconds-per-whole based on new tempo */ + mspw = 1000.0 * 60.0; + mspw /= (e->amount / 4.0); + + break; + + case SONG_EV_METER: + + /* just store the values */ + num = e->min; + den = e->max; + time_ac_m = e->time; + + break; + + case SONG_EV_MEASURE: + + song_test_measure_boundary(e->time - time_ac_m, + num, den, e->value); + break; + + case SONG_EV_MIDI_CHANNEL: + + /* stores the channel for this track */ + track_channel[e->trk_id] = e->channel; + break; + + case SONG_EV_NOTE: + + /* convert to note on / off pairs */ + + e->vel = (int) (e->vol * 127.0); + + add_midi_ev(e); + + e = add_midi_ev(e); + e->type = SONG_EV_NOTE_OFF; + + msecs += (int) (e->len * mspw); + e->msecs = msecs; + + break; + + case SONG_EV_BACK: + + /* move the cursor back */ + msecs_ac -= (int) (e->len * mspw); + break; + + case SONG_EV_MIDI_PROGRAM: + + add_midi_ev(e); + break; + + case SONG_EV_SS_PITCH_STRETCH: + case SONG_EV_SS_PRINT_WAVE_TEMPO: + case SONG_EV_SS_WAV: + case SONG_EV_SS_PAT: + case SONG_EV_SS_SF2: + case SONG_EV_SS_SUSTAIN: + case SONG_EV_SS_ATTACK: + case SONG_EV_SS_VIBRATO: + case SONG_EV_SS_PORTAMENTO: + case SONG_EV_SS_CHANNEL: + case SONG_EV_SS_EFF_DELAY: + case SONG_EV_SS_EFF_ECHO: + case SONG_EV_SS_EFF_COMB: + case SONG_EV_SS_EFF_ALLPASS: + case SONG_EV_SS_EFF_FLANGER: + case SONG_EV_SS_EFF_WOBBLE: + case SONG_EV_SS_EFF_SQWOBBLE: + case SONG_EV_SS_EFF_HFWOBBLE: + case SONG_EV_SS_EFF_FADER: + case SONG_EV_SS_EFF_REVERB: + case SONG_EV_SS_EFF_FOLDBACK: + case SONG_EV_SS_EFF_ATAN: + case SONG_EV_SS_EFF_DISTORT: + case SONG_EV_SS_EFF_OVERDRIVE: + case SONG_EV_SS_EFF_OFF: + case SONG_EV_SS_MASTER_VOLUME: + case SONG_EV_NOP: + + /* ignored */ + break; + + case SONG_EV_SONG_INFO: + + /* song info should be used */ + break; + + case SONG_EV_EOT: + + /* end of track; trigger possible cleaning */ + break; + + case SONG_EV_NOTE_OFF: + case SONG_EV_END: + + /* never found in generic song streams */ + break; + } + + /* store the further time seen */ + if (f_msecs < msecs) + f_msecs = msecs; + } + + /* generates an end of event mark, a time after the last one */ + e = add_event(&midi_song, &n_midi_ev); + + e->type = SONG_EV_END; + e->msecs = f_msecs + 1000; +} + + +int midi_song_play(int skip_secs) +{ +#ifdef CONFOPT_NANOSLEEP + struct song_ev *e; + int msecs, msecs_p, msecs_d; + int go; + struct timespec ts; + unsigned char midimsg[1024]; + int mi; + int skip_msecs; + + /* convert the song to MIDI events */ + midi_song_convert_events(); + + /* sort by time */ + qsort(midi_song, n_midi_ev, sizeof(struct song_ev), msecs_type_cmp); + + msecs = msecs_p = 0; + go = 1; + e = midi_song; + + /* calculate the millisecond to start playing */ + skip_msecs = skip_secs * 1000; + + /* loop the events */ + while (go) { + /* clear buffer */ + mi = 0; + + if (verbose >= 1 && msecs % 1000 == 0) { + int m = msecs / 1000; + printf("[%02d:%02d]\r", m / 60, m % 60); + fflush(stdout); + } + + /* process all events for this exact time */ + while (e->msecs == msecs) { + switch (e->type) { + case SONG_EV_NOTE: + + midimsg[mi++] = MIDI_MSG_NOTE_ON | e->channel; + midimsg[mi++] = e->value; + midimsg[mi++] = e->vel; + + break; + + case SONG_EV_NOTE_OFF: + + midimsg[mi++] = MIDI_MSG_NOTE_OFF | e->channel; + midimsg[mi++] = e->value; + midimsg[mi++] = 0; + + break; + + case SONG_EV_MIDI_PROGRAM: + + midimsg[mi++] = MIDI_MSG_PROGRAM | e->channel; + midimsg[mi++] = e->value; + + break; + + case SONG_EV_END: + + go = 0; + break; + + default: + /* ignore the rest */ + break; + } + + /* next event */ + e++; + } + + if (!go) + break; + + /* get time of next event */ + msecs_p = msecs; + msecs = e->msecs; + msecs_d = msecs - msecs_p; + + if (msecs >= skip_msecs) { + /* if there are pending messages, write them */ + if (mi) + write(midi_fd, midimsg, mi); + + /* calculate the time to sleep */ + ts.tv_sec = (time_t) msecs_d / 1000; + ts.tv_nsec = (long) ((msecs_d * 1000000) % 1000000000); + + nanosleep(&ts, NULL); + } + } + + if (verbose >= 1) + printf("\n"); + +#endif /* CONFOPT_NANOSLEEP */ + + return 0; +} + + +int midi_device_open(char *devfile) +{ + if (devfile == NULL) + devfile = "/dev/midi"; + + return (midi_fd = open(devfile, O_WRONLY)); +} + + +void midi_device_close(void) +{ + close(midi_fd); +} diff --git a/midiin.c b/midiin.c index 2c2dd6b..cad5054 100644 --- a/midiin.c +++ b/midiin.c @@ -36,9 +36,8 @@ #include "ahxm.h" -/******************* - Data -********************/ + +/** data **/ #define MIDI_NOTE_OFF 0x80 #define MIDI_NOTE_ON 0x90 @@ -64,141 +63,141 @@ int i_msg = 0; /* use the instruments in ss_ins */ extern struct ss_ins ss_song_ins[256]; -/******************* - Code -********************/ + +/** code **/ void print_note(int note) { - static int octave = -1; - int o, d, n; - char *notestr[] = { - "c", "c#", "d", "d#", "e", "f", - "f#", "g", "g#", "a", "a#", "b" - }; - - o = note / 12; - n = note % 12; - - if (octave == -1 || (d = (octave - o)) > 1 || d < -1) { - /* first time or octave too far; set it */ - octave = o; - printf("o%d ", o); - d = 0; - } - - printf("%s%s ", notestr[n], (d == -1 ? "'" : (d == 1 ? "," : ""))); - - fflush(stdout); + static int octave = -1; + int o, d, n; + char *notestr[] = { + "c", "c#", "d", "d#", "e", "f", + "f#", "g", "g#", "a", "a#", "b" + }; + + o = note / 12; + n = note % 12; + + if (octave == -1 || (d = (octave - o)) > 1 || d < -1) { + /* first time or octave too far; set it */ + octave = o; + printf("o%d ", o); + d = 0; + } + + printf("%s%s ", notestr[n], (d == -1 ? "'" : (d == 1 ? "," : ""))); + + fflush(stdout); } void process_MIDI(void) { - /* strip MIDI channel */ - midimsg[0] &= 0xf0; + /* strip MIDI channel */ + midimsg[0] &= 0xf0; - if (midimsg[0] == MIDI_NOTE_OFF) - ss_ins_note_off(&ss_song_ins[0], midimsg[1]); - else if (midimsg[0] == MIDI_NOTE_ON) { - ss_ins_note_on(&ss_song_ins[0], midimsg[1], - ((sample_t) midimsg[2]) / 127.0, midimsg[1]); + if (midimsg[0] == MIDI_NOTE_OFF) + ss_ins_note_off(&ss_song_ins[0], midimsg[1]); + else if (midimsg[0] == MIDI_NOTE_ON) { + ss_ins_note_on(&ss_song_ins[0], midimsg[1], + ((sample_t) midimsg[2]) / 127.0, midimsg[1]); - print_note(midimsg[1]); - } + print_note(midimsg[1]); + } - i_msg = 0; + i_msg = 0; } void midiin(void) { - unsigned char midibuf[128]; - int c, n; - sample_t sample[2]; - - for (;;) { - /* read from MIDI device */ - c = read(midi_fd, midibuf, sizeof(midibuf)); - - if (c > 0) { - for (n = 0; n < c; n++) { - /* if 7bit of input is set, - it's a start of MIDI message */ - if ((midibuf[n] & 0x80) && i_msg) - process_MIDI(); - - midimsg[i_msg++] = midibuf[n]; - } - } - - ss_output_init_frame(sample); - ss_ins_frame(&ss_song_ins[0], sample); - ss_output_write(sample); - } + unsigned char midibuf[128]; + int c, n; + sample_t sample[2]; + + for (;;) { + /* read from MIDI device */ + c = read(midi_fd, midibuf, sizeof(midibuf)); + + if (c > 0) { + for (n = 0; n < c; n++) { + /* if 7bit of input is set, + it's a start of MIDI message */ + if ((midibuf[n] & 0x80) && i_msg) + process_MIDI(); + + midimsg[i_msg++] = midibuf[n]; + } + } + + ss_output_init_frame(sample); + ss_ins_frame(&ss_song_ins[0], sample); + ss_output_write(sample); + } } int main(int argc, char *argv[]) { - char *ext; + char *ext; - ss_interpolation = 1; - ss_frequency = 44100; - ss_master_volume = 1; - ss_nchannels = 2; + ss_interpolation = 1; + ss_frequency = 44100; + ss_master_volume = 1; + ss_nchannels = 2; - libpath_add("~/ahxmlib", 0); + libpath_add("~/ahxmlib", 0); - /* default converters */ - transconv_add(".flac", ".wav", "flac -d -s -o '%s' '%s'"); - transconv_add(".mp3", ".wav", "mpg321 -q -w '%s' '%s'"); + /* default converters */ + transconv_add(".flac", ".wav", "flac -d -s -o '%s' '%s'"); + transconv_add(".mp3", ".wav", "mpg321 -q -w '%s' '%s'"); - if (argc == 0) { - printf("Usage:\n"); - printf("midiin [instrument.pat] [midi device]\n"); - return 1; - } + if (argc == 0) { + printf("Usage:\n"); + printf("midiin [instrument.pat] [midi device]\n"); + return 1; + } - if (argc > 1) - strcpy(instrument, argv[1]); + if (argc > 1) + strcpy(instrument, argv[1]); - if (argc > 2) - strcpy(midi_dev, argv[2]); + if (argc > 2) + strcpy(midi_dev, argv[2]); - ss_gen_init(); + ss_gen_init(); - /* loads the instrument or bangs */ - ss_ins_init(&ss_song_ins[0]); + /* loads the instrument or bangs */ + ss_ins_init(&ss_song_ins[0]); - if ((ext = strchr(instrument, '.')) == NULL) { - printf("The instrument '%s' doesn't have an extension\n", instrument); - return 2; - } + if ((ext = strchr(instrument, '.')) == NULL) { + printf("The instrument '%s' doesn't have an extension\n", + instrument); + return 2; + } - if (strcmp(ext, ".pat") == 0 || strcmp(ext, ".PAT") == 0) { - if (ss_load_pat_file(&ss_song_ins[0], instrument) < 0) { - printf("Error loading '%s'\n", instrument); - return 2; - } - } - else { - if (compile_ahs(instrument)) - return 2; + if (strcmp(ext, ".pat") == 0 || strcmp(ext, ".PAT") == 0) { + if (ss_load_pat_file(&ss_song_ins[0], instrument) < 0) { + printf("Error loading '%s'\n", instrument); + return 2; + } + } + else { + if (compile_ahs(instrument)) + return 2; - if (ss_song_render(0, "default", NULL)) - return 4; - } + if (ss_song_render(0, "default", NULL)) + return 4; + } - /* opens the MIDI channel */ - if ((midi_fd = open(midi_dev, O_RDONLY | O_NONBLOCK)) == -1) { - printf("Error opening midi device '%s'\n", midi_dev); - return 3; - } + /* opens the MIDI channel */ + if ((midi_fd = open(midi_dev, O_RDONLY | O_NONBLOCK)) == -1) { + printf("Error opening midi device '%s'\n", midi_dev); + return 3; + } - midiin(); + midiin(); - ss_output_close(); + ss_output_close(); - return 0; + return 0; } diff --git a/sha1.c b/sha1.c dissimilarity index 64% index 7f6fc05..2d4cdb9 100644 --- a/sha1.c +++ b/sha1.c @@ -1,152 +1,177 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - * Paul Kocher - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include "sha1.h" - -static void shaHashBlock(SHA_CTX *ctx); - -void SHA1_Init(SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301; - ctx->H[1] = 0xefcdab89; - ctx->H[2] = 0x98badcfe; - ctx->H[3] = 0x10325476; - ctx->H[4] = 0xc3d2e1f0; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void SHA1_Update(SHA_CTX *ctx, void *_dataIn, int len) { - unsigned char *dataIn = _dataIn; - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - SHA1_Update(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - SHA1_Update(ctx, &pad0x00, 1); - SHA1_Update(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - SHA1_Init(ctx); -} - - -#define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n)))) - -static void shaHashBlock(SHA_CTX *ctx) { - int t; - unsigned int A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROT(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = SHA_ROT(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999; - E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = SHA_ROT(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1; - E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = SHA_ROT(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdc; - E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = SHA_ROT(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6; - E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is SHA 180-1 Reference Implementation (Compact version) + * + * The Initial Developer of the Original Code is Paul Kocher of + * Cryptography Research. Portions created by Paul Kocher are + * Copyright (C) 1995-9 by Cryptography Research, Inc. All + * Rights Reserved. + * + * Contributor(s): + * + * Paul Kocher + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "sha1.h" + +static void shaHashBlock(SHA_CTX * ctx); + +void SHA1_Init(SHA_CTX * ctx) +{ + int i; + + ctx->lenW = 0; + ctx->sizeHi = ctx->sizeLo = 0; + + /* Initialize H with the magic constants (see FIPS180 for constants) + */ + ctx->H[0] = 0x67452301; + ctx->H[1] = 0xefcdab89; + ctx->H[2] = 0x98badcfe; + ctx->H[3] = 0x10325476; + ctx->H[4] = 0xc3d2e1f0; + + for (i = 0; i < 80; i++) + ctx->W[i] = 0; +} + + +void SHA1_Update(SHA_CTX * ctx, void *_dataIn, int len) +{ + unsigned char *dataIn = _dataIn; + int i; + + /* Read the data into W and process blocks as they get full + */ + for (i = 0; i < len; i++) { + ctx->W[ctx->lenW / 4] <<= 8; + ctx->W[ctx->lenW / 4] |= (unsigned int) dataIn[i]; + if ((++ctx->lenW) % 64 == 0) { + shaHashBlock(ctx); + ctx->lenW = 0; + } + ctx->sizeLo += 8; + ctx->sizeHi += (ctx->sizeLo < 8); + } +} + + +void SHA1_Final(unsigned char hashout[20], SHA_CTX * ctx) +{ + unsigned char pad0x80 = 0x80; + unsigned char pad0x00 = 0x00; + unsigned char padlen[8]; + int i; + + /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length + */ + padlen[0] = (unsigned char) ((ctx->sizeHi >> 24) & 255); + padlen[1] = (unsigned char) ((ctx->sizeHi >> 16) & 255); + padlen[2] = (unsigned char) ((ctx->sizeHi >> 8) & 255); + padlen[3] = (unsigned char) ((ctx->sizeHi >> 0) & 255); + padlen[4] = (unsigned char) ((ctx->sizeLo >> 24) & 255); + padlen[5] = (unsigned char) ((ctx->sizeLo >> 16) & 255); + padlen[6] = (unsigned char) ((ctx->sizeLo >> 8) & 255); + padlen[7] = (unsigned char) ((ctx->sizeLo >> 0) & 255); + SHA1_Update(ctx, &pad0x80, 1); + while (ctx->lenW != 56) + SHA1_Update(ctx, &pad0x00, 1); + SHA1_Update(ctx, padlen, 8); + + /* Output hash + */ + for (i = 0; i < 20; i++) { + hashout[i] = (unsigned char) (ctx->H[i / 4] >> 24); + ctx->H[i / 4] <<= 8; + } + + /* + * Re-initialize the context (also zeroizes contents) + */ + SHA1_Init(ctx); +} + + +#define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n)))) + +static void shaHashBlock(SHA_CTX * ctx) +{ + int t; + unsigned int A, B, C, D, E, TEMP; + + for (t = 16; t <= 79; t++) + ctx->W[t] = + SHA_ROT(ctx->W[t - 3] ^ ctx->W[t - 8] ^ ctx-> + W[t - 14] ^ ctx->W[t - 16], 1); + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + for (t = 0; t <= 19; t++) { + TEMP = + SHA_ROT(A, + 5) + (((C ^ D) & B) ^ D) + E + ctx->W[t] + 0x5a827999; + E = D; + D = C; + C = SHA_ROT(B, 30); + B = A; + A = TEMP; + } + for (t = 20; t <= 39; t++) { + TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0x6ed9eba1; + E = D; + D = C; + C = SHA_ROT(B, 30); + B = A; + A = TEMP; + } + for (t = 40; t <= 59; t++) { + TEMP = + SHA_ROT(A, + 5) + ((B & C) | (D & (B | C))) + E + ctx->W[t] + + 0x8f1bbcdc; + E = D; + D = C; + C = SHA_ROT(B, 30); + B = A; + A = TEMP; + } + for (t = 60; t <= 79; t++) { + TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0xca62c1d6; + E = D; + D = C; + C = SHA_ROT(B, 30); + B = A; + A = TEMP; + } + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} diff --git a/song.c b/song.c dissimilarity index 62% index 6aec244..4a701ea 100644 --- a/song.c +++ b/song.c @@ -1,356 +1,467 @@ -/* - - Ann Hell Ex Machina - Music Software - Copyright (C) 2003/2008 Angel Ortega - - song.c - Device-independent song event stream management - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.triptico.com - -*/ - -#include "config.h" - -#include -#include -#include -#include - -#include "ahxm.h" - -/******************* - Data -********************/ - -/* the song event stream */ -struct song_ev *song = NULL; - -/* number of song events */ -int n_song_ev = 0; - -/* number of tracks in song */ -int n_song_tracks = 0; - -/******************* - Code -********************/ - -/** - * add_event - Adds an event to an event list. - * @song: A pointer to an event list (dynamically allocated) - * @count: A pointer to an integer (number of elements) - * - * Increments the @song event list to fit @count number of - * elements, probably reallocating its memory. - * - * Returns a pointer to the new element. - */ -struct song_ev * add_event(struct song_ev **song, int *count) -{ - struct song_ev * r; - - GROW(*song, *count, struct song_ev); - - r = *song + *count; - memset(r, '\0', sizeof(struct song_ev)); - - (*count)++; - - return r; -} - - -/** - * copy_event - Appends an event to an event list. - * @song: the event list - * @count: a pointer to the number of elements - * @e: the event to be copied - * - * Appends the @e event to the @song event list. - */ -struct song_ev * copy_event(struct song_ev **song, int *count, const struct song_ev *e) -{ - struct song_ev * r = add_event(song, count); - - memcpy(r, e, sizeof(struct song_ev)); - - return r; -} - - -/** - * song_clear - Clears the song stream - * - * Clears the song stream. - */ -void song_clear(void) -{ - if (song != NULL) { - free(song); - song = NULL; - } - - n_song_ev = 0; -} - - -static char * event_name(song_ev_type t) -{ - char * ptr = "UNKNOWN"; - - switch (t) { - case SONG_EV_TEMPO: ptr = "TEMPO--"; break; - case SONG_EV_METER: ptr = "METER--"; break; - case SONG_EV_MEASURE: ptr = "MEASURE"; break; - case SONG_EV_SS_SUSTAIN: ptr = "SUSTAIN"; break; - case SONG_EV_SS_ATTACK: ptr = "ATTACK-"; break; - case SONG_EV_SS_VIBRATO: ptr = "VIBRATO"; break; - case SONG_EV_SS_PORTAMENTO: ptr = "PORTMNT"; break; - case SONG_EV_SS_CHANNEL: ptr = "CHANNEL"; break; - case SONG_EV_SS_WAV: ptr = "WAV----"; break; - case SONG_EV_SS_PAT: ptr = "PAT----"; break; - case SONG_EV_SS_SF2: ptr = "SF2----"; break; - case SONG_EV_SS_EFF_OFF: ptr = "OFF----"; break; - case SONG_EV_SS_EFF_DELAY: ptr = "DELAY--"; break; - case SONG_EV_SS_EFF_ECHO: ptr = "ECHO---"; break; - case SONG_EV_SS_EFF_COMB: ptr = "COMB---"; break; - case SONG_EV_SS_EFF_ALLPASS: ptr = "ALLPASS"; break; - case SONG_EV_SS_EFF_FLANGER: ptr = "FLANGER"; break; - case SONG_EV_SS_EFF_WOBBLE: ptr = "WOBBLE-"; break; - case SONG_EV_SS_EFF_SQWOBBLE: ptr = "SQWOBBL"; break; - case SONG_EV_SS_EFF_HFWOBBLE: ptr = "HFWOBBL"; break; - case SONG_EV_SS_EFF_FADER: ptr = "FADER--"; break; - case SONG_EV_SS_EFF_REVERB: ptr = "REVERB-"; break; - case SONG_EV_SS_EFF_FOLDBACK: ptr = "FOLDBCK"; break; - case SONG_EV_SS_EFF_ATAN: ptr = "ATAN---"; break; - case SONG_EV_SS_EFF_DISTORT: ptr = "DISTORT"; break; - case SONG_EV_SS_EFF_OVERDRIVE: ptr = "OVERDRV"; break; - case SONG_EV_MIDI_CHANNEL: ptr = "MIDICHN"; break; - case SONG_EV_MIDI_PROGRAM: ptr = "MIDIPRG"; break; - case SONG_EV_BACK: ptr = "BACK---"; break; - case SONG_EV_NOTE_OFF: ptr = "NOTEOFF"; break; - case SONG_EV_NOTE: ptr = "NOTE---"; break; - case SONG_EV_SS_PITCH_STRETCH: ptr = "PTCHSTR"; break; - case SONG_EV_SS_PRINT_WAVE_TEMPO: ptr = "PRNTMPO"; break; - case SONG_EV_SS_MASTER_VOLUME: ptr = "MASTRVL"; break; - case SONG_EV_SONG_INFO: ptr = "SONGNFO"; break; - case SONG_EV_EOT: ptr = "EOT----"; break; - case SONG_EV_END: ptr = "END----"; break; - case SONG_EV_NOP: ptr = "NOP----"; break; - } - - return ptr; -} - - -void dump_song_event(const struct song_ev *e) -{ - if (e->frame) - printf("FRM: %8d ", e->frame); - - if (e->msecs) - printf("MS: %8d ", e->msecs); - - printf("%7.3lf %7s TRK: %2d ID: %4d", - e->time, event_name(e->type), e->trk_id, e->event_id); - - if (e->value) - printf(" VAL: %3d", e->value); - - if (e->note_id) - printf(" NOTE: %3d", e->note_id); - - if (e->min || e->max) - printf(" [%d,%d]", e->min, e->max); - - printf(" CHN: %d", e->channel); - - if (e->skip_channels) - printf(" SKIP: %d", e->skip_channels); - - if (e->vol > 0.0) - printf(" VOL: %5.3lf", e->vol); - - if (e->amount > 0.0) - printf(" AMOUNT: %7.3lf", e->amount); - - if (e->len > 0.0) - printf(" LEN: %7.3lf", e->len); - - if (e->name != NULL) - printf(" NAME: '%s'", e->name); - - if (e->str2 != NULL) - printf(" STR2: '%s'", e->str2); - - printf("\n"); -} - - -void dump_song_events(const struct song_ev *song, int n_song_ev) -{ - const struct song_ev *e; - int n; - - for (n = 0, e = song; n < n_song_ev; n++, e++) - dump_song_event(e); - - printf("\n"); -} - - -static int time_type_eventid_cmp(const void *v1, const void *v2) -/* sorts events by time, then type, then event_id */ -{ - struct song_ev *e1; - struct song_ev *e2; - int ret; - - e1 = (struct song_ev *) v1; - e2 = (struct song_ev *) v2; - - ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0)); - - /* same time? order by type of event */ - if (ret == 0) - ret = e1->type - e2->type; - - /* same time and same event? order by event id */ - if (ret == 0) - ret = e1->event_id - e2->event_id; - - return ret; -} - - -static void count_tracks(void) -/* sets n_song_tracks */ -{ - int n; - - n_song_tracks = 0; - - for(n = 0; n < n_song_ev; n++) { - struct song_ev *e; - - e = &song[n]; - - if (n_song_tracks < e->trk_id + 1) - n_song_tracks = e->trk_id + 1; - } -} - - -static void add_eot_events(void) -/* travels all events and adds EOT ones */ -{ - int n, m; - - for (n = 0; n < n_song_tracks; n++) { - struct song_ev *e; - double t = -1; - - for (m = 0; m < n_song_ev; m++) { - e = &song[m]; - - /* if this is the track we're looking for - and this event time is bigger, store it */ - if (e->trk_id == n && e->time > t) - t = e->time; - } - - /* now t has the biggest time; add an EOT event with t */ - e = add_event(&song, &n_song_ev); - - e->type = SONG_EV_EOT; - e->time = t; - e->trk_id = n; - e->event_id = n_song_ev - 1; - } -} - - -/** - * mute_tracks - Converts track events to NOPs. - * @trk_id: Track to be muted. If negative, all buts this will be muted - * - * Converts events to NOP. If @trk_id is positive, all events for that - * track id will be converted to NOP; if it's negative, all events BUT - * for the ones in that track will be muted. - */ -void mute_tracks(int trk_id) -{ - int n; - - for (n = 0; n < n_song_ev; n++) { - struct song_ev *e; - - e = &song[n]; - - /* try only 'real' tracks */ - if (e->trk_id >= 0) { - if (trk_id > 0) { - if (e->trk_id == trk_id) - e->type = SONG_EV_NOP; - } - else { - if (e->trk_id != -trk_id) - e->type = SONG_EV_NOP; - } - } - } -} - - -/** - * song_sort - Sorts the song stream - * - * Sorts the song stream. - */ -void song_sort(void) -{ - count_tracks(); - add_eot_events(); - - /* sorts by time, type and event_id */ - qsort(song, n_song_ev, sizeof(struct song_ev), time_type_eventid_cmp); - - if (trace) { - printf("\n** GENERIC SONG EVENT DUMP **\n\n"); - dump_song_events(song, n_song_ev); - } -} - - -/** - * song_test_measure_boundary - Does a measure boundary check - * @ev_time: event time - * @num: meter numerator - * @den: meter denominator - * - * Does a measure boundary check. Returns 0 if the event time falls - * exactly between two measures, or nonzero otherwise. - */ -int song_test_measure_boundary(double ev_time, int num, int den, int line) -{ - int ret; - - if ((ret = ((int) (ev_time * (double) den)) % num)) - printf("Measure boundary check failed in line %d\n", line); - - return ret; -} +/* + + Ann Hell Ex Machina - Music Software + Copyright (C) 2003/2008 Angel Ortega + + song.c - Device-independent song event stream management + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.triptico.com + +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include "ahxm.h" + +/** data **/ + +/* the song event stream */ +struct song_ev *song = NULL; + +/* number of song events */ +int n_song_ev = 0; + +/* number of tracks in song */ +int n_song_tracks = 0; + + +/** code **/ + +/** + * add_event - Adds an event to an event list. + * @song: A pointer to an event list (dynamically allocated) + * @count: A pointer to an integer (number of elements) + * + * Increments the @song event list to fit @count number of + * elements, probably reallocating its memory. + * + * Returns a pointer to the new element. + */ +struct song_ev *add_event(struct song_ev **song, int *count) +{ + struct song_ev *r; + + GROW(*song, *count, struct song_ev); + + r = *song + *count; + memset(r, '\0', sizeof(struct song_ev)); + + (*count)++; + + return r; +} + + +/** + * copy_event - Appends an event to an event list. + * @song: the event list + * @count: a pointer to the number of elements + * @e: the event to be copied + * + * Appends the @e event to the @song event list. + */ +struct song_ev *copy_event(struct song_ev **song, int *count, + const struct song_ev *e) +{ + struct song_ev *r = add_event(song, count); + + memcpy(r, e, sizeof(struct song_ev)); + + return r; +} + + +/** + * song_clear - Clears the song stream + * + * Clears the song stream. + */ +void song_clear(void) +{ + if (song != NULL) { + free(song); + song = NULL; + } + + n_song_ev = 0; +} + + +static char *event_name(song_ev_type t) +{ + char *ptr = "UNKNOWN"; + + switch (t) { + case SONG_EV_TEMPO: + ptr = "TEMPO--"; + break; + + case SONG_EV_METER: + ptr = "METER--"; + break; + + case SONG_EV_MEASURE: + ptr = "MEASURE"; + break; + + case SONG_EV_SS_SUSTAIN: + ptr = "SUSTAIN"; + break; + + case SONG_EV_SS_ATTACK: + ptr = "ATTACK-"; + break; + + case SONG_EV_SS_VIBRATO: + ptr = "VIBRATO"; + break; + + case SONG_EV_SS_PORTAMENTO: + ptr = "PORTMNT"; + break; + + case SONG_EV_SS_CHANNEL: + ptr = "CHANNEL"; + break; + + case SONG_EV_SS_WAV: + ptr = "WAV----"; + break; + + case SONG_EV_SS_PAT: + ptr = "PAT----"; + break; + + case SONG_EV_SS_SF2: + ptr = "SF2----"; + break; + + case SONG_EV_SS_EFF_OFF: + ptr = "OFF----"; + break; + + case SONG_EV_SS_EFF_DELAY: + ptr = "DELAY--"; + break; + + case SONG_EV_SS_EFF_ECHO: + ptr = "ECHO---"; + break; + + case SONG_EV_SS_EFF_COMB: + ptr = "COMB---"; + break; + + case SONG_EV_SS_EFF_ALLPASS: + ptr = "ALLPASS"; + break; + + case SONG_EV_SS_EFF_FLANGER: + ptr = "FLANGER"; + break; + + case SONG_EV_SS_EFF_WOBBLE: + ptr = "WOBBLE-"; + break; + + case SONG_EV_SS_EFF_SQWOBBLE: + ptr = "SQWOBBL"; + break; + + case SONG_EV_SS_EFF_HFWOBBLE: + ptr = "HFWOBBL"; + break; + + case SONG_EV_SS_EFF_FADER: + ptr = "FADER--"; + break; + + case SONG_EV_SS_EFF_REVERB: + ptr = "REVERB-"; + break; + + case SONG_EV_SS_EFF_FOLDBACK: + ptr = "FOLDBCK"; + break; + + case SONG_EV_SS_EFF_ATAN: + ptr = "ATAN---"; + break; + + case SONG_EV_SS_EFF_DISTORT: + ptr = "DISTORT"; + break; + + case SONG_EV_SS_EFF_OVERDRIVE: + ptr = "OVERDRV"; + break; + + case SONG_EV_MIDI_CHANNEL: + ptr = "MIDICHN"; + break; + + case SONG_EV_MIDI_PROGRAM: + ptr = "MIDIPRG"; + break; + + case SONG_EV_BACK: + ptr = "BACK---"; + break; + + case SONG_EV_NOTE_OFF: + ptr = "NOTEOFF"; + break; + + case SONG_EV_NOTE: + ptr = "NOTE---"; + break; + + case SONG_EV_SS_PITCH_STRETCH: + ptr = "PTCHSTR"; + break; + + case SONG_EV_SS_PRINT_WAVE_TEMPO: + ptr = "PRNTMPO"; + break; + + case SONG_EV_SS_MASTER_VOLUME: + ptr = "MASTRVL"; + break; + + case SONG_EV_SONG_INFO: + ptr = "SONGNFO"; + break; + + case SONG_EV_EOT: + ptr = "EOT----"; + break; + + case SONG_EV_END: + ptr = "END----"; + break; + + case SONG_EV_NOP: + ptr = "NOP----"; + break; + } + + return ptr; +} + + +void dump_song_event(const struct song_ev *e) +{ + if (e->frame) + printf("FRM: %8d ", e->frame); + + if (e->msecs) + printf("MS: %8d ", e->msecs); + + printf("%7.3lf %7s TRK: %2d ID: %4d", + e->time, event_name(e->type), e->trk_id, e->event_id); + + if (e->value) + printf(" VAL: %3d", e->value); + + if (e->note_id) + printf(" NOTE: %3d", e->note_id); + + if (e->min || e->max) + printf(" [%d,%d]", e->min, e->max); + + printf(" CHN: %d", e->channel); + + if (e->skip_channels) + printf(" SKIP: %d", e->skip_channels); + + if (e->vol > 0.0) + printf(" VOL: %5.3lf", e->vol); + + if (e->amount > 0.0) + printf(" AMOUNT: %7.3lf", e->amount); + + if (e->len > 0.0) + printf(" LEN: %7.3lf", e->len); + + if (e->name != NULL) + printf(" NAME: '%s'", e->name); + + if (e->str2 != NULL) + printf(" STR2: '%s'", e->str2); + + printf("\n"); +} + + +void dump_song_events(const struct song_ev *song, int n_song_ev) +{ + const struct song_ev *e; + int n; + + for (n = 0, e = song; n < n_song_ev; n++, e++) + dump_song_event(e); + + printf("\n"); +} + + +static int time_type_eventid_cmp(const void *v1, const void *v2) +/* sorts events by time, then type, then event_id */ +{ + struct song_ev *e1; + struct song_ev *e2; + int ret; + + e1 = (struct song_ev *) v1; + e2 = (struct song_ev *) v2; + + ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0)); + + /* same time? order by type of event */ + if (ret == 0) + ret = e1->type - e2->type; + + /* same time and same event? order by event id */ + if (ret == 0) + ret = e1->event_id - e2->event_id; + + return ret; +} + + +static void count_tracks(void) +/* sets n_song_tracks */ +{ + int n; + + n_song_tracks = 0; + + for (n = 0; n < n_song_ev; n++) { + struct song_ev *e; + + e = &song[n]; + + if (n_song_tracks < e->trk_id + 1) + n_song_tracks = e->trk_id + 1; + } +} + + +static void add_eot_events(void) +/* travels all events and adds EOT ones */ +{ + int n, m; + + for (n = 0; n < n_song_tracks; n++) { + struct song_ev *e; + double t = -1; + + for (m = 0; m < n_song_ev; m++) { + e = &song[m]; + + /* if this is the track we're looking for + and this event time is bigger, store it */ + if (e->trk_id == n && e->time > t) + t = e->time; + } + + /* now t has the biggest time; add an EOT event with t */ + e = add_event(&song, &n_song_ev); + + e->type = SONG_EV_EOT; + e->time = t; + e->trk_id = n; + e->event_id = n_song_ev - 1; + } +} + + +/** + * mute_tracks - Converts track events to NOPs. + * @trk_id: Track to be muted. If negative, all buts this will be muted + * + * Converts events to NOP. If @trk_id is positive, all events for that + * track id will be converted to NOP; if it's negative, all events BUT + * for the ones in that track will be muted. + */ +void mute_tracks(int trk_id) +{ + int n; + + for (n = 0; n < n_song_ev; n++) { + struct song_ev *e; + + e = &song[n]; + + /* try only 'real' tracks */ + if (e->trk_id >= 0) { + if (trk_id > 0) { + if (e->trk_id == trk_id) + e->type = SONG_EV_NOP; + } + else { + if (e->trk_id != -trk_id) + e->type = SONG_EV_NOP; + } + } + } +} + + +/** + * song_sort - Sorts the song stream + * + * Sorts the song stream. + */ +void song_sort(void) +{ + count_tracks(); + add_eot_events(); + + /* sorts by time, type and event_id */ + qsort(song, n_song_ev, sizeof(struct song_ev), time_type_eventid_cmp); + + if (trace) { + printf("\n** GENERIC SONG EVENT DUMP **\n\n"); + dump_song_events(song, n_song_ev); + } +} + + +/** + * song_test_measure_boundary - Does a measure boundary check + * @ev_time: event time + * @num: meter numerator + * @den: meter denominator + * + * Does a measure boundary check. Returns 0 if the event time falls + * exactly between two measures, or nonzero otherwise. + */ +int song_test_measure_boundary(double ev_time, int num, int den, int line) +{ + int ret; + + if ((ret = ((int) (ev_time * (double) den)) % num)) + printf("Measure boundary check failed in line %d\n", line); + + return ret; +} diff --git a/ss_core.c b/ss_core.c index a8ba4dd..f3f79ec 100644 --- a/ss_core.c +++ b/ss_core.c @@ -32,9 +32,8 @@ #include "ahxm.h" -/******************* - Data -********************/ + +/** data **/ /* main output frequency */ int ss_frequency = 44100; @@ -49,9 +48,8 @@ int ss_nchannels = -1; double ss_middle_A_freq = 440.0; static double note_frequency[128]; -/******************* - Code -********************/ + +/** code **/ /** * ss_note_frequency - MIDI note to frequency converter @@ -62,19 +60,19 @@ static double note_frequency[128]; */ double ss_note_frequency(int note) { - int n; + int n; - if (note < 0 || note > 127) - return 0; + if (note < 0 || note > 127) + return 0; - /* builds the table if empty */ - if (note_frequency[0] == 0.0) { - for (n = 0; n < 128; n++) - note_frequency[n] = (ss_middle_A_freq / 32.0) * - pow(2.0, (((double) n - 9.0) / 12.0)); - } + /* builds the table if empty */ + if (note_frequency[0] == 0.0) { + for (n = 0; n < 128; n++) + note_frequency[n] = (ss_middle_A_freq / 32.0) * + pow(2.0, (((double) n - 9.0) / 12.0)); + } - return note_frequency[note]; + return note_frequency[note]; } @@ -88,27 +86,28 @@ double ss_note_frequency(int note) * Allocates a wave structure. If @p_size is -1, it's assumed to be the * same as @size (so the sound will live entirely in memory). */ -struct ss_wave *ss_alloc_wave(int size, int n_channels, int s_rate, int p_size) +struct ss_wave *ss_alloc_wave(int size, int n_channels, int s_rate, + int p_size) { - struct ss_wave *w = NULL; + struct ss_wave *w = NULL; - if (p_size == -1) - p_size = size; + if (p_size == -1) + p_size = size; - if ((w = (struct ss_wave *) malloc(sizeof(struct ss_wave))) != NULL) { - memset(w, '\0', sizeof(struct ss_wave)); + if ((w = (struct ss_wave *) malloc(sizeof(struct ss_wave))) != NULL) { + memset(w, '\0', sizeof(struct ss_wave)); - w->size = (double) size; - w->p_size = p_size; - w->n_channels = n_channels; - w->s_rate = s_rate; + w->size = (double) size; + w->p_size = p_size; + w->n_channels = n_channels; + w->s_rate = s_rate; - /* alloc space for the pointers to the waves */ - w->wave = (sample_t **) malloc(n_channels * sizeof(sample_t *)); - memset(w->wave, '\0', n_channels * sizeof(sample_t *)); - } + /* alloc space for the pointers to the waves */ + w->wave = (sample_t **) malloc(n_channels * sizeof(sample_t *)); + memset(w->wave, '\0', n_channels * sizeof(sample_t *)); + } - return w; + return w; } @@ -120,114 +119,117 @@ struct ss_wave *ss_alloc_wave(int size, int n_channels, int s_rate, int p_size) */ void ss_free_wave(struct ss_wave *w) { - if (w->wave != NULL) { - int n; + if (w->wave != NULL) { + int n; - /* frees the buffers */ - for (n = 0; n < w->n_channels; n++) - if (w->wave[n] != NULL) - free(w->wave[n]); + /* frees the buffers */ + for (n = 0; n < w->n_channels; n++) + if (w->wave[n] != NULL) + free(w->wave[n]); - /* frees the space for the pointers to the waves */ - free(w->wave); + /* frees the space for the pointers to the waves */ + free(w->wave); - /* if it has a filename, also free it */ - if (w->filename != NULL) - free((char *)w->filename); - } + /* if it has a filename, also free it */ + if (w->filename != NULL) + free((char *) w->filename); + } - /* frees the wave itself */ - free(w); + /* frees the wave itself */ + free(w); } void ss_prepare_wave(struct ss_wave *w) /* prepares a wave file for usage (creates the page buffers) */ { - int n; + int n; - /* alloc space for the waves themselves */ - for (n = 0; n < w->n_channels; n++) { - w->wave[n] = (sample_t *) realloc(w->wave[n], w->p_size * sizeof(sample_t)); + /* alloc space for the waves themselves */ + for (n = 0; n < w->n_channels; n++) { + w->wave[n] = + (sample_t *) realloc(w->wave[n], w->p_size * sizeof(sample_t)); - memset(w->wave[n], '\0', w->p_size * sizeof(sample_t)); - } + memset(w->wave[n], '\0', w->p_size * sizeof(sample_t)); + } } static void ss_load_page(struct ss_wave *w, int offset) /* loads a page from a wave file into memory */ { - FILE *f; - int s; + FILE *f; + int s; - /* set the offset to some samples behind the - wanted offset (to avoid possible page bounces) */ - if ((w->p_offset = offset - 441) < 0) - w->p_offset = 0; + /* set the offset to some samples behind the + wanted offset (to avoid possible page bounces) */ + if ((w->p_offset = offset - 441) < 0) + w->p_offset = 0; - /* too much page faults for this wave? */ - if (w->page_faults >= 8) { - /* increase space */ - if ((w->p_size *= 2) > (int) w->size) { - /* if this resize is too much, just - set it to load the full wave */ - w->p_size = (int) w->size; - w->p_offset = 0; - } + /* too much page faults for this wave? */ + if (w->page_faults >= 8) { + /* increase space */ + if ((w->p_size *= 2) > (int) w->size) { + /* if this resize is too much, just + set it to load the full wave */ + w->p_size = (int) w->size; + w->p_offset = 0; + } - /* trigger a page resizing and restart statistics */ - w->page_faults = 0; - } + /* trigger a page resizing and restart statistics */ + w->page_faults = 0; + } - if (w->page_faults == 0) - ss_prepare_wave(w); + if (w->page_faults == 0) + ss_prepare_wave(w); - if ((f = fopen(w->filename, "rb")) == NULL) { - fprintf(stderr, "Can't open '%s'\n", w->filename); - return; - } + if ((f = fopen(w->filename, "rb")) == NULL) { + fprintf(stderr, "Can't open '%s'\n", w->filename); + return; + } - if (verbose >= 3) - printf("load_page [%s,%d,%d,%d]\n", w->filename, - w->p_offset, w->p_size, w->page_faults); + if (verbose >= 3) + printf("load_page [%s,%d,%d,%d]\n", w->filename, + w->p_offset, w->p_size, w->page_faults); - /* calculate the frame size */ - s = w->p_offset * (w->bits / 8) * w->n_channels; + /* calculate the frame size */ + s = w->p_offset * (w->bits / 8) * w->n_channels; - /* move there */ - fseek(f, w->f_pos + s, SEEK_SET); + /* move there */ + fseek(f, w->f_pos + s, SEEK_SET); - /* fill the page */ - load_pcm_wave(f, w); + /* fill the page */ + load_pcm_wave(f, w); - fclose(f); + fclose(f); - w->page_faults++; + w->page_faults++; } -static sample_t ss_pick_sample(struct ss_wave *w, int channel, double offset) +static sample_t ss_pick_sample(struct ss_wave *w, int channel, + double offset) /* picks a sample from a ss_wave, forcing a call to ss_load_page() if the wanted sample is not in memory */ { - int o; - sample_t *wave; + int o; + sample_t *wave; - o = (int) offset; + o = (int) offset; - /* is the wanted sample not in memory? */ - if (o < w->p_offset || o > w->p_offset + w->p_size) { + /* is the wanted sample not in memory? */ + if (o < w->p_offset || o > w->p_offset + w->p_size) { - if (verbose >= 3) - printf("ss_pick_sample: offset: %lf, p_offset: %d, p_size: %d, size: %lf, loop_end: %lf\n", - offset, w->p_offset, w->p_size, w->size, w->loop_end); + if (verbose >= 3) + printf + ("ss_pick_sample: offset: %lf, p_offset: %d, p_size: %d, size: %lf, loop_end: %lf\n", + offset, w->p_offset, w->p_size, w->size, w->loop_end); - ss_load_page(w, o); - } + ss_load_page(w, o); + } - wave = w->wave[channel]; - return wave[o - w->p_offset]; + wave = w->wave[channel]; + return wave[o - w->p_offset]; } @@ -242,87 +244,87 @@ static sample_t ss_pick_sample(struct ss_wave *w, int channel, double offset) */ sample_t ss_get_sample(struct ss_wave * w, int channel, double offset) { - sample_t d, t, r = 0.0; - sample_t s0, s1, s2, s3; - - /* take care of wrappings */ - if (offset < 0) - offset += w->size; - - /* pick sample at offset */ - s1 = ss_pick_sample(w, channel, offset); - - switch (ss_interpolation) { - case 0: - /* no interpolation */ - r = s1; - break; - - case 1: - /* linear interpolation */ - if (offset > w->size - 2) - r = s1; - else { - d = (sample_t) (offset - floor(offset)); - s2 = (ss_pick_sample(w, channel, offset + 1) - s1) * d; - - r = s1 + s2; - } - - break; - - case 2: - /* cubic spline (borrowed from timidity) */ - if (offset < 1 || offset > w->size - 3) - r = s1; - else { - s0 = ss_pick_sample(w, channel, offset - 1); - s2 = ss_pick_sample(w, channel, offset + 1); - s3 = ss_pick_sample(w, channel, offset + 2); - - t = s2; - - d = (sample_t) (offset - floor(offset)); - - s2 = (6.0 * s2 + - ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) * - (d + 1.0) * (d - 1.0)) * d; - - s1 = ((6.0 * s1 + - ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) * - d * (d - 2.0)) * (1.0 - d) + s2) / 6.0; - - r = s1; - } - - break; - - case 3: - /* lagrange (borrowed from timidity) */ - if (offset < 1 || offset > w->size - 3) - r = s1; - else { - s0 = ss_pick_sample(w, channel, offset - 1); - s2 = ss_pick_sample(w, channel, offset + 1); - s3 = ss_pick_sample(w, channel, offset + 2); - - d = (sample_t) (offset - floor(offset)); - - s3 += -3.0 * s2 + 3.0 * s1 - s0; - s3 *= (d - 2.0) / 6.0; - s3 += s2 - 2.0 * s1 + s0; - s3 *= (d - 1.0) / 2.0; - s3 += s1 - s0; - s3 *= d; - s3 += s0; - - r = s3; - } - - break; - } - - return r; + sample_t d, t, r = 0.0; + sample_t s0, s1, s2, s3; + + /* take care of wrappings */ + if (offset < 0) + offset += w->size; + + /* pick sample at offset */ + s1 = ss_pick_sample(w, channel, offset); + + switch (ss_interpolation) { + case 0: + /* no interpolation */ + r = s1; + break; + + case 1: + /* linear interpolation */ + if (offset > w->size - 2) + r = s1; + else { + d = (sample_t) (offset - floor(offset)); + s2 = (ss_pick_sample(w, channel, offset + 1) - s1) * d; + + r = s1 + s2; + } + + break; + + case 2: + /* cubic spline (borrowed from timidity) */ + if (offset < 1 || offset > w->size - 3) + r = s1; + else { + s0 = ss_pick_sample(w, channel, offset - 1); + s2 = ss_pick_sample(w, channel, offset + 1); + s3 = ss_pick_sample(w, channel, offset + 2); + + t = s2; + + d = (sample_t) (offset - floor(offset)); + + s2 = (6.0 * s2 + + ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) * + (d + 1.0) * (d - 1.0)) * d; + + s1 = ((6.0 * s1 + + ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) * + d * (d - 2.0)) * (1.0 - d) + s2) / 6.0; + + r = s1; + } + + break; + + case 3: + /* lagrange (borrowed from timidity) */ + if (offset < 1 || offset > w->size - 3) + r = s1; + else { + s0 = ss_pick_sample(w, channel, offset - 1); + s2 = ss_pick_sample(w, channel, offset + 1); + s3 = ss_pick_sample(w, channel, offset + 2); + + d = (sample_t) (offset - floor(offset)); + + s3 += -3.0 * s2 + 3.0 * s1 - s0; + s3 *= (d - 2.0) / 6.0; + s3 += s2 - 2.0 * s1 + s0; + s3 *= (d - 1.0) / 2.0; + s3 += s1 - s0; + s3 *= d; + s3 += s0; + + r = s3; + } + + break; + } + + return r; } @@ -337,21 +339,21 @@ sample_t ss_get_sample(struct ss_wave * w, int channel, double offset) */ double ss_tempo_from_wave(const struct ss_wave *w, int note, double len) { - double d; + double d; - d = ss_note_frequency(note) / w->base_freq; + d = ss_note_frequency(note) / w->base_freq; - /* get the length of a whole, in seconds */ - d *= w->s_rate / w->size; + /* get the length of a whole, in seconds */ + d *= w->s_rate / w->size; - /* convert to minutes */ - d *= 60.0; + /* convert to minutes */ + d *= 60.0; - /* then to bpm,s */ - d *= 4.0; - d *= len; + /* then to bpm,s */ + d *= 4.0; + d *= len; - return d; + return d; } @@ -364,16 +366,17 @@ double ss_tempo_from_wave(const struct ss_wave *w, int note, double len) * Calculates the optimal frequency (pitch) for the @w wave, at @tempo, * to last @len whole notes. */ -double ss_pitch_from_tempo(const struct ss_wave *w, double tempo, double len) +double ss_pitch_from_tempo(const struct ss_wave *w, double tempo, + double len) { - double d; + double d; - /* calculate number of seconds the wave lasts */ - d = w->size / (double) w->s_rate; + /* calculate number of seconds the wave lasts */ + d = w->size / (double) w->s_rate; - /* convert to minutes, then to wpms */ - d /= 60.0; - d *= (tempo / 4.0); + /* convert to minutes, then to wpms */ + d /= 60.0; + d *= (tempo / 4.0); - return w->base_freq * d * len; + return w->base_freq * d * len; } diff --git a/ss_eff.c b/ss_eff.c index 7dfd59a..83e4ab0 100644 --- a/ss_eff.c +++ b/ss_eff.c @@ -36,61 +36,64 @@ /** helping functions **/ static struct ss_eff *ss_eff_add(struct ss_eff **ec, double size, - sample_t gain, sample_t(*func) (struct ss_eff *, sample_t)) + sample_t gain, + sample_t(*func) (struct ss_eff *, + sample_t)) /* adds an effect to the ec chain */ { - struct ss_eff *e; + struct ss_eff *e; - /* convert to frames */ - size = MS2F(size); + /* convert to frames */ + size = MS2F(size); - /* create new structure and reset */ - if ((e = malloc(sizeof(struct ss_eff))) == NULL) - return NULL; + /* create new structure and reset */ + if ((e = malloc(sizeof(struct ss_eff))) == NULL) + return NULL; - memset(e, '\0', sizeof(struct ss_eff)); + memset(e, '\0', sizeof(struct ss_eff)); - /* enqueue */ - if (*ec == NULL) - *ec = e; - else { - struct ss_eff *t; + /* enqueue */ + if (*ec == NULL) + *ec = e; + else { + struct ss_eff *t; - /* loop to add e to the end */ - for (t = *ec; t->next != NULL; t = t->next); + /* loop to add e to the end */ + for (t = *ec; t->next != NULL; t = t->next); - t->next = e; - } + t->next = e; + } - /* add buffer */ - if (size > 0) { - e->wave = ss_alloc_wave((int) size, 1, ss_frequency, -1); - ss_prepare_wave(e->wave); - } + /* add buffer */ + if (size > 0) { + e->wave = ss_alloc_wave((int) size, 1, ss_frequency, -1); + ss_prepare_wave(e->wave); + } - e->gain = gain; - e->func = func; + e->gain = gain; + e->func = func; - return e; + return e; } -static void ss_eff_set_lfo(struct ss_eff *e, double freq, double phase, double depth) +static void ss_eff_set_lfo(struct ss_eff *e, double freq, double phase, + double depth) /* sets an alfo */ { - e->lfo = phase * 6.28; - e->lfo_inc = (freq * 6.28) / (double) ss_frequency; - e->lfo_depth = MS2F(depth); + e->lfo = phase * 6.28; + e->lfo_inc = (freq * 6.28) / (double) ss_frequency; + e->lfo_depth = MS2F(depth); } static double ss_eff_lfo(struct ss_eff *e) /* processes an lfo */ { - double r = sin(e->lfo); - e->lfo += e->lfo_inc; + double r = sin(e->lfo); + e->lfo += e->lfo_inc; - return r; + return r; } @@ -104,21 +107,21 @@ static double ss_eff_lfo(struct ss_eff *e) */ sample_t ss_eff_process(struct ss_eff * e, sample_t s) { - while (e != NULL) { - /* filter */ - s = e->func(e, s); + while (e != NULL) { + /* filter */ + s = e->func(e, s); - /* increment cursor */ - if (e->wave != NULL) { - if (++e->cursor >= e->wave->size) - e->cursor = 0; - } + /* increment cursor */ + if (e->wave != NULL) { + if (++e->cursor >= e->wave->size) + e->cursor = 0; + } - /* move to next */ - e = e->next; - } + /* move to next */ + e = e->next; + } - return s; + return s; } @@ -130,27 +133,27 @@ sample_t ss_eff_process(struct ss_eff * e, sample_t s) */ void ss_eff_off(struct ss_eff **ec) { - while (*ec != NULL) { - struct ss_eff *e = (*ec)->next; + while (*ec != NULL) { + struct ss_eff *e = (*ec)->next; - /* free the buffer, if any */ - if ((*ec)->wave != NULL) - ss_free_wave((*ec)->wave); + /* free the buffer, if any */ + if ((*ec)->wave != NULL) + ss_free_wave((*ec)->wave); - /* free the effect itself */ - free(*ec); + /* free the effect itself */ + free(*ec); - /* move to next */ - *ec = e; - } + /* move to next */ + *ec = e; + } } static sample_t *eff_cursor_ptr(struct ss_eff *e) /* returns a pointer to the current sample */ { - sample_t *wave = e->wave->wave[0]; - return wave + (int) e->cursor; + sample_t *wave = e->wave->wave[0]; + return wave + (int) e->cursor; } @@ -158,14 +161,14 @@ static sample_t *eff_cursor_ptr(struct ss_eff *e) static sample_t func_delay(struct ss_eff *e, sample_t input) { - sample_t *p; - sample_t s; + sample_t *p; + sample_t s; - p = eff_cursor_ptr(e); - s = *p; - *p = input; + p = eff_cursor_ptr(e); + s = *p; + *p = input; - return s; + return s; } @@ -180,7 +183,7 @@ static sample_t func_delay(struct ss_eff *e, sample_t input) */ void ss_eff_delay(struct ss_eff **ec, double size) { - ss_eff_add(ec, size, 0, func_delay); + ss_eff_add(ec, size, 0, func_delay); } @@ -188,14 +191,14 @@ void ss_eff_delay(struct ss_eff **ec, double size) static sample_t func_echo(struct ss_eff *e, sample_t input) { - sample_t *p; - sample_t s; + sample_t *p; + sample_t s; - p = eff_cursor_ptr(e); - s = *p * e->gain; - *p = input; + p = eff_cursor_ptr(e); + s = *p * e->gain; + *p = input; - return input + s; + return input + s; } @@ -211,7 +214,7 @@ static sample_t func_echo(struct ss_eff *e, sample_t input) */ void ss_eff_echo(struct ss_eff **ec, double size, sample_t gain) { - ss_eff_add(ec, size, gain, func_echo); + ss_eff_add(ec, size, gain, func_echo); } @@ -219,14 +222,14 @@ void ss_eff_echo(struct ss_eff **ec, double size, sample_t gain) static sample_t func_comb(struct ss_eff *e, sample_t input) { - sample_t *p; - sample_t s; + sample_t *p; + sample_t s; - p = eff_cursor_ptr(e); - s = *p; - *p = input + (s * e->gain); + p = eff_cursor_ptr(e); + s = *p; + *p = input + (s * e->gain); - return input + s; + return input + s; } @@ -242,7 +245,7 @@ static sample_t func_comb(struct ss_eff *e, sample_t input) */ void ss_eff_comb(struct ss_eff **ec, double size, sample_t gain) { - ss_eff_add(ec, size, gain, func_comb); + ss_eff_add(ec, size, gain, func_comb); } @@ -250,18 +253,18 @@ void ss_eff_comb(struct ss_eff **ec, double size, sample_t gain) static sample_t func_allpass(struct ss_eff *e, sample_t input) { - sample_t *p; - sample_t s, t, u; + sample_t *p; + sample_t s, t, u; - p = eff_cursor_ptr(e); - t = *p; + p = eff_cursor_ptr(e); + t = *p; - u = input + (t * e->gain); - s = t - (e->gain * u); + u = input + (t * e->gain); + s = t - (e->gain * u); - *p = u; + *p = u; - return s; + return s; } @@ -277,7 +280,7 @@ static sample_t func_allpass(struct ss_eff *e, sample_t input) */ void ss_eff_allpass(struct ss_eff **ec, double size, sample_t gain) { - ss_eff_add(ec, size, gain, func_allpass); + ss_eff_add(ec, size, gain, func_allpass); } @@ -285,18 +288,18 @@ void ss_eff_allpass(struct ss_eff **ec, double size, sample_t gain) static sample_t func_flanger(struct ss_eff *e, sample_t input) { - double c; - sample_t s; - sample_t *p; + double c; + sample_t s; + sample_t *p; - c = e->cursor - e->lfo_depth - (e->lfo_depth * ss_eff_lfo(e)); + c = e->cursor - e->lfo_depth - (e->lfo_depth * ss_eff_lfo(e)); - s = ss_get_sample(e->wave, 0, c) * e->gain; + s = ss_get_sample(e->wave, 0, c) * e->gain; - p = eff_cursor_ptr(e); - *p = input; + p = eff_cursor_ptr(e); + *p = input; - return input + s; + return input + s; } @@ -319,12 +322,12 @@ static sample_t func_flanger(struct ss_eff *e, sample_t input) * 0.5 half a period and so on. The LFO is sinusoidal. */ void ss_eff_flanger(struct ss_eff **ec, double size, sample_t gain, - double depth, double freq, double phase) + double depth, double freq, double phase) { - struct ss_eff *e; + struct ss_eff *e; - e = ss_eff_add(ec, size, gain, func_flanger); - ss_eff_set_lfo(e, freq, phase, depth); + e = ss_eff_add(ec, size, gain, func_flanger); + ss_eff_set_lfo(e, freq, phase, depth); } @@ -332,11 +335,12 @@ void ss_eff_flanger(struct ss_eff **ec, double size, sample_t gain, static sample_t func_wobble(struct ss_eff *e, sample_t input) { - sample_t s; + sample_t s; - s = (input * fabs(ss_eff_lfo(e)) * e->gain) + (input * (1.0 - e->gain)); + s = (input * fabs(ss_eff_lfo(e)) * e->gain) + + (input * (1.0 - e->gain)); - return s; + return s; } @@ -354,12 +358,13 @@ static sample_t func_wobble(struct ss_eff *e, sample_t input) * fractional part of a period, being 0 the start of the period, * 0.5 half a period and so on. The LFO is sinusoidal. */ -void ss_eff_wobble(struct ss_eff **ec, double freq, double phase, sample_t gain) +void ss_eff_wobble(struct ss_eff **ec, double freq, double phase, + sample_t gain) { - struct ss_eff *e; + struct ss_eff *e; - e = ss_eff_add(ec, 0, gain, func_wobble); - ss_eff_set_lfo(e, freq, phase, 0); + e = ss_eff_add(ec, 0, gain, func_wobble); + ss_eff_set_lfo(e, freq, phase, 0); } @@ -367,7 +372,7 @@ void ss_eff_wobble(struct ss_eff **ec, double freq, double phase, sample_t gain) static sample_t func_square_wobble(struct ss_eff *e, sample_t input) { - return ss_eff_lfo(e) > 0 ? input : 0; + return ss_eff_lfo(e) > 0 ? input : 0; } @@ -384,10 +389,10 @@ static sample_t func_square_wobble(struct ss_eff *e, sample_t input) */ void ss_eff_square_wobble(struct ss_eff **ec, double freq, double phase) { - struct ss_eff *e; + struct ss_eff *e; - e = ss_eff_add(ec, 0, 0, func_square_wobble); - ss_eff_set_lfo(e, freq, phase, 0); + e = ss_eff_add(ec, 0, 0, func_square_wobble); + ss_eff_set_lfo(e, freq, phase, 0); } @@ -395,11 +400,11 @@ void ss_eff_square_wobble(struct ss_eff **ec, double freq, double phase) static sample_t func_half_wobble(struct ss_eff *e, sample_t input) { - sample_t s; + sample_t s; - s = ss_eff_lfo(e); + s = ss_eff_lfo(e); - return s > 0.0 ? s * input : 0.0; + return s > 0.0 ? s * input : 0.0; } @@ -415,10 +420,10 @@ static sample_t func_half_wobble(struct ss_eff *e, sample_t input) */ void ss_eff_half_wobble(struct ss_eff **ec, double freq, double phase) { - struct ss_eff *e; + struct ss_eff *e; - e = ss_eff_add(ec, 0, 0, func_half_wobble); - ss_eff_set_lfo(e, freq, phase, 0); + e = ss_eff_add(ec, 0, 0, func_half_wobble); + ss_eff_set_lfo(e, freq, phase, 0); } @@ -426,15 +431,15 @@ void ss_eff_half_wobble(struct ss_eff **ec, double freq, double phase) static sample_t func_fader(struct ss_eff *e, sample_t input) { - sample_t s; + sample_t s; - s = input * e->gain; - e->gain += e->igain; + s = input * e->gain; + e->gain += e->igain; - if (e->cursor == e->wave->size - 1) - e->igain = 0; + if (e->cursor == e->wave->size - 1) + e->igain = 0; - return s; + return s; } @@ -448,13 +453,14 @@ static sample_t func_fader(struct ss_eff *e, sample_t input) * Adds a fader effect. The effect will fade in or out the input * volume from @initial to @final during @size samples. */ -void ss_eff_fader(struct ss_eff **ec, double size, sample_t initial, sample_t final) +void ss_eff_fader(struct ss_eff **ec, double size, sample_t initial, + sample_t final) { - struct ss_eff *e; + struct ss_eff *e; - e = ss_eff_add(ec, size, initial, func_fader); + e = ss_eff_add(ec, size, initial, func_fader); - e->igain = (final - initial) / (sample_t) MS2F(size); + e->igain = (final - initial) / (sample_t) MS2F(size); } @@ -468,9 +474,9 @@ void ss_eff_fader(struct ss_eff **ec, double size, sample_t initial, sample_t fi */ void ss_eff_reverb(struct ss_eff **ec) { - ss_eff_allpass(ec, 20.0, 0.9); - ss_eff_allpass(ec, 36.0, 0.9); - ss_eff_allpass(ec, 39.0, 0.9); + ss_eff_allpass(ec, 20.0, 0.9); + ss_eff_allpass(ec, 36.0, 0.9); + ss_eff_allpass(ec, 39.0, 0.9); } @@ -478,15 +484,15 @@ void ss_eff_reverb(struct ss_eff **ec) static sample_t func_foldback(struct ss_eff *e, sample_t input) { - sample_t s = input; + sample_t s = input; - /* http://www.musicdsp.org/archive.php?classid=4#203 */ - if (input > e->gain) - s = e->gain - (input - e->gain); - else if (input < -e->gain) - s = -e->gain + (-e->gain - input); + /* http://www.musicdsp.org/archive.php?classid=4#203 */ + if (input > e->gain) + s = e->gain - (input - e->gain); + else if (input < -e->gain) + s = -e->gain + (-e->gain - input); - return s; + return s; } @@ -500,7 +506,7 @@ static sample_t func_foldback(struct ss_eff *e, sample_t input) */ void ss_eff_foldback(struct ss_eff **ec, sample_t threshold) { - ss_eff_add(ec, 0, threshold, func_foldback); + ss_eff_add(ec, 0, threshold, func_foldback); } @@ -508,13 +514,13 @@ void ss_eff_foldback(struct ss_eff **ec, sample_t threshold) static sample_t func_atan(struct ss_eff *e, sample_t input) { - sample_t s = input; + sample_t s = input; - /* atan */ - /* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=104 */ - s = atan(s * e->gain) / e->gain; + /* atan */ + /* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=104 */ + s = atan(s * e->gain) / e->gain; - return s; + return s; } @@ -527,7 +533,7 @@ static sample_t func_atan(struct ss_eff *e, sample_t input) */ void ss_eff_atan(struct ss_eff **ec, sample_t gain) { - ss_eff_add(ec, 0, gain, func_atan); + ss_eff_add(ec, 0, gain, func_atan); } @@ -535,13 +541,13 @@ void ss_eff_atan(struct ss_eff **ec, sample_t gain) static sample_t func_distort(struct ss_eff *e, sample_t input) { - sample_t s = input; + sample_t s = input; - /* distort */ - /* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=86 */ - s = s - e->gain * s * s * s; + /* distort */ + /* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=86 */ + s = s - e->gain * s * s * s; - return s; + return s; } @@ -554,7 +560,7 @@ static sample_t func_distort(struct ss_eff *e, sample_t input) */ void ss_eff_distort(struct ss_eff **ec, sample_t gain) { - ss_eff_add(ec, 0, gain, func_distort); + ss_eff_add(ec, 0, gain, func_distort); } @@ -562,13 +568,13 @@ void ss_eff_distort(struct ss_eff **ec, sample_t gain) static sample_t func_overdrive(struct ss_eff *e, sample_t input) { - sample_t s = input; + sample_t s = input; - /* overdrive */ - /* http://www.musicdsp.org/archive.php?classid=4#41 */ - s = s * (fabs(s) + e->gain) / (s * s + (e->gain - 1) * fabs(s) + 1); + /* overdrive */ + /* http://www.musicdsp.org/archive.php?classid=4#41 */ + s = s * (fabs(s) + e->gain) / (s * s + (e->gain - 1) * fabs(s) + 1); - return s; + return s; } @@ -581,5 +587,5 @@ static sample_t func_overdrive(struct ss_eff *e, sample_t input) */ void ss_eff_overdrive(struct ss_eff **ec, sample_t gain) { - ss_eff_add(ec, 0, gain, func_overdrive); + ss_eff_add(ec, 0, gain, func_overdrive); } diff --git a/ss_gen.c b/ss_gen.c index 8c27058..648e1af 100644 --- a/ss_gen.c +++ b/ss_gen.c @@ -32,9 +32,8 @@ #include "ahxm.h" -/******************* - Data -********************/ + +/** data **/ /* maximum number of generators */ int ss_gen_num = SS_MAX_GENERATORS; @@ -46,63 +45,61 @@ static struct ss_gen *ss_gen_pool = NULL; static struct ss_gen *ss_gen_free_queue = NULL; -/******************* - Code -********************/ +/** code **/ static void ss_gen_enqueue(struct ss_gen **q, struct ss_gen *g) /* Enqueues a generator in a generator queue */ { - g->prev = NULL; - g->next = *q; + g->prev = NULL; + g->next = *q; - if (*q != NULL) - (*q)->prev = g; + if (*q != NULL) + (*q)->prev = g; - *q = g; + *q = g; } void ss_gen_init(void) /* inits the generator pool */ { - int n; + int n; - ss_gen_pool = (struct ss_gen *) realloc(ss_gen_pool, ss_gen_num * - sizeof(struct ss_gen)); + ss_gen_pool = (struct ss_gen *) realloc(ss_gen_pool, ss_gen_num * + sizeof(struct ss_gen)); - memset(ss_gen_pool, '\0', ss_gen_num * sizeof(struct ss_gen)); + memset(ss_gen_pool, '\0', ss_gen_num * sizeof(struct ss_gen)); - /* enqueue all into the free generator queue */ - for (n = 0; n < ss_gen_num; n++) - ss_gen_enqueue(&ss_gen_free_queue, &ss_gen_pool[n]); + /* enqueue all into the free generator queue */ + for (n = 0; n < ss_gen_num; n++) + ss_gen_enqueue(&ss_gen_free_queue, &ss_gen_pool[n]); } static struct ss_gen *ss_gen_dequeue(struct ss_gen **q, struct ss_gen *g) /* Dequeues a generator from a generator queue */ { - if (g->prev != NULL) - g->prev->next = g->next; - else - *q = g->next; + if (g->prev != NULL) + g->prev->next = g->next; + else + *q = g->next; - if (g->next != NULL) - g->next->prev = g->prev; + if (g->next != NULL) + g->next->prev = g->prev; - return g; + return g; } static struct ss_gen *ss_gen_pop(struct ss_gen **q) /* gets the first enqueued generator from q */ { - struct ss_gen *g = NULL; + struct ss_gen *g = NULL; - if (*q != NULL) - g = ss_gen_dequeue(q, *q); + if (*q != NULL) + g = ss_gen_dequeue(q, *q); - return g; + return g; } @@ -117,12 +114,12 @@ static struct ss_gen *ss_gen_pop(struct ss_gen **q) */ struct ss_gen *ss_gen_alloc(struct ss_gen **q) { - struct ss_gen *g; + struct ss_gen *g; - if ((g = ss_gen_pop(&ss_gen_free_queue)) != NULL) - ss_gen_enqueue(q, g); + if ((g = ss_gen_pop(&ss_gen_free_queue)) != NULL) + ss_gen_enqueue(q, g); - return g; + return g; } @@ -135,7 +132,7 @@ struct ss_gen *ss_gen_alloc(struct ss_gen **q) */ void ss_gen_free(struct ss_gen **q, struct ss_gen *g) { - ss_gen_enqueue(&ss_gen_free_queue, ss_gen_dequeue(q, g)); + ss_gen_enqueue(&ss_gen_free_queue, ss_gen_dequeue(q, g)); } @@ -149,7 +146,7 @@ void ss_gen_free(struct ss_gen **q, struct ss_gen *g) */ void ss_gen_sustain(struct ss_gen *g, double sustain) { - g->sustain = MS2F(sustain); + g->sustain = MS2F(sustain); } @@ -163,12 +160,12 @@ void ss_gen_sustain(struct ss_gen *g, double sustain) */ void ss_gen_attack(struct ss_gen *g, double attack) { - if ((g->attack = MS2F(attack)) > 0) { - /* calculates the delta volume */ - g->davol = g->vol / (sample_t) g->attack; + if ((g->attack = MS2F(attack)) > 0) { + /* calculates the delta volume */ + g->davol = g->vol / (sample_t) g->attack; - g->vol = 0.0; - } + g->vol = 0.0; + } } @@ -183,12 +180,12 @@ void ss_gen_attack(struct ss_gen *g, double attack) */ void ss_gen_vibrato(struct ss_gen *g, double depth, double freq) { - /* good freq: 6 Hz (0.001) */ - /* good depth: 1/6 semitone (20, 30 frames) */ + /* good freq: 6 Hz (0.001) */ + /* good depth: 1/6 semitone (20, 30 frames) */ - g->vib_depth = MS2F(depth); - g->vib_inc = (6.28 * freq) / (double) ss_frequency; - g->vibrato = 0.0; + g->vib_depth = MS2F(depth); + g->vib_inc = (6.28 * freq) / (double) ss_frequency; + g->vibrato = 0.0; } @@ -204,7 +201,7 @@ void ss_gen_vibrato(struct ss_gen *g, double depth, double freq) */ void ss_gen_portamento(struct ss_gen *g, double portamento) { - g->portamento = portamento; + g->portamento = portamento; } @@ -222,25 +219,26 @@ void ss_gen_portamento(struct ss_gen *g, double portamento) * frequency, @vol the volume and @note_id a positive, unique * identifier for the note. */ -void ss_gen_play(struct ss_gen *g, double freq, sample_t vol, int note_id, struct ss_wave *w) +void ss_gen_play(struct ss_gen *g, double freq, sample_t vol, int note_id, + struct ss_wave *w) { - /* store data */ - g->note_id = note_id; - g->vol = vol; - g->w = w; - - /* start from the beginning */ - g->cursor = 0; - - /* calculate increment */ - g->inc = freq / w->base_freq; - g->inc *= (double) w->s_rate / (double) ss_frequency; - - /* default sustain, vibrato and portamento */ - ss_gen_sustain(g, 50.0); - ss_gen_attack(g, 0.0); - ss_gen_vibrato(g, 0.0, 0.0); - ss_gen_portamento(g, 0.0); + /* store data */ + g->note_id = note_id; + g->vol = vol; + g->w = w; + + /* start from the beginning */ + g->cursor = 0; + + /* calculate increment */ + g->inc = freq / w->base_freq; + g->inc *= (double) w->s_rate / (double) ss_frequency; + + /* default sustain, vibrato and portamento */ + ss_gen_sustain(g, 50.0); + ss_gen_attack(g, 0.0); + ss_gen_vibrato(g, 0.0, 0.0); + ss_gen_portamento(g, 0.0); } @@ -254,11 +252,11 @@ void ss_gen_play(struct ss_gen *g, double freq, sample_t vol, int note_id, struc */ void ss_gen_release(struct ss_gen *g) { - /* note needs not be tracked anymore */ - g->note_id = -1; + /* note needs not be tracked anymore */ + g->note_id = -1; - /* calculates the delta volume */ - g->dsvol = g->vol / (sample_t) g->sustain; + /* calculates the delta volume */ + g->dsvol = g->vol / (sample_t) g->sustain; } @@ -276,62 +274,62 @@ void ss_gen_release(struct ss_gen *g) */ int ss_gen_frame(struct ss_gen *g, int n_channels, sample_t frame[]) { - int n, m; - int to_free = 0; - double v; - sample_t l_frame[SS_MAX_CHANNELS]; - struct ss_wave *w; - - v = g->cursor; - w = g->w; - - /* process attack */ - if (g->attack) { - g->vol += g->davol; - g->attack--; - } - - /* process vibrato */ - if (g->vib_inc) { - g->vibrato += g->vib_inc; - v += sin(g->vibrato) * g->vib_depth; - } - - /* add samples to frame */ - for (n = 0; n < w->n_channels; n++) - l_frame[n] = ss_get_sample(w, n, v) * g->vol; - - /* spread the frame into n_channels */ - for (n = w->first_channel, m = 0; n < n_channels; n++) { - frame[n] += l_frame[m]; - - n += w->skip_channels; - if (++m == w->n_channels) - m = 0; - } - - /* increment pointer */ - g->cursor += g->inc; - - /* test loop boundaries */ - if (g->cursor > w->loop_end) { - /* loop mode? */ - if (w->loop_start < 0) - to_free = 1; - else - g->cursor = w->loop_start; - } - - /* process sustain */ - if (g->note_id == -1) { - g->vol -= g->dsvol; - - if (--g->sustain <= 0) - to_free = 1; - } - - /* process portamento */ - g->inc += g->portamento; - - return to_free; + int n, m; + int to_free = 0; + double v; + sample_t l_frame[SS_MAX_CHANNELS]; + struct ss_wave *w; + + v = g->cursor; + w = g->w; + + /* process attack */ + if (g->attack) { + g->vol += g->davol; + g->attack--; + } + + /* process vibrato */ + if (g->vib_inc) { + g->vibrato += g->vib_inc; + v += sin(g->vibrato) * g->vib_depth; + } + + /* add samples to frame */ + for (n = 0; n < w->n_channels; n++) + l_frame[n] = ss_get_sample(w, n, v) * g->vol; + + /* spread the frame into n_channels */ + for (n = w->first_channel, m = 0; n < n_channels; n++) { + frame[n] += l_frame[m]; + + n += w->skip_channels; + if (++m == w->n_channels) + m = 0; + } + + /* increment pointer */ + g->cursor += g->inc; + + /* test loop boundaries */ + if (g->cursor > w->loop_end) { + /* loop mode? */ + if (w->loop_start < 0) + to_free = 1; + else + g->cursor = w->loop_start; + } + + /* process sustain */ + if (g->note_id == -1) { + g->vol -= g->dsvol; + + if (--g->sustain <= 0) + to_free = 1; + } + + /* process portamento */ + g->inc += g->portamento; + + return to_free; } diff --git a/ss_input.c b/ss_input.c dissimilarity index 72% index eb91a3c..25ff6fb 100644 --- a/ss_input.c +++ b/ss_input.c @@ -1,711 +1,716 @@ -/* - - Ann Hell Ex Machina - Music Software - Copyright (C) 2003/2008 Angel Ortega - - ss_input.c - Code to load softsynth sounds in different formats - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.triptico.com - -*/ - -#include "config.h" - -#include -#include -#include - -#include "ahxm.h" - -/******************* - Data -********************/ - -/* maximum page size */ -int ss_page_size = 441000; - -/******************* - Code -********************/ - -static int fget16(FILE * f) -/* Reads a 16 bit integer from a file in big endian byte ordering */ -{ - int c; - - c = fgetc(f); - c += (fgetc(f) * 256); - - return c; -} - - -static int fget32(FILE * f) -/* Reads a 32 bit integer from a file in big endian byte ordering */ -{ - int c; - - c = fgetc(f); - c += (fgetc(f) * 256); - c += (fgetc(f) * 65536); - c += (fgetc(f) * 16777216); - - return c; -} - - -static sample_t load_sample(FILE * f, int bits, int sign) -/* loads one sample from a file */ -{ - int s; - - /* if on eof, return silence */ - if (feof(f)) - return 0; - - if (bits == 8) { - s = fgetc(f) - 128; - s <<= 8; - } - else { - if (!sign) - s = fget16(f) - 32768; - else - s = (short int) fget16(f); - } - - return ((sample_t) s) / 32768.0; -} - - -void load_pcm_wave(FILE * f, struct ss_wave *w) -/* loads an interleaved stream from a file */ -{ - int n, m; - - /* fills the channels */ - for (m = 0; m < w->p_size; m++) { - for (n = 0; n < w->n_channels; n++) - w->wave[n][m] = load_sample(f, w->bits, w->sign); - } -} - - -/** - * ss_load_wav_file - Loads a file in .WAV format. - * @file: name of the file - * @base_freq: base frequency - * @min_freq: minimum frequency - * @max_freq: maximum frequency - * @loop_start: frame number of loop start (-1, no loop) - * @loop_end: frame number of loop end (-1, end of wave) - * @first_channel: first channel to start spreading - * @skip_channels: channels to skip when spreading - * - * Loads a file in .WAV format. - */ -struct ss_wave *ss_load_wav_file(const char *file, - double base_freq, double min_freq, double max_freq, - double loop_start, double loop_end, - int first_channel, int skip_channels) -{ - FILE *f; - char dummydata[256]; - int rlen, flen; - short int b_per_sec, n_channels; - char riffid[5], waveid[5], fmtid[5], dataid[5]; - double size; - int s_rate, bits; - struct ss_wave *w; - int p; - - if (*file == '|') - file = transconv_pipe(file + 1, ".wav", "ahxm"); - else { - /* find the file in the library path */ - if ((file = libpath_locate(file)) == NULL) - return NULL; - - /* try converting */ - if ((file = transconv(file, ".wav", "ahxm")) == NULL) - return NULL; - } - - if ((f = fopen(file, "rb")) == NULL) - return NULL; - - fread(riffid, 1, 4, f); - riffid[4] = 0; - fread(&rlen, 1, 4, f); - fread(waveid, 1, 4, f); - waveid[4] = 0; - - if (strcmp(waveid, "WAVE")) { - fclose(f); - return NULL; - } - - fread(fmtid, 1, 4, f); - fmtid[4] = 0; - flen = fget32(f); - - if (flen > 240) - flen = 240; - - if (fget16(f) != 1) { - /* wicked compressed format? fail */ - fclose(f); - return NULL; - } - - n_channels = fget16(f); - s_rate = fget32(f); - b_per_sec = fget32(f); - - bits = fget16(f) / n_channels; - bits *= 8; - - fread(dummydata, 1, (size_t) flen - 14, f); - fread(dataid, 1, 4, f); - dataid[4] = 0; - - size = (double) fget32(f); - if (bits == 16) - size /= 2; - size /= (double) n_channels; - - p = size > ss_page_size ? ss_page_size : size; - - if ((w = ss_alloc_wave(size, n_channels, s_rate, p)) != NULL) { - w->base_freq = base_freq; - w->min_freq = min_freq; - w->max_freq = max_freq; - - w->loop_start = loop_start; - - if (loop_end < 0) - w->loop_end = size; - else - w->loop_end = loop_end; - - w->first_channel = first_channel; - w->skip_channels = skip_channels; - - /* fill the info needed for paging */ - w->filename = strdup(file); - w->f_pos = ftell(f); - w->bits = bits; - w->sign = 1; - - /* set the page offset further the end, to - force a page reading the first time it's used */ - w->p_offset = (int) size; - } - - fclose(f); - - return w; -} - - -/** - * ss_load_pat_file - Loads an instrument in .PAT format. - * @i: The instrument - * @filename: filename holding the instrument - * - * Loads data from a Gravis Ultrasound patch (.PAT) format and - * stores it as layers for an instrument. - * - * Returns -100 if the file could not be read, -101 or -102 - * if the file is not recognized as a .PAT file, or 0 if - * everything went OK. - */ -int ss_load_pat_file(struct ss_ins *i, const char *file) -{ - FILE *f; - char buffer[512]; - int m, n, o; - int n_layers; - int flags, bits, sign, loop, pingpong; - struct ss_wave *w; - - if ((f = libpath_fopen(file, "rb")) == NULL) - return -100; - - /* read signatures */ - fread(buffer, 12, 1, f); - if (strcmp(buffer, "GF1PATCH110") != 0) { - fclose(f); - return -101; - } - - fread(buffer, 10, 1, f); - if (strcmp(buffer, "ID#000002") != 0) { - fclose(f); - return -102; - } - - /* skip description */ - fread(buffer, 65, 1, f); - - /* ignore volume */ - fget16(f); - - /* skip */ - fread(buffer, 109, 1, f); - - /* # of layers */ - n_layers = fgetc(f); - - /* skip */ - fread(buffer, 40, 1, f); - - for (n = 0; n < n_layers; n++) { - int size, s_rate; - double loop_start, loop_end; - double min_freq, max_freq, base_freq; - - /* layer name */ - fread(buffer, 8, 1, f); - - size = (double) fget32(f); - loop_start = (double) fget32(f); - loop_end = (double) fget32(f); - s_rate = fget16(f); - - min_freq = ((double) fget32(f)) / 1000.0; - max_freq = ((double) fget32(f)) / 1000.0; - base_freq = ((double) fget32(f)) / 1000.0; - - if (base_freq < 0) - break; - - /* ignore fine-tune */ - fget16(f); - - /* ignore pan position */ - fgetc(f); - - /* skip envelope rate, value, tremolo and vibrato */ - fread(buffer, 18, 1, f); - - flags = fgetc(f); - - bits = flags & 0x01 ? 16 : 8; - sign = flags & 0x02 ? 0 : 1; - loop = flags & 0x04 ? 1 : 0; - pingpong = flags & 0x08 ? 1 : 0; - - if (bits == 16) { - size /= 2; - loop_start /= 2; - loop_end /= 2; - } - - /* skip frequency scale data */ - fget16(f); - fget16(f); - - /* skip reserved */ - fread(buffer, 36, 1, f); - - if ((w = ss_alloc_wave(size, 1, s_rate, -1)) == NULL) - break; - - /* set the rest of values */ - w->loop_start = loop_start; - w->loop_end = loop_end; - w->base_freq = base_freq; - w->min_freq = min_freq; - w->max_freq = max_freq; - w->bits = bits; - w->sign = sign; - - /* load the wave */ - ss_prepare_wave(w); - load_pcm_wave(f, w); - - if (pingpong && loop) { - int loop_size; - sample_t *ptr; - - /* if ping-pong, realloc space for a reverse - version of the loop */ - loop_size = (int) (loop_end - loop_start); - - ptr = (sample_t *) malloc((size + loop_size + 1) - * sizeof(sample_t)); - - /* transfer start and loop */ - for (m = 0; m <= (int) loop_end; m++) - ptr[m] = w->wave[0][m]; - - /* transfer a reversed version of the loop */ - for (o = m - 1; o >= loop_start; o--, m++) - ptr[m] = w->wave[0][o]; - - /* transfer the end */ - for (o = loop_end + 1; o < size; o++, m++) - ptr[m] = w->wave[0][o]; - - w->loop_end += (double) loop_size; - w->size += (double) loop_size; - w->p_size += loop_size; - - /* free and swap */ - free(w->wave[0]); - w->wave[0] = ptr; - } - - if (loop == 0) - w->loop_start = -1; - - /* finally add layer to instrument */ - ss_ins_add_layer(i, w); - } - - fclose(f); - return 0; -} - - -/* Soundfont support */ - -#define CID(a,b,c,d) (((d)<<24)+((c)<<16)+((b)<<8)+((a))) - -#define CID_RIFF CID('R','I','F','F') -#define CID_LIST CID('L','I','S','T') -#define CID_INFO CID('I','N','F','O') -#define CID_sdta CID('s','d','t','a') -#define CID_snam CID('s','n','a','m') -#define CID_smpl CID('s','m','p','l') -#define CID_pdta CID('p','d','t','a') -#define CID_phdr CID('p','h','d','r') -#define CID_pbag CID('p','b','a','g') -#define CID_pmod CID('p','m','o','d') -#define CID_pgen CID('p','g','e','n') -#define CID_inst CID('i','n','s','t') -#define CID_ibag CID('i','b','a','g') -#define CID_imod CID('i','m','o','d') -#define CID_igen CID('i','g','e','n') -#define CID_shdr CID('s','h','d','r') -#define CID_ifil CID('i','f','i','l') -#define CID_isng CID('i','s','n','g') -#define CID_irom CID('i','r','o','m') -#define CID_iver CID('i','v','e','r') -#define CID_INAM CID('I','N','A','M') -#define CID_IPRD CID('I','P','R','D') -#define CID_ICOP CID('I','C','O','P') -#define CID_sfbk CID('s','f','b','k') -#define CID_ICRD CID('I','C','R','D') -#define CID_IENG CID('I','E','N','G') -#define CID_ICMT CID('I','C','M','T') -#define CID_ISFT CID('I','S','F','T') - -#define MAX_LAYERS 128 - -static int base_notes[MAX_LAYERS]; -static int min_notes[MAX_LAYERS]; -static int max_notes[MAX_LAYERS]; -static int sampleids[MAX_LAYERS]; - -#define CALC_END(s,f) (ftell(f) + (s) + ((s) & 1)) - - -int ss_load_sf2_file(struct ss_ins *i, const char *file, const char *iname) -{ - FILE *f; - int n, num; - int cid, fsize, fend; - int sample_offset = 0; - int ibag_s = -1, ibag_e = -1; - int igen_s = -1, igen_e = -1; - char tmp[21]; - int i_layers = 0; - - if ((f = libpath_fopen(file, "rb")) == NULL) - return -100; - - if ((cid = fget32(f)) != CID_RIFF) - return -101; - - fsize = fget32(f); - fend = CALC_END(fsize, f); - - if ((cid = fget32(f)) != CID_sfbk) - return -102; - - while (ftell(f) < fend) { - int csize, cend; - - cid = fget32(f); - csize = fget32(f); - cend = CALC_END(csize, f); - - switch (cid) { - case CID_LIST: - - cid = fget32(f); - - while (ftell(f) < cend) { - int scid, ssize, send; - - scid = fget32(f); - ssize = fget32(f); - send = CALC_END(ssize, f); - - switch (cid) { - case CID_INFO: - - switch (scid) { - case CID_ifil: - - if (fget16(f) < 2) - return -103; - fget16(f); - break; - - case CID_INAM: - case CID_irom: - case CID_ICRD: - case CID_IENG: - case CID_IPRD: - case CID_ICOP: - case CID_ISFT: - /* misc. data (ignored) */ - break; - } - - fseek(f, send, SEEK_SET); - break; - - case CID_pdta: - - switch (scid) { - case CID_phdr: - /* preset headers */ - break; - - case CID_pbag: - /* preset index list */ - break; - - case CID_pgen: - /* preset generator list */ - break; - - case CID_inst: - /* instrument names */ - num = ssize / 22; - - for (n = 0; n < num; n++) { - int i; - - fread(tmp, 20, 1, f); - tmp[20] = '\0'; - - /* trim spaces */ - for (i = 20; i && tmp[i] == '\0'; i--); - for (; i && tmp[i] == ' '; i--) - tmp[i] = '\0'; - - i = fget16(f); - - /* if ibag_s is set and ibag_e isn't, - pick this as the end */ - if (ibag_s != -1 && ibag_e == -1) - ibag_e = i; - - if (iname != NULL) { - if (strcmp(iname, tmp) == 0) - ibag_s = i; - } - else { - printf("[%s]\n", tmp); - } - } - - break; - - case CID_ibag: - - num = ssize / 4; - - for (n = 0; n < num; n++) { - int igen = fget16(f); - fget16(f); - - /* pick start of igen */ - if (n == ibag_s) - igen_s = igen; - - /* pick end of igen */ - if (n == ibag_e) - igen_e = igen; - } - - break; - - case CID_igen: - - num = ssize / 4; - - /* init layers */ - for (n = 0; n < MAX_LAYERS; n++) { - base_notes[n] = -1; - min_notes[n] = 0; - max_notes[n] = 127; - } - - for (n = 0; n < num; n++) { - int op = fget16(f); - int am = fget16(f); - - if (n >= igen_s && n < igen_e) { - - if (op == 58) /* overridingRootKey */ - base_notes[i_layers] = am; - - if (op == 43) { /* keyRange */ - min_notes[i_layers] = am & 0xff; - max_notes[i_layers] = am >> 8; - } - - if (op == 53) { /* sampleID */ - sampleids[i_layers++] = am; - } - } - } - - break; - - case CID_shdr: - /* sample headers */ - num = ssize / 46; - - for (n = 0; n < num; n++) { - int m; - int start, end; - int loop_start, loop_end; - int sample_rate, base_note; - int sample_type; - - fread(tmp, 20, 1, f); - tmp[20] = '\0'; - - start = fget32(f); - end = fget32(f); - loop_start = fget32(f); - loop_end = fget32(f); - sample_rate = fget32(f); - base_note = fgetc(f); - fgetc(f); /* correction */ - fget16(f); /* sample_link */ - sample_type = fget16(f); - - for (m = 0; m < i_layers; m++) { - struct ss_wave *w; - int t; - - if (sampleids[m] != n) - continue; - - /* create wave! */ - if (base_notes[m] != -1) - base_note = base_notes[m]; - - if (verbose >= 2) { - printf("SF2 Sample:\t[%s]\n", tmp); - printf("start/end:\t%d/%d (%d)\n", start, end, end - start); - printf("loop:\t\t%d/%d\n", loop_start, loop_end); - printf("rate/stype:\t%d/%d\n", sample_rate, sample_type); - printf("notes:\t\t%d/%d/%d\n", - min_notes[m], base_note, max_notes[m]); - } - - w = ss_alloc_wave( - end - start, 1, - sample_rate, -1 - ); - - w->loop_start = loop_start - start; - w->loop_end = loop_end - start; - w->base_freq = ss_note_frequency(base_note); - w->min_freq = ss_note_frequency(min_notes[m]); - w->max_freq = ss_note_frequency(max_notes[m]); - - w->bits = 16; - w->sign = 1; - - switch (sample_type) { - case 2: /* right */ - w->first_channel = 1; - /* fallthrough */ - case 4: /* left */ - w->skip_channels = 1; - break; - } - - t = ftell(f); - - fseek(f, sample_offset + (start * 2), SEEK_SET); - - ss_prepare_wave(w); - load_pcm_wave(f, w); - - fseek(f, t, SEEK_SET); - - ss_ins_add_layer(i, w); - } - } - - break; - } - - fseek(f, send, SEEK_SET); - break; - - case CID_sdta: - - /* sample info starts here */ - sample_offset = ftell(f); - - fseek(f, send, SEEK_SET); - break; - - default: - /* unknown chunk */ - fseek(f, cend, SEEK_SET); - break; - } - } - - break; - - default: - fseek(f, cend, SEEK_SET); - break; - } - } - - fclose(f); - - if (iname != NULL && ibag_s == -1) - return -104; - - return 0; -} +/* + + Ann Hell Ex Machina - Music Software + Copyright (C) 2003/2008 Angel Ortega + + ss_input.c - Code to load softsynth sounds in different formats + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.triptico.com + +*/ + +#include "config.h" + +#include +#include +#include + +#include "ahxm.h" + + +/** data **/ + +/* maximum page size */ +int ss_page_size = 441000; + + +/** code **/ + +static int fget16(FILE * f) +/* Reads a 16 bit integer from a file in big endian byte ordering */ +{ + int c; + + c = fgetc(f); + c += (fgetc(f) * 256); + + return c; +} + + +static int fget32(FILE * f) +/* Reads a 32 bit integer from a file in big endian byte ordering */ +{ + int c; + + c = fgetc(f); + c += (fgetc(f) * 256); + c += (fgetc(f) * 65536); + c += (fgetc(f) * 16777216); + + return c; +} + + +static sample_t load_sample(FILE * f, int bits, int sign) +/* loads one sample from a file */ +{ + int s; + + /* if on eof, return silence */ + if (feof(f)) + return 0; + + if (bits == 8) { + s = fgetc(f) - 128; + s <<= 8; + } + else { + if (!sign) + s = fget16(f) - 32768; + else + s = (short int) fget16(f); + } + + return ((sample_t) s) / 32768.0; +} + + +void load_pcm_wave(FILE * f, struct ss_wave *w) +/* loads an interleaved stream from a file */ +{ + int n, m; + + /* fills the channels */ + for (m = 0; m < w->p_size; m++) { + for (n = 0; n < w->n_channels; n++) + w->wave[n][m] = load_sample(f, w->bits, w->sign); + } +} + + +/** + * ss_load_wav_file - Loads a file in .WAV format. + * @file: name of the file + * @base_freq: base frequency + * @min_freq: minimum frequency + * @max_freq: maximum frequency + * @loop_start: frame number of loop start (-1, no loop) + * @loop_end: frame number of loop end (-1, end of wave) + * @first_channel: first channel to start spreading + * @skip_channels: channels to skip when spreading + * + * Loads a file in .WAV format. + */ +struct ss_wave *ss_load_wav_file(const char *file, + double base_freq, double min_freq, + double max_freq, double loop_start, + double loop_end, int first_channel, + int skip_channels) +{ + FILE *f; + char dummydata[256]; + int rlen, flen; + short int b_per_sec, n_channels; + char riffid[5], waveid[5], fmtid[5], dataid[5]; + double size; + int s_rate, bits; + struct ss_wave *w; + int p; + + if (*file == '|') + file = transconv_pipe(file + 1, ".wav", "ahxm"); + else { + /* find the file in the library path */ + if ((file = libpath_locate(file)) == NULL) + return NULL; + + /* try converting */ + if ((file = transconv(file, ".wav", "ahxm")) == NULL) + return NULL; + } + + if ((f = fopen(file, "rb")) == NULL) + return NULL; + + fread(riffid, 1, 4, f); + riffid[4] = 0; + fread(&rlen, 1, 4, f); + fread(waveid, 1, 4, f); + waveid[4] = 0; + + if (strcmp(waveid, "WAVE")) { + fclose(f); + return NULL; + } + + fread(fmtid, 1, 4, f); + fmtid[4] = 0; + flen = fget32(f); + + if (flen > 240) + flen = 240; + + if (fget16(f) != 1) { + /* wicked compressed format? fail */ + fclose(f); + return NULL; + } + + n_channels = fget16(f); + s_rate = fget32(f); + b_per_sec = fget32(f); + + bits = fget16(f) / n_channels; + bits *= 8; + + fread(dummydata, 1, (size_t) flen - 14, f); + fread(dataid, 1, 4, f); + dataid[4] = 0; + + size = (double) fget32(f); + if (bits == 16) + size /= 2; + size /= (double) n_channels; + + p = size > ss_page_size ? ss_page_size : size; + + if ((w = ss_alloc_wave(size, n_channels, s_rate, p)) != NULL) { + w->base_freq = base_freq; + w->min_freq = min_freq; + w->max_freq = max_freq; + + w->loop_start = loop_start; + + if (loop_end < 0) + w->loop_end = size; + else + w->loop_end = loop_end; + + w->first_channel = first_channel; + w->skip_channels = skip_channels; + + /* fill the info needed for paging */ + w->filename = strdup(file); + w->f_pos = ftell(f); + w->bits = bits; + w->sign = 1; + + /* set the page offset further the end, to + force a page reading the first time it's used */ + w->p_offset = (int) size; + } + + fclose(f); + + return w; +} + + +/** + * ss_load_pat_file - Loads an instrument in .PAT format. + * @i: The instrument + * @filename: filename holding the instrument + * + * Loads data from a Gravis Ultrasound patch (.PAT) format and + * stores it as layers for an instrument. + * + * Returns -100 if the file could not be read, -101 or -102 + * if the file is not recognized as a .PAT file, or 0 if + * everything went OK. + */ +int ss_load_pat_file(struct ss_ins *i, const char *file) +{ + FILE *f; + char buffer[512]; + int m, n, o; + int n_layers; + int flags, bits, sign, loop, pingpong; + struct ss_wave *w; + + if ((f = libpath_fopen(file, "rb")) == NULL) + return -100; + + /* read signatures */ + fread(buffer, 12, 1, f); + if (strcmp(buffer, "GF1PATCH110") != 0) { + fclose(f); + return -101; + } + + fread(buffer, 10, 1, f); + if (strcmp(buffer, "ID#000002") != 0) { + fclose(f); + return -102; + } + + /* skip description */ + fread(buffer, 65, 1, f); + + /* ignore volume */ + fget16(f); + + /* skip */ + fread(buffer, 109, 1, f); + + /* # of layers */ + n_layers = fgetc(f); + + /* skip */ + fread(buffer, 40, 1, f); + + for (n = 0; n < n_layers; n++) { + int size, s_rate; + double loop_start, loop_end; + double min_freq, max_freq, base_freq; + + /* layer name */ + fread(buffer, 8, 1, f); + + size = (double) fget32(f); + loop_start = (double) fget32(f); + loop_end = (double) fget32(f); + s_rate = fget16(f); + + min_freq = ((double) fget32(f)) / 1000.0; + max_freq = ((double) fget32(f)) / 1000.0; + base_freq = ((double) fget32(f)) / 1000.0; + + if (base_freq < 0) + break; + + /* ignore fine-tune */ + fget16(f); + + /* ignore pan position */ + fgetc(f); + + /* skip envelope rate, value, tremolo and vibrato */ + fread(buffer, 18, 1, f); + + flags = fgetc(f); + + bits = flags & 0x01 ? 16 : 8; + sign = flags & 0x02 ? 0 : 1; + loop = flags & 0x04 ? 1 : 0; + pingpong = flags & 0x08 ? 1 : 0; + + if (bits == 16) { + size /= 2; + loop_start /= 2; + loop_end /= 2; + } + + /* skip frequency scale data */ + fget16(f); + fget16(f); + + /* skip reserved */ + fread(buffer, 36, 1, f); + + if ((w = ss_alloc_wave(size, 1, s_rate, -1)) == NULL) + break; + + /* set the rest of values */ + w->loop_start = loop_start; + w->loop_end = loop_end; + w->base_freq = base_freq; + w->min_freq = min_freq; + w->max_freq = max_freq; + w->bits = bits; + w->sign = sign; + + /* load the wave */ + ss_prepare_wave(w); + load_pcm_wave(f, w); + + if (pingpong && loop) { + int loop_size; + sample_t *ptr; + + /* if ping-pong, realloc space for a reverse + version of the loop */ + loop_size = (int) (loop_end - loop_start); + + ptr = (sample_t *) malloc((size + loop_size + 1) + * sizeof(sample_t)); + + /* transfer start and loop */ + for (m = 0; m <= (int) loop_end; m++) + ptr[m] = w->wave[0][m]; + + /* transfer a reversed version of the loop */ + for (o = m - 1; o >= loop_start; o--, m++) + ptr[m] = w->wave[0][o]; + + /* transfer the end */ + for (o = loop_end + 1; o < size; o++, m++) + ptr[m] = w->wave[0][o]; + + w->loop_end += (double) loop_size; + w->size += (double) loop_size; + w->p_size += loop_size; + + /* free and swap */ + free(w->wave[0]); + w->wave[0] = ptr; + } + + if (loop == 0) + w->loop_start = -1; + + /* finally add layer to instrument */ + ss_ins_add_layer(i, w); + } + + fclose(f); + return 0; +} + + +/* Soundfont support */ + +#define CID(a,b,c,d) (((d)<<24)+((c)<<16)+((b)<<8)+((a))) + +#define CID_RIFF CID('R','I','F','F') +#define CID_LIST CID('L','I','S','T') +#define CID_INFO CID('I','N','F','O') +#define CID_sdta CID('s','d','t','a') +#define CID_snam CID('s','n','a','m') +#define CID_smpl CID('s','m','p','l') +#define CID_pdta CID('p','d','t','a') +#define CID_phdr CID('p','h','d','r') +#define CID_pbag CID('p','b','a','g') +#define CID_pmod CID('p','m','o','d') +#define CID_pgen CID('p','g','e','n') +#define CID_inst CID('i','n','s','t') +#define CID_ibag CID('i','b','a','g') +#define CID_imod CID('i','m','o','d') +#define CID_igen CID('i','g','e','n') +#define CID_shdr CID('s','h','d','r') +#define CID_ifil CID('i','f','i','l') +#define CID_isng CID('i','s','n','g') +#define CID_irom CID('i','r','o','m') +#define CID_iver CID('i','v','e','r') +#define CID_INAM CID('I','N','A','M') +#define CID_IPRD CID('I','P','R','D') +#define CID_ICOP CID('I','C','O','P') +#define CID_sfbk CID('s','f','b','k') +#define CID_ICRD CID('I','C','R','D') +#define CID_IENG CID('I','E','N','G') +#define CID_ICMT CID('I','C','M','T') +#define CID_ISFT CID('I','S','F','T') + +#define MAX_LAYERS 128 + +static int base_notes[MAX_LAYERS]; +static int min_notes[MAX_LAYERS]; +static int max_notes[MAX_LAYERS]; +static int sampleids[MAX_LAYERS]; + +#define CALC_END(s,f) (ftell(f) + (s) + ((s) & 1)) + + +int ss_load_sf2_file(struct ss_ins *i, const char *file, const char *iname) +{ + FILE *f; + int n, num; + int cid, fsize, fend; + int sample_offset = 0; + int ibag_s = -1, ibag_e = -1; + int igen_s = -1, igen_e = -1; + char tmp[21]; + int i_layers = 0; + + if ((f = libpath_fopen(file, "rb")) == NULL) + return -100; + + if ((cid = fget32(f)) != CID_RIFF) + return -101; + + fsize = fget32(f); + fend = CALC_END(fsize, f); + + if ((cid = fget32(f)) != CID_sfbk) + return -102; + + while (ftell(f) < fend) { + int csize, cend; + + cid = fget32(f); + csize = fget32(f); + cend = CALC_END(csize, f); + + switch (cid) { + case CID_LIST: + + cid = fget32(f); + + while (ftell(f) < cend) { + int scid, ssize, send; + + scid = fget32(f); + ssize = fget32(f); + send = CALC_END(ssize, f); + + switch (cid) { + case CID_INFO: + + switch (scid) { + case CID_ifil: + + if (fget16(f) < 2) + return -103; + fget16(f); + break; + + case CID_INAM: + case CID_irom: + case CID_ICRD: + case CID_IENG: + case CID_IPRD: + case CID_ICOP: + case CID_ISFT: + /* misc. data (ignored) */ + break; + } + + fseek(f, send, SEEK_SET); + break; + + case CID_pdta: + + switch (scid) { + case CID_phdr: + /* preset headers */ + break; + + case CID_pbag: + /* preset index list */ + break; + + case CID_pgen: + /* preset generator list */ + break; + + case CID_inst: + /* instrument names */ + num = ssize / 22; + + for (n = 0; n < num; n++) { + int i; + + fread(tmp, 20, 1, f); + tmp[20] = '\0'; + + /* trim spaces */ + for (i = 20; i && tmp[i] == '\0'; i--); + for (; i && tmp[i] == ' '; i--) + tmp[i] = '\0'; + + i = fget16(f); + + /* if ibag_s is set and ibag_e isn't, + pick this as the end */ + if (ibag_s != -1 && ibag_e == -1) + ibag_e = i; + + if (iname != NULL) { + if (strcmp(iname, tmp) == 0) + ibag_s = i; + } + else { + printf("[%s]\n", tmp); + } + } + + break; + + case CID_ibag: + + num = ssize / 4; + + for (n = 0; n < num; n++) { + int igen = fget16(f); + fget16(f); + + /* pick start of igen */ + if (n == ibag_s) + igen_s = igen; + + /* pick end of igen */ + if (n == ibag_e) + igen_e = igen; + } + + break; + + case CID_igen: + + num = ssize / 4; + + /* init layers */ + for (n = 0; n < MAX_LAYERS; n++) { + base_notes[n] = -1; + min_notes[n] = 0; + max_notes[n] = 127; + } + + for (n = 0; n < num; n++) { + int op = fget16(f); + int am = fget16(f); + + if (n >= igen_s && n < igen_e) { + + if (op == 58) /* overridingRootKey */ + base_notes[i_layers] = am; + + if (op == 43) { /* keyRange */ + min_notes[i_layers] = am & 0xff; + max_notes[i_layers] = am >> 8; + } + + if (op == 53) { /* sampleID */ + sampleids[i_layers++] = am; + } + } + } + + break; + + case CID_shdr: + /* sample headers */ + num = ssize / 46; + + for (n = 0; n < num; n++) { + int m; + int start, end; + int loop_start, loop_end; + int sample_rate, base_note; + int sample_type; + + fread(tmp, 20, 1, f); + tmp[20] = '\0'; + + start = fget32(f); + end = fget32(f); + loop_start = fget32(f); + loop_end = fget32(f); + sample_rate = fget32(f); + base_note = fgetc(f); + fgetc(f); /* correction */ + fget16(f); /* sample_link */ + sample_type = fget16(f); + + for (m = 0; m < i_layers; m++) { + struct ss_wave *w; + int t; + + if (sampleids[m] != n) + continue; + + /* create wave! */ + if (base_notes[m] != -1) + base_note = base_notes[m]; + + if (verbose >= 2) { + printf("SF2 Sample:\t[%s]\n", tmp); + printf("start/end:\t%d/%d (%d)\n", + start, end, end - start); + printf("loop:\t\t%d/%d\n", loop_start, + loop_end); + printf("rate/stype:\t%d/%d\n", + sample_rate, sample_type); + printf("notes:\t\t%d/%d/%d\n", + min_notes[m], base_note, + max_notes[m]); + } + + w = ss_alloc_wave(end - start, 1, + sample_rate, -1); + + w->loop_start = loop_start - start; + w->loop_end = loop_end - start; + w->base_freq = + ss_note_frequency(base_note); + w->min_freq = + ss_note_frequency(min_notes[m]); + w->max_freq = + ss_note_frequency(max_notes[m]); + + w->bits = 16; + w->sign = 1; + + switch (sample_type) { + case 2: /* right */ + w->first_channel = 1; + /* fallthrough */ + case 4: /* left */ + w->skip_channels = 1; + break; + } + + t = ftell(f); + + fseek(f, sample_offset + (start * 2), + SEEK_SET); + + ss_prepare_wave(w); + load_pcm_wave(f, w); + + fseek(f, t, SEEK_SET); + + ss_ins_add_layer(i, w); + } + } + + break; + } + + fseek(f, send, SEEK_SET); + break; + + case CID_sdta: + + /* sample info starts here */ + sample_offset = ftell(f); + + fseek(f, send, SEEK_SET); + break; + + default: + /* unknown chunk */ + fseek(f, cend, SEEK_SET); + break; + } + } + + break; + + default: + fseek(f, cend, SEEK_SET); + break; + } + } + + fclose(f); + + if (iname != NULL && ibag_s == -1) + return -104; + + return 0; +} diff --git a/ss_ins.c b/ss_ins.c index f89848d..ec84988 100644 --- a/ss_ins.c +++ b/ss_ins.c @@ -32,13 +32,6 @@ #include "ahxm.h" -/******************* - Data -********************/ - -/******************* - Code -********************/ /** * ss_ins_init - Initializes an instrument. @@ -48,17 +41,17 @@ */ void ss_ins_init(struct ss_ins *i) { - memset(i, '\0', sizeof(struct ss_ins)); + memset(i, '\0', sizeof(struct ss_ins)); - /* default channels: stereo left and right, full volume */ - ss_ins_set_channel(i, 0, 1.0); - ss_ins_set_channel(i, 1, 1.0); + /* default channels: stereo left and right, full volume */ + ss_ins_set_channel(i, 0, 1.0); + ss_ins_set_channel(i, 1, 1.0); - /* sustain shouldn't be 0 to avoid end of note clicks */ - ss_ins_set_sustain(i, 50.0); - ss_ins_set_attack(i, 0.0); - ss_ins_set_vibrato(i, 0.0, 0.0); - ss_ins_set_portamento(i, 0.0); + /* sustain shouldn't be 0 to avoid end of note clicks */ + ss_ins_set_sustain(i, 50.0); + ss_ins_set_attack(i, 0.0); + ss_ins_set_vibrato(i, 0.0, 0.0); + ss_ins_set_portamento(i, 0.0); } @@ -72,7 +65,7 @@ void ss_ins_init(struct ss_ins *i) */ void ss_ins_disable(struct ss_ins *i) { - i->disabled = 1; + i->disabled = 1; } @@ -87,12 +80,12 @@ void ss_ins_disable(struct ss_ins *i) */ void ss_ins_add_layer(struct ss_ins *i, struct ss_wave *w) { - /* grow layers */ - GROW(i->layers, i->n_layers, struct ss_wave *); + /* grow layers */ + GROW(i->layers, i->n_layers, struct ss_wave *); - i->layers[i->n_layers] = w; + i->layers[i->n_layers] = w; - i->n_layers++; + i->n_layers++; } @@ -108,30 +101,31 @@ void ss_ins_add_layer(struct ss_ins *i, struct ss_wave *w) * (allowing it to be used as an enumerator). If no layer is found, NULL * is returned. */ -struct ss_wave *ss_ins_find_layer(const struct ss_ins *i, double freq, int *off) +struct ss_wave *ss_ins_find_layer(const struct ss_ins *i, double freq, + int *off) { - int n = 0; - struct ss_wave *w = NULL; + int n = 0; + struct ss_wave *w = NULL; - /* if off is NULL, point to the first layer */ - if (off == NULL) - off = &n; + /* if off is NULL, point to the first layer */ + if (off == NULL) + off = &n; - /* find a matching layer, starting from *off */ - for (; *off < i->n_layers; (*off)++) { - w = i->layers[*off]; + /* find a matching layer, starting from *off */ + for (; *off < i->n_layers; (*off)++) { + w = i->layers[*off]; - if (freq >= w->min_freq && freq <= w->max_freq) - break; - } + if (freq >= w->min_freq && freq <= w->max_freq) + break; + } - /* passed the end; none found */ - if (*off == i->n_layers) - w = NULL; - else - (*off)++; + /* passed the end; none found */ + if (*off == i->n_layers) + w = NULL; + else + (*off)++; - return w; + return w; } @@ -147,24 +141,24 @@ struct ss_wave *ss_ins_find_layer(const struct ss_ins *i, double freq, int *off) */ void ss_ins_set_channel(struct ss_ins *i, int channel, sample_t vol) { - /* if channel is new, alloc space for it */ - if (channel <= i->n_channels) { - int n; + /* if channel is new, alloc space for it */ + if (channel <= i->n_channels) { + int n; - GROW(i->vols, channel, sample_t); - GROW(i->effs, channel, struct ss_eff *); + GROW(i->vols, channel, sample_t); + GROW(i->effs, channel, struct ss_eff *); - /* fill newly allocated space */ - for (n = i->n_channels; n <= channel; n++) { - i->vols[n] = 1.0; - i->effs[n] = NULL; - } + /* fill newly allocated space */ + for (n = i->n_channels; n <= channel; n++) { + i->vols[n] = 1.0; + i->effs[n] = NULL; + } - i->n_channels = channel + 1; - } + i->n_channels = channel + 1; + } - /* store volume */ - i->vols[channel] = vol; + /* store volume */ + i->vols[channel] = vol; } @@ -178,7 +172,7 @@ void ss_ins_set_channel(struct ss_ins *i, int channel, sample_t vol) */ void ss_ins_set_sustain(struct ss_ins *i, double sustain) { - i->sustain = sustain; + i->sustain = sustain; } @@ -192,7 +186,7 @@ void ss_ins_set_sustain(struct ss_ins *i, double sustain) */ void ss_ins_set_attack(struct ss_ins *i, double attack) { - i->attack = attack; + i->attack = attack; } @@ -207,8 +201,8 @@ void ss_ins_set_attack(struct ss_ins *i, double attack) */ void ss_ins_set_vibrato(struct ss_ins *i, double depth, double freq) { - i->vib_depth = depth; - i->vib_freq = freq; + i->vib_depth = depth; + i->vib_freq = freq; } @@ -221,7 +215,7 @@ void ss_ins_set_vibrato(struct ss_ins *i, double depth, double freq) */ void ss_ins_set_portamento(struct ss_ins *i, double portamento) { - i->portamento = portamento; + i->portamento = portamento; } @@ -240,28 +234,29 @@ void ss_ins_set_portamento(struct ss_ins *i, double portamento) * Returns -1 if the instrument is disabled, -2 if no free generators * were found, or 0 if everything went ok. */ -int ss_ins_play(struct ss_ins *i, double freq, sample_t vol, int note_id, struct ss_wave *w) +int ss_ins_play(struct ss_ins *i, double freq, sample_t vol, int note_id, + struct ss_wave *w) { - struct ss_gen *g; + struct ss_gen *g; - /* if the instrument is disabled, no more notes are allowed */ - if (i->disabled) - return -1; + /* if the instrument is disabled, no more notes are allowed */ + if (i->disabled) + return -1; - /* get a free generator, or fail */ - if ((g = ss_gen_alloc(&i->gens)) == NULL) - return -2; + /* get a free generator, or fail */ + if ((g = ss_gen_alloc(&i->gens)) == NULL) + return -2; - /* start the generator */ - ss_gen_play(g, freq, vol, note_id, w); + /* start the generator */ + ss_gen_play(g, freq, vol, note_id, w); - /* set generator parameters */ - ss_gen_sustain(g, i->sustain); - ss_gen_attack(g, i->attack); - ss_gen_vibrato(g, i->vib_depth, i->vib_freq); - ss_gen_portamento(g, i->portamento); + /* set generator parameters */ + ss_gen_sustain(g, i->sustain); + ss_gen_attack(g, i->attack); + ss_gen_vibrato(g, i->vib_depth, i->vib_freq); + ss_gen_portamento(g, i->portamento); - return 1; + return 1; } @@ -282,18 +277,18 @@ int ss_ins_play(struct ss_ins *i, double freq, sample_t vol, int note_id, struct */ int ss_ins_note_on(struct ss_ins *i, int note, sample_t vol, int note_id) { - int n, g; - struct ss_wave *w; - double freq; + int n, g; + struct ss_wave *w; + double freq; - freq = ss_note_frequency(note); + freq = ss_note_frequency(note); - for (n = g = 0; (w = ss_ins_find_layer(i, freq, &n)) != NULL; g++) { - if (ss_ins_play(i, freq, vol, note_id, w) < 0) - break; - } + for (n = g = 0; (w = ss_ins_find_layer(i, freq, &n)) != NULL; g++) { + if (ss_ins_play(i, freq, vol, note_id, w) < 0) + break; + } - return g; + return g; } @@ -306,13 +301,13 @@ int ss_ins_note_on(struct ss_ins *i, int note, sample_t vol, int note_id) */ void ss_ins_note_off(struct ss_ins *i, int note_id) { - struct ss_gen *g; + struct ss_gen *g; - /* releases all generators with that note_id */ - for (g = i->gens; g != NULL; g = g->next) { - if (g->note_id == note_id) - ss_gen_release(g); - } + /* releases all generators with that note_id */ + for (g = i->gens; g != NULL; g = g->next) { + if (g->note_id == note_id) + ss_gen_release(g); + } } @@ -329,35 +324,35 @@ void ss_ins_note_off(struct ss_ins *i, int note_id) */ int ss_ins_frame(struct ss_ins *i, sample_t frame[]) { - struct ss_gen *g; - struct ss_gen *t; - int n; - sample_t l_frame[SS_MAX_CHANNELS]; + struct ss_gen *g; + struct ss_gen *t; + int n; + sample_t l_frame[SS_MAX_CHANNELS]; - /* if instrument is disabled and there is no more generators, exit */ - if (i->disabled && i->gens == NULL) { - /* reset all effects */ - for (n = 0; n < i->n_channels; n++) - ss_eff_off(&i->effs[n]); + /* if instrument is disabled and there is no more generators, exit */ + if (i->disabled && i->gens == NULL) { + /* reset all effects */ + for (n = 0; n < i->n_channels; n++) + ss_eff_off(&i->effs[n]); - return 0; - } + return 0; + } - /* resets this local frame */ - ss_output_init_frame(l_frame); + /* resets this local frame */ + ss_output_init_frame(l_frame); - /* loops through the generators */ - for (g = i->gens; g != NULL; g = t) { - t = g->next; + /* loops through the generators */ + for (g = i->gens; g != NULL; g = t) { + t = g->next; - /* if the generator has stopped, free it */ - if (ss_gen_frame(g, i->n_channels, l_frame)) - ss_gen_free(&i->gens, g); - } + /* if the generator has stopped, free it */ + if (ss_gen_frame(g, i->n_channels, l_frame)) + ss_gen_free(&i->gens, g); + } - /* loops through the effects and remixes */ - for (n = 0; n < i->n_channels; n++) - frame[n] += ss_eff_process(i->effs[n], l_frame[n] * i->vols[n]); + /* loops through the effects and remixes */ + for (n = 0; n < i->n_channels; n++) + frame[n] += ss_eff_process(i->effs[n], l_frame[n] * i->vols[n]); - return 1; + return 1; } diff --git a/ss_outdev.c b/ss_outdev.c index a8bcee3..7f6444d 100755 --- a/ss_outdev.c +++ b/ss_outdev.c @@ -29,10 +29,11 @@ #include #include -static void *d_unsupp(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_unsupp(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* unsupported stub function */ { - return NULL; + return NULL; } @@ -45,52 +46,55 @@ static void *d_unsupp(const char *drvname, const char *filename, int freq, int n struct ss_outdrv_arts /* control structure */ { - void (*func) (void *, short int *); - arts_stream_t arts; - int size; + void (*func) (void *, short int *); + arts_stream_t arts; + int size; }; static void d_arts_func(void *d, short int *frame) /* writing / close function */ { - struct ss_outdrv_arts *drv = d; + struct ss_outdrv_arts *drv = d; - if (frame != NULL) - arts_write(drv->arts, frame, drv->size); - else - arts_free(); + if (frame != NULL) + arts_write(drv->arts, frame, drv->size); + else + arts_free(); } -static void *d_arts(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_arts(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_arts drv; + static struct ss_outdrv_arts drv; - if (drvname && strcmp("arts", drvname) != 0) - return NULL; + if (drvname && strcmp("arts", drvname) != 0) + return NULL; - /* filename specified? get out */ - if (filename != NULL) - return NULL; + /* filename specified? get out */ + if (filename != NULL) + return NULL; - *ssize = sizeof(struct ss_outdrv_arts); - drv.func = d_arts_func; - drv.size = n_channels >= 2 ? 2 : 1; + *ssize = sizeof(struct ss_outdrv_arts); + drv.func = d_arts_func; + drv.size = n_channels >= 2 ? 2 : 1; - if (arts_init() || (drv.arts = arts_play_stream(freq, 16, drv.size, "ahxm")) == NULL) - return NULL; + if (arts_init() + || (drv.arts = + arts_play_stream(freq, 16, drv.size, "ahxm")) == NULL) + return NULL; - drv.size *= sizeof(short int); + drv.size *= sizeof(short int); - return &drv; + return &drv; } -#else /* CONFOPT_ARTS */ +#else /* CONFOPT_ARTS */ #define d_arts d_unsupp -#endif /* CONFOPT_ARTS */ +#endif /* CONFOPT_ARTS */ /** ESD driver **/ @@ -103,53 +107,55 @@ static void *d_arts(const char *drvname, const char *filename, int freq, int n_c struct ss_outdrv_esd /* control structure */ { - void (*func) (void *, short int *); - int fd; - int size; + void (*func) (void *, short int *); + int fd; + int size; }; static void d_esd_func(void *d, short int *frame) /* write / close function */ { - struct ss_outdrv_esd *drv = d; + struct ss_outdrv_esd *drv = d; - if (frame != NULL) - write(drv->fd, frame, drv->size); - else - close(drv->fd); + if (frame != NULL) + write(drv->fd, frame, drv->size); + else + close(drv->fd); } -static void *d_esd(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_esd(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_esd drv; - esd_format_t format; + static struct ss_outdrv_esd drv; + esd_format_t format; - if (drvname && strcmp("esd", drvname) != 0) - return NULL; + if (drvname && strcmp("esd", drvname) != 0) + return NULL; - *ssize = sizeof(struct ss_outdrv_esd); - drv.func = d_esd_func; - drv.size = n_channels >= 2 ? 2 : 1; + *ssize = sizeof(struct ss_outdrv_esd); + drv.func = d_esd_func; + drv.size = n_channels >= 2 ? 2 : 1; - format = ESD_STREAM | ESD_PLAY | ESD_BITS16; - format |= drv.size == 2 ? ESD_STEREO : ESD_MONO; + format = ESD_STREAM | ESD_PLAY | ESD_BITS16; + format |= drv.size == 2 ? ESD_STEREO : ESD_MONO; - if (esd_open_sound(filename) < 0 || - (drv.fd = esd_play_stream_fallback(format, freq, NULL, "ahxm")) < 0) - return NULL; + if (esd_open_sound(filename) < 0 || + (drv.fd = + esd_play_stream_fallback(format, freq, NULL, "ahxm")) < 0) + return NULL; - drv.size *= sizeof(short int); + drv.size *= sizeof(short int); - return &drv; + return &drv; } -#else /* CONFOPT_ESD */ +#else /* CONFOPT_ESD */ #define d_esd d_unsupp -#endif /* CONFOPT_ESD */ +#endif /* CONFOPT_ESD */ /** Pulseaudio driver **/ @@ -162,54 +168,56 @@ static void *d_esd(const char *drvname, const char *filename, int freq, int n_ch struct ss_outdrv_pulse /* control structure */ { - void (*func) (void *, short int *); - pa_simple * pa; - int size; + void (*func) (void *, short int *); + pa_simple *pa; + int size; }; static void d_pulse_func(void *d, short int *frame) /* write / close function */ { - struct ss_outdrv_pulse *drv = d; - int error; + struct ss_outdrv_pulse *drv = d; + int error; - if (frame != NULL) - pa_simple_write(drv->pa, frame, drv->size, &error); - else { - pa_simple_drain(drv->pa, &error); - pa_simple_free(drv->pa); - } + if (frame != NULL) + pa_simple_write(drv->pa, frame, drv->size, &error); + else { + pa_simple_drain(drv->pa, &error); + pa_simple_free(drv->pa); + } } -static void *d_pulse(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_pulse(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_pulse drv; - pa_sample_spec ss; + static struct ss_outdrv_pulse drv; + pa_sample_spec ss; - if (drvname && strcmp("pulse", drvname) != 0) - return NULL; + if (drvname && strcmp("pulse", drvname) != 0) + return NULL; - ss.format = PA_SAMPLE_S16LE; - ss.rate = freq; - ss.channels = n_channels; + ss.format = PA_SAMPLE_S16LE; + ss.rate = freq; + ss.channels = n_channels; - *ssize = sizeof(struct ss_outdrv_pulse); - drv.func = d_pulse_func; - drv.size = n_channels * sizeof(short int); + *ssize = sizeof(struct ss_outdrv_pulse); + drv.func = d_pulse_func; + drv.size = n_channels * sizeof(short int); - if ((drv.pa = pa_simple_new(filename, "ahxm", PA_STREAM_PLAYBACK, - NULL, "ahxm", &ss, NULL, NULL, NULL)) == NULL) - return NULL; + if ((drv.pa = pa_simple_new(filename, "ahxm", PA_STREAM_PLAYBACK, + NULL, "ahxm", &ss, NULL, NULL, + NULL)) == NULL) + return NULL; - return &drv; + return &drv; } -#else /* CONFOPT_PULSEAUDIO */ +#else /* CONFOPT_PULSEAUDIO */ #define d_pulse d_unsupp -#endif /* CONFOPT_PULSEAUDIO */ +#endif /* CONFOPT_PULSEAUDIO */ /** SGI Irix driver **/ @@ -221,67 +229,68 @@ static void *d_pulse(const char *drvname, const char *filename, int freq, int n_ struct ss_outdrv_sgi /* control structure */ { - void (*func) (void *, short int *); - ALconfig ac; - ALport ap; + void (*func) (void *, short int *); + ALconfig ac; + ALport ap; }; static void d_sgi_func(void *d, short int *frame) /* write / close function */ { - struct ss_outdrv_sgi *drv = d; + struct ss_outdrv_sgi *drv = d; - if (frame != NULL) - alWriteFrames(drv->ap, frame, 1); - else { - alClosePort(drv->ap); - alFreeConfig(drv->ac); - } + if (frame != NULL) + alWriteFrames(drv->ap, frame, 1); + else { + alClosePort(drv->ap); + alFreeConfig(drv->ac); + } } -static void *d_sgi(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_sgi(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_sgi drv; - ALpv p[2]; + static struct ss_outdrv_sgi drv; + ALpv p[2]; - if (drvname && strcmp("sgi", drvname) != 0) - return NULL; + if (drvname && strcmp("sgi", drvname) != 0) + return NULL; - /* filename specified? get out */ - if (filename != NULL) - return NULL; + /* filename specified? get out */ + if (filename != NULL) + return NULL; - *ssize = sizeof(struct ss_outdrv_sgi); - drv.func = d_sgi_func; + *ssize = sizeof(struct ss_outdrv_sgi); + drv.func = d_sgi_func; - p[0].param = AL_MASTER_CLOCK; - p[0].value.i = AL_CRYSTAL_MCLK_TYPE; - p[1].param = AL_RATE; - p[1].value.ll = alDoubleToFixed((double) freq); + p[0].param = AL_MASTER_CLOCK; + p[0].value.i = AL_CRYSTAL_MCLK_TYPE; + p[1].param = AL_RATE; + p[1].value.ll = alDoubleToFixed((double) freq); - if (!(drv.ac = alNewConfig())) - return NULL; + if (!(drv.ac = alNewConfig())) + return NULL; - if (alSetChannels(drv.ac, n_channels) < 0 || - alSetWidth(drv.ac, AL_SAMPLE_16) < 0 || - alSetSampFmt(drv.ac, AL_SAMPFMT_TWOSCOMP) < 0 || - alSetQueueSize(drv.ac, 2048) < 0 || - alSetDevice(drv.ac, AL_DEFAULT_OUTPUT) < 0 || - alSetParams(alGetDevice(drv.ac), p, 2) < 0 || - !(drv.ap = alOpenPort("ahxm", "w", drv.ac))) { - alFreeConfig(drv.ac); - return NULL; - } + if (alSetChannels(drv.ac, n_channels) < 0 || + alSetWidth(drv.ac, AL_SAMPLE_16) < 0 || + alSetSampFmt(drv.ac, AL_SAMPFMT_TWOSCOMP) < 0 || + alSetQueueSize(drv.ac, 2048) < 0 || + alSetDevice(drv.ac, AL_DEFAULT_OUTPUT) < 0 || + alSetParams(alGetDevice(drv.ac), p, 2) < 0 || + !(drv.ap = alOpenPort("ahxm", "w", drv.ac))) { + alFreeConfig(drv.ac); + return NULL; + } - return &drv; + return &drv; } -#else /* CONFOPT_SGI */ +#else /* CONFOPT_SGI */ #define d_sgi d_unsupp -#endif /* CONFOPT_SGI */ +#endif /* CONFOPT_SGI */ /** Linux OSS driver **/ @@ -296,74 +305,75 @@ static void *d_sgi(const char *drvname, const char *filename, int freq, int n_ch struct ss_outdrv_oss /* control structure */ { - void (*func) (void *, short int *); - int fd; - int size; + void (*func) (void *, short int *); + int fd; + int size; }; static int is_little_endian(void) /* is this machine little endian? */ { - short s = 1; - unsigned char *c = (unsigned char *) &s; + short s = 1; + unsigned char *c = (unsigned char *) &s; - return *c == 1; + return *c == 1; } static void d_oss_func(void *d, short int *frame) /* write / close function */ { - struct ss_outdrv_oss *drv = d; + struct ss_outdrv_oss *drv = d; - if (frame != NULL) - write(drv->fd, frame, drv->size); - else - close(drv->fd); + if (frame != NULL) + write(drv->fd, frame, drv->size); + else + close(drv->fd); } -static void *d_oss(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_oss(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_oss drv; - int fr, st, fm; + static struct ss_outdrv_oss drv; + int fr, st, fm; - if (drvname && strcmp("oss", drvname) != 0) - return NULL; + if (drvname && strcmp("oss", drvname) != 0) + return NULL; - if (filename == NULL) - filename = "/dev/dsp"; + if (filename == NULL) + filename = "/dev/dsp"; - fr = (2 << 16) | 12; - st = n_channels >= 2 ? 1 : 0; - fm = is_little_endian()? AFMT_S16_LE : AFMT_S16_BE; + fr = (2 << 16) | 12; + st = n_channels >= 2 ? 1 : 0; + fm = is_little_endian()? AFMT_S16_LE : AFMT_S16_BE; - *ssize = sizeof(struct ss_outdrv_oss); - drv.func = d_oss_func; - drv.size = n_channels >= 2 ? 2 : 1; + *ssize = sizeof(struct ss_outdrv_oss); + drv.func = d_oss_func; + drv.size = n_channels >= 2 ? 2 : 1; - if ((drv.fd = open(filename, O_WRONLY)) < 0) - return NULL; + if ((drv.fd = open(filename, O_WRONLY)) < 0) + return NULL; - if (ioctl(drv.fd, SNDCTL_DSP_SETFRAGMENT, &fr) < 0 || - ioctl(drv.fd, SNDCTL_DSP_RESET, 0) < 0 || - ioctl(drv.fd, SNDCTL_DSP_SPEED, &freq) < 0 || - ioctl(drv.fd, SNDCTL_DSP_STEREO, &st) < 0 || - ioctl(drv.fd, SNDCTL_DSP_SETFMT, &fm) < 0) { - close(drv.fd); - return NULL; - } + if (ioctl(drv.fd, SNDCTL_DSP_SETFRAGMENT, &fr) < 0 || + ioctl(drv.fd, SNDCTL_DSP_RESET, 0) < 0 || + ioctl(drv.fd, SNDCTL_DSP_SPEED, &freq) < 0 || + ioctl(drv.fd, SNDCTL_DSP_STEREO, &st) < 0 || + ioctl(drv.fd, SNDCTL_DSP_SETFMT, &fm) < 0) { + close(drv.fd); + return NULL; + } - drv.size *= sizeof(short int); + drv.size *= sizeof(short int); - return &drv; + return &drv; } -#else /* CONFOPT_LINUX_OSS */ +#else /* CONFOPT_LINUX_OSS */ #define d_oss d_unsupp -#endif /* CONFOPT_LINUX_OSS */ +#endif /* CONFOPT_LINUX_OSS */ /** WAV file driver **/ @@ -371,89 +381,90 @@ static void *d_oss(const char *drvname, const char *filename, int freq, int n_ch struct ss_outdrv_wav /* control structure */ { - void (*func) (void *, short int *); - FILE *fd; - int size; - int n_frames; + void (*func) (void *, short int *); + FILE *fd; + int size; + int n_frames; }; static void fput16(short int i, FILE * f) /* writes a 16 bit integer, in any machine order */ { - fputc(i & 0x00ff, f); - fputc((i & 0xff00) >> 8, f); + fputc(i & 0x00ff, f); + fputc((i & 0xff00) >> 8, f); } static void fput32(int i, FILE * f) /* writes a 32 bit integer, in any machine order */ { - fputc(i & 0x000000ff, f); - fputc((i & 0x0000ff00) >> 8, f); - fputc((i & 0x00ff0000) >> 16, f); - fputc((i & 0xff000000) >> 24, f); + fputc(i & 0x000000ff, f); + fputc((i & 0x0000ff00) >> 8, f); + fputc((i & 0x00ff0000) >> 16, f); + fputc((i & 0xff000000) >> 24, f); } static void d_wav_func(void *d, short int *frame) /* write / close function */ { - struct ss_outdrv_wav *drv = d; + struct ss_outdrv_wav *drv = d; - if (frame != NULL) { - int n; + if (frame != NULL) { + int n; - for (n = 0; n < drv->size; n++) - fput16(frame[n], drv->fd); + for (n = 0; n < drv->size; n++) + fput16(frame[n], drv->fd); - drv->n_frames++; - } - else { - /* rewind file and write total size */ - fseek(drv->fd, 4, SEEK_SET); - fput32((drv->n_frames * drv->size * 2) + 36, drv->fd); + drv->n_frames++; + } + else { + /* rewind file and write total size */ + fseek(drv->fd, 4, SEEK_SET); + fput32((drv->n_frames * drv->size * 2) + 36, drv->fd); - fseek(drv->fd, 40, SEEK_SET); - fput32((drv->n_frames * drv->size * 2), drv->fd); + fseek(drv->fd, 40, SEEK_SET); + fput32((drv->n_frames * drv->size * 2), drv->fd); - fclose(drv->fd); - } + fclose(drv->fd); + } } -static void *d_wav(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_wav(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) /* init function */ { - static struct ss_outdrv_wav drv; - - if (drvname && strcmp("wav", drvname) != 0) - return NULL; - - if (filename == NULL) - filename = "output.wav"; + static struct ss_outdrv_wav drv; - *ssize = sizeof(struct ss_outdrv_wav); - drv.func = d_wav_func; - drv.size = n_channels; - drv.n_frames = 0; - - if ((drv.fd = fopen(filename, "wb")) == NULL) - return 0; - - /* write wav header */ + if (drvname && strcmp("wav", drvname) != 0) + return NULL; - fwrite("RIFF", 1, 4, drv.fd); - fput32(36, drv.fd); /* first checkpoint (offset: 4) */ - fwrite("WAVE", 1, 4, drv.fd); - fwrite("fmt ", 1, 4, drv.fd); - fput32(16, drv.fd); /* chunk size */ - fput16(1, drv.fd); /* 1: uncompressed PCM */ - fput16(n_channels, drv.fd); /* # of channels */ - fput32(freq, drv.fd); /* sample rate */ - fput32(freq * n_channels * 2, drv.fd); /* bytes per second */ - fput16(n_channels * 2, drv.fd); /* 'block align' */ - fput16(16, drv.fd); /* 16 bits per sample */ - fwrite("data", 1, 4, drv.fd); - fput32(0, drv.fd); /* second checkpoint (offset: 40) */ + if (filename == NULL) + filename = "output.wav"; + + *ssize = sizeof(struct ss_outdrv_wav); + drv.func = d_wav_func; + drv.size = n_channels; + drv.n_frames = 0; + + if ((drv.fd = fopen(filename, "wb")) == NULL) + return 0; + + /* write wav header */ + + fwrite("RIFF", 1, 4, drv.fd); + fput32(36, drv.fd); /* first checkpoint (offset: 4) */ + fwrite("WAVE", 1, 4, drv.fd); + fwrite("fmt ", 1, 4, drv.fd); + fput32(16, drv.fd); /* chunk size */ + fput16(1, drv.fd); /* 1: uncompressed PCM */ + fput16(n_channels, drv.fd); /* # of channels */ + fput32(freq, drv.fd); /* sample rate */ + fput32(freq * n_channels * 2, drv.fd); /* bytes per second */ + fput16(n_channels * 2, drv.fd); /* 'block align' */ + fput16(16, drv.fd); /* 16 bits per sample */ + fwrite("data", 1, 4, drv.fd); + fput32(0, drv.fd); /* second checkpoint (offset: 40) */ - return &drv; + return &drv; } @@ -479,77 +490,77 @@ static short int *frame_cpy = NULL; static void *outdev_thread(void *driver) /* pthread 'consumer' function */ { - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutex); - for (;;) { - /* wait for data available */ - pthread_cond_wait(&cond, &mutex); + for (;;) { + /* wait for data available */ + pthread_cond_wait(&cond, &mutex); - /* call the real function */ - real_drv_func(driver, frame_cpy); + /* call the real function */ + real_drv_func(driver, frame_cpy); - /* no more? */ - if (frame_cpy == NULL) - break; - } + /* no more? */ + if (frame_cpy == NULL) + break; + } - pthread_mutex_unlock(&mutex); - return NULL; + pthread_mutex_unlock(&mutex); + return NULL; } static void outdev_producer_wrapper(void *d, short int *frame) /* wrapper 'producer' function */ { - int n; + int n; - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutex); - if (frame == NULL) { - /* close */ - free(frame_cpy); - frame_cpy = NULL; - frame_cpy_n = 0; - } - else { - /* copy the frame */ - for (n = 0; n < frame_cpy_n; n++) - frame_cpy[n] = frame[n]; - } + if (frame == NULL) { + /* close */ + free(frame_cpy); + frame_cpy = NULL; + frame_cpy_n = 0; + } + else { + /* copy the frame */ + for (n = 0; n < frame_cpy_n; n++) + frame_cpy[n] = frame[n]; + } - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); } static void thread_setup(void *d, int n_channels) { - void (**drv) (void *, short int *) = d; + void (**drv) (void *, short int *) = d; - /* create the buffer */ - frame_cpy_n = n_channels; - frame_cpy = malloc(frame_cpy_n * sizeof(short int)); + /* create the buffer */ + frame_cpy_n = n_channels; + frame_cpy = malloc(frame_cpy_n * sizeof(short int)); - pthread_mutex_init(&mutex, NULL); - pthread_cond_init(&cond, NULL); + pthread_mutex_init(&mutex, NULL); + pthread_cond_init(&cond, NULL); - /* 'patch' the driver */ - real_drv_func = *drv; - *drv = outdev_producer_wrapper; + /* 'patch' the driver */ + real_drv_func = *drv; + *drv = outdev_producer_wrapper; - /* launch the thread */ - pthread_create(&consumer, NULL, outdev_thread, d); + /* launch the thread */ + pthread_create(&consumer, NULL, outdev_thread, d); } -#else /* CONFOPT_PTHREADS */ +#else /* CONFOPT_PTHREADS */ void thread_setup(void *d, int n) { - /* do nothing */ + /* do nothing */ } -#endif /* CONFOPT_PTHREADS */ +#endif /* CONFOPT_PTHREADS */ /** win32 waveout support **/ @@ -580,7 +591,7 @@ struct ss_outdrv_win32 static void d_win32_func(void *d, short int *frame) { - struct ss_outdrv_win32 *drv = d; + struct ss_outdrv_win32 *drv = d; struct _wob *b = &drv->wob[drv->wob_i]; int w = 1; @@ -597,11 +608,12 @@ static void d_win32_func(void *d, short int *frame) if (w) { /* clean previous buffer, if needed */ if (b->header.lpData) - waveOutUnprepareHeader(drv->hwaveout, &b->header, sizeof(WAVEHDR)); + waveOutUnprepareHeader(drv->hwaveout, &b->header, + sizeof(WAVEHDR)); /* prepare new buffer */ - b->header.dwBufferLength = b->offset; - b->header.lpData = (LPSTR) b->buf; + b->header.dwBufferLength = b->offset; + b->header.lpData = (LPSTR) b->buf; /* send it */ waveOutPrepareHeader(drv->hwaveout, &b->header, sizeof(WAVEHDR)); @@ -619,90 +631,93 @@ static void d_win32_func(void *d, short int *frame) } /* wait until buffer is done */ - while (b->header.lpData != NULL && !(b->header.dwFlags & WHDR_DONE)) + while (b->header.lpData != NULL + && !(b->header.dwFlags & WHDR_DONE)) Sleep(1); } } -static void *d_win32(const char *drvname, const char *filename, int freq, int n_channels, int *ssize) +static void *d_win32(const char *drvname, const char *filename, int freq, + int n_channels, int *ssize) { static struct ss_outdrv_win32 drv; WAVEFORMATEX wfx; - if (drvname && strcmp("win32", drvname) != 0) - return NULL; + if (drvname && strcmp("win32", drvname) != 0) + return NULL; memset(&drv, '\0', sizeof(drv)); - wfx.nSamplesPerSec = freq; - wfx.wBitsPerSample = 16; - wfx.nChannels = n_channels; - wfx.cbSize = 0; - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; + wfx.nSamplesPerSec = freq; + wfx.wBitsPerSample = 16; + wfx.nChannels = n_channels; + wfx.cbSize = 0; + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; if (waveOutOpen(&drv.hwaveout, WAVE_MAPPER, - &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) + &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) return NULL; - drv.func = d_win32_func; - drv.size = n_channels * sizeof(short int); - drv.wob_i = 0; + drv.func = d_win32_func; + drv.size = n_channels * sizeof(short int); + drv.wob_i = 0; - *ssize = sizeof(struct ss_outdrv_win32); + *ssize = sizeof(struct ss_outdrv_win32); return &drv; } -#else /* CONFOPT_WIN32 */ +#else /* CONFOPT_WIN32 */ #define d_win32 d_unsupp -#endif /* CONFOPT_WIN32 */ +#endif /* CONFOPT_WIN32 */ /** Interface **/ -void *ss_outdev_open(const char *drvname, const char *file, int freq, int n_channels) +void *ss_outdev_open(const char *drvname, const char *file, int freq, + int n_channels) { - int size; - void *drv; - void *ret = NULL; - - if ((drv = d_arts(drvname, file, freq, n_channels, &size)) != NULL || - (drv = d_esd(drvname, file, freq, n_channels, &size)) != NULL || - (drv = d_pulse(drvname, file, freq, n_channels, &size)) != NULL || - (drv = d_sgi(drvname, file, freq, n_channels, &size)) != NULL || - (drv = d_oss(drvname, file, freq, n_channels, &size)) != NULL || + int size; + void *drv; + void *ret = NULL; + + if ((drv = d_arts(drvname, file, freq, n_channels, &size)) != NULL || + (drv = d_esd(drvname, file, freq, n_channels, &size)) != NULL || + (drv = d_pulse(drvname, file, freq, n_channels, &size)) != NULL || + (drv = d_sgi(drvname, file, freq, n_channels, &size)) != NULL || + (drv = d_oss(drvname, file, freq, n_channels, &size)) != NULL || (drv = d_win32(drvname, file, freq, n_channels, &size)) != NULL || - (drv = d_wav(drvname, file, freq, n_channels, &size)) != NULL) { - ret = malloc(size); - memcpy(ret, drv, size); - } + (drv = d_wav(drvname, file, freq, n_channels, &size)) != NULL) { + ret = malloc(size); + memcpy(ret, drv, size); + } - thread_setup(ret, n_channels); + thread_setup(ret, n_channels); - return ret; + return ret; } void ss_outdev_write(void *drv, short int *frame) { - void (**func) (void *, short int *) = drv; + void (**func) (void *, short int *) = drv; - (*func) (drv, frame); + (*func) (drv, frame); } void *ss_outdev_close(void *drv) { - if (drv != NULL) { - ss_outdev_write(drv, NULL); - free(drv); - } + if (drv != NULL) { + ss_outdev_write(drv, NULL); + free(drv); + } - return NULL; + return NULL; } diff --git a/ss_output.c b/ss_output.c index 231acf8..fd7a44c 100644 --- a/ss_output.c +++ b/ss_output.c @@ -35,9 +35,8 @@ #include "ahxm.h" -/******************* - Data -********************/ + +/** data **/ /* master output volume */ sample_t ss_master_volume = 0.5; @@ -75,11 +74,11 @@ static const char *ss_output_file_name = NULL; const char *ss_cue_file_name = NULL; static int ss_cue_file_track = -1; -/******************* - Code -********************/ -void *ss_outdev_open(const char *drvname, const char *file, int freq, int n_channels); +/** code **/ + +void *ss_outdev_open(const char *drvname, const char *file, int freq, + int n_channels); void ss_outdev_write(void *drv, short int *frame); void *ss_outdev_close(void *drv); @@ -87,11 +86,11 @@ void *ss_outdev_close(void *drv); static void close_on_signal(int sig_num) /* SIGINT (and other) signal handler */ { - /* close output device */ - outdev = ss_outdev_close(outdev); + /* close output device */ + outdev = ss_outdev_close(outdev); - /* exit */ - exit(0); + /* exit */ + exit(0); } @@ -115,21 +114,22 @@ static void close_on_signal(int sig_num) */ int ss_output_open(const char *drvname, const char *filename) { - if (strcmp(drvname, "default") == 0) - drvname = NULL; + if (strcmp(drvname, "default") == 0) + drvname = NULL; - /* reset accounting */ - ss_output_clipped = 0; - ss_max = 0.0; + /* reset accounting */ + ss_output_clipped = 0; + ss_max = 0.0; - /* close the device on unexpected signals */ - signal(SIGINT, close_on_signal); + /* close the device on unexpected signals */ + signal(SIGINT, close_on_signal); - /* store a copy of the filename */ - ss_output_file_name = filename; + /* store a copy of the filename */ + ss_output_file_name = filename; - return (outdev = ss_outdev_open(drvname, - filename, ss_frequency, ss_nchannels)) == NULL; + return (outdev = ss_outdev_open(drvname, + filename, ss_frequency, + ss_nchannels)) == NULL; } @@ -141,7 +141,7 @@ int ss_output_open(const char *drvname, const char *filename) */ void ss_output_init_frame(sample_t frame[]) { - memset(frame, '\0', sizeof(sample_t) * SS_MAX_CHANNELS); + memset(frame, '\0', sizeof(sample_t) * SS_MAX_CHANNELS); } @@ -156,46 +156,46 @@ void ss_output_init_frame(sample_t frame[]) */ int ss_output_write(sample_t frame[]) { - int n, ret = 0; - sample_t s; - short int is[SS_MAX_CHANNELS]; - - /* final corrections */ - for (n = 0; n < ss_nchannels; n++) { - s = frame[n]; - - /* test maximum amplitudes, apply master - volume and clipping */ - if (s < 0) { - if (s < -ss_max) - ss_max = -s; - s *= ss_master_volume; - if (s < -1) { - s = -1; - ss_output_clipped++; - } - } - else { - if (s > ss_max) - ss_max = s; - s *= ss_master_volume; - if (s > 1) { - s = 1; - ss_output_clipped++; - } - } - - /* convert to 16 bit signed */ - s *= 32767.0; - - /* store in buffer */ - is[n] = (short int) s; - } - - /* finally write */ - ss_outdev_write(outdev, is); - - return ret; + int n, ret = 0; + sample_t s; + short int is[SS_MAX_CHANNELS]; + + /* final corrections */ + for (n = 0; n < ss_nchannels; n++) { + s = frame[n]; + + /* test maximum amplitudes, apply master + volume and clipping */ + if (s < 0) { + if (s < -ss_max) + ss_max = -s; + s *= ss_master_volume; + if (s < -1) { + s = -1; + ss_output_clipped++; + } + } + else { + if (s > ss_max) + ss_max = s; + s *= ss_master_volume; + if (s > 1) { + s = 1; + ss_output_clipped++; + } + } + + /* convert to 16 bit signed */ + s *= 32767.0; + + /* store in buffer */ + is[n] = (short int) s; + } + + /* finally write */ + ss_outdev_write(outdev, is); + + return ret; } @@ -206,64 +206,65 @@ int ss_output_write(sample_t frame[]) */ void ss_output_close(void) { - /* back to default signal behaviour */ - signal(SIGINT, SIG_DFL); + /* back to default signal behaviour */ + signal(SIGINT, SIG_DFL); - /* close the device */ - outdev = ss_outdev_close(outdev); + /* close the device */ + outdev = ss_outdev_close(outdev); - /* calculate optimal master volume for zero saturation */ - if (ss_max) - ss_optimal_volume = 1 / ss_max; + /* calculate optimal master volume for zero saturation */ + if (ss_max) + ss_optimal_volume = 1 / ss_max; } static int cue_file_init(void) /* inits the cue file, writing the first line */ { - FILE *f; + FILE *f; - if (ss_output_file_name == NULL || (f = fopen(ss_cue_file_name, "wb")) == NULL) - return -2; + if (ss_output_file_name == NULL + || (f = fopen(ss_cue_file_name, "wb")) == NULL) + return -2; - /* write first line */ - fprintf(f, "FILE \"%s\" WAVE\n", ss_output_file_name); - fclose(f); + /* write first line */ + fprintf(f, "FILE \"%s\" WAVE\n", ss_output_file_name); + fclose(f); - ss_cue_file_track = 0; + ss_cue_file_track = 0; - return 0; + return 0; } int cue_file_song_info(int frame, const char *author, const char *name) { - int s; - FILE *f; - - if (ss_cue_file_name == NULL) - return 0; - - /* init if it's the first time */ - if (ss_cue_file_track == -1) { - /* can't open? fail */ - if (cue_file_init() < 0) { - ss_cue_file_name = NULL; - return -1; - } - } - - /* open or fail */ - if ((f = fopen(ss_cue_file_name, "a")) == NULL) - return -1; - - s = frame / ss_frequency; - - fprintf(f, "TRACK %02d AUDIO\n", ss_cue_file_track++); - fprintf(f, " PERFORMER \"%s\"\n", author); - fprintf(f, " TITLE \"%s\"\n", name); - fprintf(f, " INDEX 01 %02d:%02d:00\n", s / 60, s % 60); - - fclose(f); - return 0; + int s; + FILE *f; + + if (ss_cue_file_name == NULL) + return 0; + + /* init if it's the first time */ + if (ss_cue_file_track == -1) { + /* can't open? fail */ + if (cue_file_init() < 0) { + ss_cue_file_name = NULL; + return -1; + } + } + + /* open or fail */ + if ((f = fopen(ss_cue_file_name, "a")) == NULL) + return -1; + + s = frame / ss_frequency; + + fprintf(f, "TRACK %02d AUDIO\n", ss_cue_file_track++); + fprintf(f, " PERFORMER \"%s\"\n", author); + fprintf(f, " TITLE \"%s\"\n", name); + fprintf(f, " INDEX 01 %02d:%02d:00\n", s / 60, s % 60); + + fclose(f); + return 0; } diff --git a/ss_song.c b/ss_song.c dissimilarity index 84% index 745b4d0..c6272bd 100644 --- a/ss_song.c +++ b/ss_song.c @@ -1,609 +1,610 @@ -/* - - Ann Hell Ex Machina - Music Software - Copyright (C) 2003/2008 Angel Ortega - - ss_song.c - Software synth song event stream management - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.triptico.com - -*/ - -#include "config.h" - -#include -#include -#include -#include - -#include "ahxm.h" - -/******************* - Data -********************/ - -/* the softsynth song stream */ - -static struct song_ev *ss_song = NULL; -static int n_ss_ev = 0; - -/* the instruments */ - -struct ss_ins ss_song_ins[SS_MAX_INSTRUMENTS]; - -/******************* - Code -********************/ - -static struct song_ev * add_ss_ev(const struct song_ev *e) -/* adds a softsynth song event */ -{ - return copy_event(&ss_song, &n_ss_ev, e); -} - - -static int frame_type_eventid_cmp(const void *v1, const void *v2) -/* softsynth song event compare function for qsort() */ -{ - struct song_ev *e1; - struct song_ev *e2; - int ret; - - e1 = (struct song_ev *) v1; - e2 = (struct song_ev *) v2; - - ret = e1->frame - e2->frame; - - if (ret == 0) - ret = e1->type - e2->type; - - if (ret == 0) - ret = e1->event_id - e2->event_id; - - return ret; -} - - -static void ss_song_convert_events(int *n_channels) -/* converts generic song_ev events to softsynth events */ -{ - int note_id = 1; - struct song_ev *e; - int frame, frame_ac, f_frame; - double fpw, time_ac, time_ac_m; - int num, den; - int n; - - *n_channels = -1; - - /* resets the ss stream */ - if (ss_song != NULL) { - free(ss_song); - ss_song = NULL; - } - - n_ss_ev = 0; - - /* sorts the song */ - song_sort(); - - fpw = 0; - frame = frame_ac = f_frame = 0; - time_ac = time_ac_m = 0; - num = den = 4; - - /* travels the song events generating softsynth song events */ - for (n = 0; n < n_song_ev; n++) { - /* gets the song event */ - e = &song[n]; - - /* calculates the frame */ - frame = ((e->time - time_ac) * fpw) + frame_ac; - e->frame = frame; - - switch (e->type) { - case SONG_EV_TEMPO: - - /* updates accumulations */ - frame_ac = frame; - time_ac = e->time; - - /* calculates frames-per-whole based on new tempo */ - fpw = (double) ss_frequency * 60.0; - fpw /= e->amount / 4.0; - - add_ss_ev(e); - - break; - - case SONG_EV_METER: - - /* just store the values */ - num = e->min; - den = e->max; - time_ac_m = e->time; - - break; - - case SONG_EV_MEASURE: - - song_test_measure_boundary(e->time - time_ac_m, - num, den, e->value); - break; - - case SONG_EV_NOTE: - - /* assign a note id */ - e->note_id = note_id++; - - /* copy */ - add_ss_ev(e); - - /* copy again, but set as NOTE_OFF */ - e = add_ss_ev(e); - e->type = SONG_EV_NOTE_OFF; - - frame += (int) (e->len * fpw); - e->frame = frame; - - break; - - case SONG_EV_BACK: - - /* move the cursor back */ - - frame_ac -= (int) (e->len * fpw); - - break; - - case SONG_EV_SS_PITCH_STRETCH: - - /* assign a note id */ - e->note_id = note_id++; - - /* copy */ - add_ss_ev(e); - - /* and copy again, as a note off */ - e = add_ss_ev(e); - e->type = SONG_EV_NOTE_OFF; - - frame += (int) (e->len * fpw); - e->frame = frame; - - break; - - case SONG_EV_SS_PRINT_WAVE_TEMPO: - case SONG_EV_SS_WAV: - case SONG_EV_SS_PAT: - case SONG_EV_SS_SF2: - case SONG_EV_SS_SUSTAIN: - case SONG_EV_SS_ATTACK: - case SONG_EV_SS_VIBRATO: - case SONG_EV_SS_PORTAMENTO: - case SONG_EV_SS_EFF_DELAY: - case SONG_EV_SS_EFF_ECHO: - case SONG_EV_SS_EFF_COMB: - case SONG_EV_SS_EFF_ALLPASS: - case SONG_EV_SS_EFF_FLANGER: - case SONG_EV_SS_EFF_WOBBLE: - case SONG_EV_SS_EFF_SQWOBBLE: - case SONG_EV_SS_EFF_HFWOBBLE: - case SONG_EV_SS_EFF_FADER: - case SONG_EV_SS_EFF_REVERB: - case SONG_EV_SS_EFF_FOLDBACK: - case SONG_EV_SS_EFF_ATAN: - case SONG_EV_SS_EFF_DISTORT: - case SONG_EV_SS_EFF_OVERDRIVE: - case SONG_EV_SS_EFF_OFF: - case SONG_EV_SS_MASTER_VOLUME: - case SONG_EV_SONG_INFO: - case SONG_EV_EOT: - - /* just copy */ - add_ss_ev(e); - break; - - case SONG_EV_SS_CHANNEL: - - /* count channels */ - if (*n_channels < e->channel) - *n_channels = e->channel; - - add_ss_ev(e); - break; - - case SONG_EV_NOP: - case SONG_EV_MIDI_CHANNEL: - case SONG_EV_MIDI_PROGRAM: - - /* ignored */ - break; - - case SONG_EV_NOTE_OFF: - case SONG_EV_END: - - /* never found in generic song streams */ - break; - } - - /* store the further frame seen */ - if (f_frame < frame) - f_frame = frame; - } - - /* generates an end of event mark, a time after the last one */ - e = add_event(&ss_song, &n_ss_ev); - - e->type = SONG_EV_END; - e->frame = f_frame + ss_frequency; - e->event_id = -1; - - /* finally sort */ - qsort(ss_song, n_ss_ev, sizeof(struct song_ev), frame_type_eventid_cmp); - - /* count one more */ - (*n_channels)++; -} - - -static const struct song_ev *process_this_frame_events(const struct song_ev *e, int skip_frames) -/* process the events attached to this frame */ -{ - static double tempo = 120.0; - static int frame = 0; - - /* from the beginning? */ - if (e == NULL) { - e = ss_song; - tempo = 120.0; - frame = 0; - } - - if (verbose >= 1 && frame % ss_frequency == 0) { - int m = frame / ss_frequency; - printf("[%02d:%02d]\r", m / 60, m % 60); - fflush(stdout); - } - - while (e != NULL && e->frame == frame) { - struct ss_ins *i; - struct ss_wave *w; - double freq; - - if (e->type == SONG_EV_NOTE || - e->type == SONG_EV_NOTE_OFF || - e->type == SONG_EV_SS_PITCH_STRETCH) { - if (frame < skip_frames) { - e++; - frame = e->frame; - continue; - } - } - - /* take the instrument */ - if (e->trk_id < 0) - i = NULL; - else - i = &ss_song_ins[e->trk_id]; - - switch (e->type) { - case SONG_EV_NOTE: - - if (ss_ins_note_on(i, e->value, e->vol, e->note_id) < 0 && - verbose >= 1) - printf("ss_ins_note_on error: track %d note %d\n", - e->trk_id, e->value); - - break; - - case SONG_EV_NOTE_OFF: - - ss_ins_note_off(i, e->note_id); - - break; - - case SONG_EV_SS_SUSTAIN: - - ss_ins_set_sustain(i, e->amount); - - break; - - case SONG_EV_SS_ATTACK: - - ss_ins_set_attack(i, e->amount); - - break; - - case SONG_EV_SS_VIBRATO: - - ss_ins_set_vibrato(i, e->depth, e->freq); - - break; - - case SONG_EV_SS_PORTAMENTO: - - ss_ins_set_portamento(i, (e->amount * 44100.0) - / ((double) ss_frequency * 1000000.0)); - - break; - - case SONG_EV_SS_CHANNEL: - - ss_ins_set_channel(i, e->channel, e->vol); - - break; - - case SONG_EV_SS_WAV: - - w = ss_load_wav_file(e->name, - ss_note_frequency(e->value), - ss_note_frequency(e->min), - ss_note_frequency(e->max), - e->start, e->end, - e->channel, e->skip_channels); - - /* fail if can't open wav */ - if (w == NULL) { - printf("Can't load wav '%s'\n", e->name); - e = NULL; - } - else - ss_ins_add_layer(i, w); - - break; - - case SONG_EV_SS_PAT: - - if (ss_load_pat_file(i, e->name) < 0) { - printf("Can't load pat '%s'\n", e->name); - e = NULL; - } - - break; - - case SONG_EV_SS_SF2: - - if (ss_load_sf2_file(i, e->name, e->str2) < 0) { - printf("Can't load instrument from sf2 '%s'\n", e->name); - e = NULL; - } - - break; - - case SONG_EV_SS_EFF_DELAY: - - ss_eff_delay(&i->effs[e->channel], e->len); - break; - - case SONG_EV_SS_EFF_ECHO: - - ss_eff_echo(&i->effs[e->channel], e->len, e->vol); - break; - - case SONG_EV_SS_EFF_COMB: - - ss_eff_comb(&i->effs[e->channel], e->len, e->vol); - break; - - case SONG_EV_SS_EFF_ALLPASS: - - ss_eff_allpass(&i->effs[e->channel], e->len, e->vol); - break; - - case SONG_EV_SS_EFF_FLANGER: - - ss_eff_flanger(&i->effs[e->channel], - e->len, e->vol, e->depth, e->freq, e->phase); - break; - - case SONG_EV_SS_EFF_WOBBLE: - - ss_eff_wobble(&i->effs[e->channel], e->freq, e->phase, e->vol); - - break; - - case SONG_EV_SS_EFF_SQWOBBLE: - - ss_eff_square_wobble(&i->effs[e->channel], e->freq, e->phase); - - break; - - case SONG_EV_SS_EFF_HFWOBBLE: - - ss_eff_half_wobble(&i->effs[e->channel], e->freq, e->phase); - - break; - - case SONG_EV_SS_EFF_FADER: - - ss_eff_fader(&i->effs[e->channel], e->len, e->initial, e->final); - break; - - case SONG_EV_SS_EFF_REVERB: - - ss_eff_reverb(&i->effs[e->channel]); - break; - - case SONG_EV_SS_EFF_FOLDBACK: - - ss_eff_foldback(&i->effs[e->channel], e->vol); - break; - - case SONG_EV_SS_EFF_ATAN: - - ss_eff_atan(&i->effs[e->channel], e->vol); - break; - - case SONG_EV_SS_EFF_DISTORT: - - ss_eff_distort(&i->effs[e->channel], e->vol); - break; - - case SONG_EV_SS_EFF_OVERDRIVE: - - ss_eff_overdrive(&i->effs[e->channel], e->vol); - break; - - case SONG_EV_SS_EFF_OFF: - - ss_eff_off(&i->effs[e->channel]); - break; - - case SONG_EV_TEMPO: - - /* just store the last tempo */ - tempo = e->amount; - break; - - case SONG_EV_SS_PITCH_STRETCH: - - /* find the wave */ - freq = ss_note_frequency(e->value); - w = ss_ins_find_layer(i, freq, NULL); - - /* calculate optimal frequency */ - freq = ss_pitch_from_tempo(w, tempo, e->len); - - /* play the note */ - if (ss_ins_play(i, freq, e->vol, - e->note_id, w) < 0 && verbose >= 1) - printf("ss_ins_play error: track %d freq %f\n", - e->trk_id, freq); - - break; - - case SONG_EV_SS_PRINT_WAVE_TEMPO: - - /* find the wave */ - freq = ss_note_frequency(e->value); - w = ss_ins_find_layer(i, freq, NULL); - - /* print the optimal tempo */ - printf("Optimal tempo: %lf\n", - ss_tempo_from_wave(w, e->value, e->len)); - - break; - - case SONG_EV_SS_MASTER_VOLUME: - - /* set master volume */ - ss_master_volume = e->vol; - break; - - case SONG_EV_SONG_INFO: - - /* add a new song (track) */ - cue_file_song_info(frame, e->str2, e->name); - break; - - case SONG_EV_EOT: - - /* end of track; trigger possible cleaning */ - ss_ins_disable(i); - break; - - case SONG_EV_END: - - e = NULL; - break; - - case SONG_EV_BACK: - case SONG_EV_MIDI_CHANNEL: - case SONG_EV_MIDI_PROGRAM: - case SONG_EV_METER: - case SONG_EV_MEASURE: - case SONG_EV_NOP: - - /* never found in ss song streams */ - break; - } - - /* next event */ - if (e) - e++; - } - - frame++; - - return e; -} - - -int ss_song_render(int skip_secs, const char *driver, const char *devfile) -{ - int n, i = 0; - sample_t output[SS_MAX_CHANNELS]; - int skip_frames; - int n_channels; - const struct song_ev *e = NULL; - - /* convert the song to ss events */ - ss_song_convert_events(&n_channels); - - if (verbose >= 2) - printf("Tracks: %d Channels: %d Events: %d\n", - n_song_tracks, n_channels, n_ss_ev); - - if (trace) { - printf("** SOFTWARE SYNTHESIZER EVENT DUMP **\n\n"); - dump_song_events(ss_song, n_ss_ev); - return 0; - } - - /* set the number of channels, unless forced */ - if (ss_nchannels == -1) - ss_nchannels = n_channels > 0 ? n_channels : 2; - - if (ss_output_open(driver, devfile) < 0) { - printf("Error: can't init driver\n"); - return 2; - } - - /* init the generators */ - ss_gen_init(); - - /* init the instruments */ - for (n = 0; n < n_song_tracks; n++) - ss_ins_init(&ss_song_ins[n]); - - /* calculate the frame to start playing */ - skip_frames = skip_secs * ss_frequency; - - /* main loop */ - do { - /* process all events in this frame */ - e = process_this_frame_events(e, skip_frames); - - /* reset frame samples */ - ss_output_init_frame(output); - - /* generate output from all instruments */ - for (n = i = 0; n < n_song_tracks; n++) - i += ss_ins_frame(&ss_song_ins[n], output); - - /* dump to sampling driver */ - ss_output_write(output); - } while (i); - - if (verbose >= 1) - printf("\n"); - - ss_output_close(); - - return 0; -} +/* + + Ann Hell Ex Machina - Music Software + Copyright (C) 2003/2008 Angel Ortega + + ss_song.c - Software synth song event stream management + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.triptico.com + +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include "ahxm.h" + + +/** data **/ + +/* the softsynth song stream */ + +static struct song_ev *ss_song = NULL; +static int n_ss_ev = 0; + +/* the instruments */ + +struct ss_ins ss_song_ins[SS_MAX_INSTRUMENTS]; + + +/** code **/ + +static struct song_ev *add_ss_ev(const struct song_ev *e) +/* adds a softsynth song event */ +{ + return copy_event(&ss_song, &n_ss_ev, e); +} + + +static int frame_type_eventid_cmp(const void *v1, const void *v2) +/* softsynth song event compare function for qsort() */ +{ + struct song_ev *e1; + struct song_ev *e2; + int ret; + + e1 = (struct song_ev *) v1; + e2 = (struct song_ev *) v2; + + ret = e1->frame - e2->frame; + + if (ret == 0) + ret = e1->type - e2->type; + + if (ret == 0) + ret = e1->event_id - e2->event_id; + + return ret; +} + + +static void ss_song_convert_events(int *n_channels) +/* converts generic song_ev events to softsynth events */ +{ + int note_id = 1; + struct song_ev *e; + int frame, frame_ac, f_frame; + double fpw, time_ac, time_ac_m; + int num, den; + int n; + + *n_channels = -1; + + /* resets the ss stream */ + if (ss_song != NULL) { + free(ss_song); + ss_song = NULL; + } + + n_ss_ev = 0; + + /* sorts the song */ + song_sort(); + + fpw = 0; + frame = frame_ac = f_frame = 0; + time_ac = time_ac_m = 0; + num = den = 4; + + /* travels the song events generating softsynth song events */ + for (n = 0; n < n_song_ev; n++) { + /* gets the song event */ + e = &song[n]; + + /* calculates the frame */ + frame = ((e->time - time_ac) * fpw) + frame_ac; + e->frame = frame; + + switch (e->type) { + case SONG_EV_TEMPO: + + /* updates accumulations */ + frame_ac = frame; + time_ac = e->time; + + /* calculates frames-per-whole based on new tempo */ + fpw = (double) ss_frequency *60.0; + fpw /= e->amount / 4.0; + + add_ss_ev(e); + + break; + + case SONG_EV_METER: + + /* just store the values */ + num = e->min; + den = e->max; + time_ac_m = e->time; + + break; + + case SONG_EV_MEASURE: + + song_test_measure_boundary(e->time - time_ac_m, + num, den, e->value); + break; + + case SONG_EV_NOTE: + + /* assign a note id */ + e->note_id = note_id++; + + /* copy */ + add_ss_ev(e); + + /* copy again, but set as NOTE_OFF */ + e = add_ss_ev(e); + e->type = SONG_EV_NOTE_OFF; + + frame += (int) (e->len * fpw); + e->frame = frame; + + break; + + case SONG_EV_BACK: + + /* move the cursor back */ + + frame_ac -= (int) (e->len * fpw); + + break; + + case SONG_EV_SS_PITCH_STRETCH: + + /* assign a note id */ + e->note_id = note_id++; + + /* copy */ + add_ss_ev(e); + + /* and copy again, as a note off */ + e = add_ss_ev(e); + e->type = SONG_EV_NOTE_OFF; + + frame += (int) (e->len * fpw); + e->frame = frame; + + break; + + case SONG_EV_SS_PRINT_WAVE_TEMPO: + case SONG_EV_SS_WAV: + case SONG_EV_SS_PAT: + case SONG_EV_SS_SF2: + case SONG_EV_SS_SUSTAIN: + case SONG_EV_SS_ATTACK: + case SONG_EV_SS_VIBRATO: + case SONG_EV_SS_PORTAMENTO: + case SONG_EV_SS_EFF_DELAY: + case SONG_EV_SS_EFF_ECHO: + case SONG_EV_SS_EFF_COMB: + case SONG_EV_SS_EFF_ALLPASS: + case SONG_EV_SS_EFF_FLANGER: + case SONG_EV_SS_EFF_WOBBLE: + case SONG_EV_SS_EFF_SQWOBBLE: + case SONG_EV_SS_EFF_HFWOBBLE: + case SONG_EV_SS_EFF_FADER: + case SONG_EV_SS_EFF_REVERB: + case SONG_EV_SS_EFF_FOLDBACK: + case SONG_EV_SS_EFF_ATAN: + case SONG_EV_SS_EFF_DISTORT: + case SONG_EV_SS_EFF_OVERDRIVE: + case SONG_EV_SS_EFF_OFF: + case SONG_EV_SS_MASTER_VOLUME: + case SONG_EV_SONG_INFO: + case SONG_EV_EOT: + + /* just copy */ + add_ss_ev(e); + break; + + case SONG_EV_SS_CHANNEL: + + /* count channels */ + if (*n_channels < e->channel) + *n_channels = e->channel; + + add_ss_ev(e); + break; + + case SONG_EV_NOP: + case SONG_EV_MIDI_CHANNEL: + case SONG_EV_MIDI_PROGRAM: + + /* ignored */ + break; + + case SONG_EV_NOTE_OFF: + case SONG_EV_END: + + /* never found in generic song streams */ + break; + } + + /* store the further frame seen */ + if (f_frame < frame) + f_frame = frame; + } + + /* generates an end of event mark, a time after the last one */ + e = add_event(&ss_song, &n_ss_ev); + + e->type = SONG_EV_END; + e->frame = f_frame + ss_frequency; + e->event_id = -1; + + /* finally sort */ + qsort(ss_song, n_ss_ev, sizeof(struct song_ev), + frame_type_eventid_cmp); + + /* count one more */ + (*n_channels)++; +} + + +static const struct song_ev *process_this_frame_events(const struct song_ev + *e, int skip_frames) +/* process the events attached to this frame */ +{ + static double tempo = 120.0; + static int frame = 0; + + /* from the beginning? */ + if (e == NULL) { + e = ss_song; + tempo = 120.0; + frame = 0; + } + + if (verbose >= 1 && frame % ss_frequency == 0) { + int m = frame / ss_frequency; + printf("[%02d:%02d]\r", m / 60, m % 60); + fflush(stdout); + } + + while (e != NULL && e->frame == frame) { + struct ss_ins *i; + struct ss_wave *w; + double freq; + + if (e->type == SONG_EV_NOTE || + e->type == SONG_EV_NOTE_OFF || + e->type == SONG_EV_SS_PITCH_STRETCH) { + if (frame < skip_frames) { + e++; + frame = e->frame; + continue; + } + } + + /* take the instrument */ + if (e->trk_id < 0) + i = NULL; + else + i = &ss_song_ins[e->trk_id]; + + switch (e->type) { + case SONG_EV_NOTE: + + if (ss_ins_note_on(i, e->value, e->vol, e->note_id) < 0 && + verbose >= 1) + printf("ss_ins_note_on error: track %d note %d\n", + e->trk_id, e->value); + + break; + + case SONG_EV_NOTE_OFF: + + ss_ins_note_off(i, e->note_id); + + break; + + case SONG_EV_SS_SUSTAIN: + + ss_ins_set_sustain(i, e->amount); + + break; + + case SONG_EV_SS_ATTACK: + + ss_ins_set_attack(i, e->amount); + + break; + + case SONG_EV_SS_VIBRATO: + + ss_ins_set_vibrato(i, e->depth, e->freq); + + break; + + case SONG_EV_SS_PORTAMENTO: + + ss_ins_set_portamento(i, (e->amount * 44100.0) + / ((double) ss_frequency * 1000000.0)); + + break; + + case SONG_EV_SS_CHANNEL: + + ss_ins_set_channel(i, e->channel, e->vol); + + break; + + case SONG_EV_SS_WAV: + + w = ss_load_wav_file(e->name, + ss_note_frequency(e->value), + ss_note_frequency(e->min), + ss_note_frequency(e->max), + e->start, e->end, + e->channel, e->skip_channels); + + /* fail if can't open wav */ + if (w == NULL) { + printf("Can't load wav '%s'\n", e->name); + e = NULL; + } + else + ss_ins_add_layer(i, w); + + break; + + case SONG_EV_SS_PAT: + + if (ss_load_pat_file(i, e->name) < 0) { + printf("Can't load pat '%s'\n", e->name); + e = NULL; + } + + break; + + case SONG_EV_SS_SF2: + + if (ss_load_sf2_file(i, e->name, e->str2) < 0) { + printf("Can't load instrument from sf2 '%s'\n", e->name); + e = NULL; + } + + break; + + case SONG_EV_SS_EFF_DELAY: + + ss_eff_delay(&i->effs[e->channel], e->len); + break; + + case SONG_EV_SS_EFF_ECHO: + + ss_eff_echo(&i->effs[e->channel], e->len, e->vol); + break; + + case SONG_EV_SS_EFF_COMB: + + ss_eff_comb(&i->effs[e->channel], e->len, e->vol); + break; + + case SONG_EV_SS_EFF_ALLPASS: + + ss_eff_allpass(&i->effs[e->channel], e->len, e->vol); + break; + + case SONG_EV_SS_EFF_FLANGER: + + ss_eff_flanger(&i->effs[e->channel], + e->len, e->vol, e->depth, e->freq, e->phase); + break; + + case SONG_EV_SS_EFF_WOBBLE: + + ss_eff_wobble(&i->effs[e->channel], e->freq, e->phase, e->vol); + + break; + + case SONG_EV_SS_EFF_SQWOBBLE: + + ss_eff_square_wobble(&i->effs[e->channel], e->freq, e->phase); + + break; + + case SONG_EV_SS_EFF_HFWOBBLE: + + ss_eff_half_wobble(&i->effs[e->channel], e->freq, e->phase); + + break; + + case SONG_EV_SS_EFF_FADER: + + ss_eff_fader(&i->effs[e->channel], e->len, e->initial, + e->final); + break; + + case SONG_EV_SS_EFF_REVERB: + + ss_eff_reverb(&i->effs[e->channel]); + break; + + case SONG_EV_SS_EFF_FOLDBACK: + + ss_eff_foldback(&i->effs[e->channel], e->vol); + break; + + case SONG_EV_SS_EFF_ATAN: + + ss_eff_atan(&i->effs[e->channel], e->vol); + break; + + case SONG_EV_SS_EFF_DISTORT: + + ss_eff_distort(&i->effs[e->channel], e->vol); + break; + + case SONG_EV_SS_EFF_OVERDRIVE: + + ss_eff_overdrive(&i->effs[e->channel], e->vol); + break; + + case SONG_EV_SS_EFF_OFF: + + ss_eff_off(&i->effs[e->channel]); + break; + + case SONG_EV_TEMPO: + + /* just store the last tempo */ + tempo = e->amount; + break; + + case SONG_EV_SS_PITCH_STRETCH: + + /* find the wave */ + freq = ss_note_frequency(e->value); + w = ss_ins_find_layer(i, freq, NULL); + + /* calculate optimal frequency */ + freq = ss_pitch_from_tempo(w, tempo, e->len); + + /* play the note */ + if (ss_ins_play(i, freq, e->vol, + e->note_id, w) < 0 && verbose >= 1) + printf("ss_ins_play error: track %d freq %f\n", + e->trk_id, freq); + + break; + + case SONG_EV_SS_PRINT_WAVE_TEMPO: + + /* find the wave */ + freq = ss_note_frequency(e->value); + w = ss_ins_find_layer(i, freq, NULL); + + /* print the optimal tempo */ + printf("Optimal tempo: %lf\n", + ss_tempo_from_wave(w, e->value, e->len)); + + break; + + case SONG_EV_SS_MASTER_VOLUME: + + /* set master volume */ + ss_master_volume = e->vol; + break; + + case SONG_EV_SONG_INFO: + + /* add a new song (track) */ + cue_file_song_info(frame, e->str2, e->name); + break; + + case SONG_EV_EOT: + + /* end of track; trigger possible cleaning */ + ss_ins_disable(i); + break; + + case SONG_EV_END: + + e = NULL; + break; + + case SONG_EV_BACK: + case SONG_EV_MIDI_CHANNEL: + case SONG_EV_MIDI_PROGRAM: + case SONG_EV_METER: + case SONG_EV_MEASURE: + case SONG_EV_NOP: + + /* never found in ss song streams */ + break; + } + + /* next event */ + if (e) + e++; + } + + frame++; + + return e; +} + + +int ss_song_render(int skip_secs, const char *driver, const char *devfile) +{ + int n, i = 0; + sample_t output[SS_MAX_CHANNELS]; + int skip_frames; + int n_channels; + const struct song_ev *e = NULL; + + /* convert the song to ss events */ + ss_song_convert_events(&n_channels); + + if (verbose >= 2) + printf("Tracks: %d Channels: %d Events: %d\n", + n_song_tracks, n_channels, n_ss_ev); + + if (trace) { + printf("** SOFTWARE SYNTHESIZER EVENT DUMP **\n\n"); + dump_song_events(ss_song, n_ss_ev); + return 0; + } + + /* set the number of channels, unless forced */ + if (ss_nchannels == -1) + ss_nchannels = n_channels > 0 ? n_channels : 2; + + if (ss_output_open(driver, devfile) < 0) { + printf("Error: can't init driver\n"); + return 2; + } + + /* init the generators */ + ss_gen_init(); + + /* init the instruments */ + for (n = 0; n < n_song_tracks; n++) + ss_ins_init(&ss_song_ins[n]); + + /* calculate the frame to start playing */ + skip_frames = skip_secs * ss_frequency; + + /* main loop */ + do { + /* process all events in this frame */ + e = process_this_frame_events(e, skip_frames); + + /* reset frame samples */ + ss_output_init_frame(output); + + /* generate output from all instruments */ + for (n = i = 0; n < n_song_tracks; n++) + i += ss_ins_frame(&ss_song_ins[n], output); + + /* dump to sampling driver */ + ss_output_write(output); + } while (i); + + if (verbose >= 1) + printf("\n"); + + ss_output_close(); + + return 0; +} diff --git a/stress.c b/stress.c dissimilarity index 89% index b92961b..3edea11 100644 --- a/stress.c +++ b/stress.c @@ -1,26 +1,21 @@ -#include - -#include "config.h" -#include "ahxm.h" - -int main(int argc, char *argv[]) -{ - int n; - sample_t s; - struct ss_wave *w; - - printf("load samples/amen1.wav\n"); - w = ss_load_wav_file("samples/amen1.wav", 440, 440, 440, 0, 0, 0, 0); - - printf("load some samples from wave\n"); - - for (n = 0; n < 10; n++) - printf("%lf\n", ss_get_sample(w, 0, (double) n)); - - printf("again, load same samples from wave\n"); - - for (n = 0; n < 10; n++) - printf("%lf\n", ss_get_sample(w, 0, (double) n)); - - return 0; -} +#include + +#include "config.h" +#include "ahxm.h" + int main(int argc, char *argv[]) +{ + int n; + sample_t s; + struct ss_wave *w; + printf("load samples/amen1.wav\n"); + w = ss_load_wav_file("samples/amen1.wav", 440, 440, 440, 0, 0, 0, 0); + printf("load some samples from wave\n"); + for (n = 0; n < 10; n++) + printf("%lf\n", ss_get_sample(w, 0, (double) n)); + printf("again, load same samples from wave\n"); + for (n = 0; n < 10; n++) + printf("%lf\n", ss_get_sample(w, 0, (double) n)); + return 0; + } + + diff --git a/support.c b/support.c index ce3b9f4..bcb511c 100644 --- a/support.c +++ b/support.c @@ -35,9 +35,8 @@ #include "ahxm.h" #include "sha1.h" -/******************* - Data -********************/ + +/** data **/ static char **library_path = NULL; static int n_library_paths = 0; @@ -52,17 +51,16 @@ int trace = 0; /* transparent converters */ struct transconv { - const char *from; /* extension from */ - const char *to; /* extension to */ - const char *convcmd; /* sprintf() format for converting command */ + const char *from; /* extension from */ + const char *to; /* extension to */ + const char *convcmd; /* sprintf() format for converting command */ }; static struct transconv *transconvs = NULL; static int n_transconvs = 0; -/******************* - Code -********************/ + +/** code **/ /** * libpath_add - Adds a directory path to the search path @@ -76,57 +74,58 @@ static int n_transconvs = 0; */ void libpath_add(const char *path, int strip) { - int n; - char *ptr; - char *p; - - /* if path starts with ~, set it to $HOME */ - if (*path == '~') { - char *new; - char *home; - - if ((home = getenv("HOME")) == NULL) - return; - - if ((new = malloc(strlen(home) + strlen(path) + 2)) == NULL) - return; - - strcpy(new, home); - strcat(new, "/"); - strcat(new, path + 1); - - p = new; - } - else { - /* just duplicate */ - p = strdup(path); - } - - /* if no directory path remains, abort */ - if ((ptr = strrchr(p, '/')) == NULL) { - free(p); - return; - } - - /* strip the filename part */ - if (strip) - *ptr = '\0'; - - /* now try to find if that path is already stored */ - for (n = 0; n < n_library_paths; n++) { - if (strcmp(p, library_path[n]) == 0) { - /* found; free and return */ - free(p); - return; - } - } - - /* add room for the new path */ - n_library_paths++; - library_path = (char **) realloc(library_path, n_library_paths * sizeof(char *)); - - /* store */ - library_path[n_library_paths - 1] = p; + int n; + char *ptr; + char *p; + + /* if path starts with ~, set it to $HOME */ + if (*path == '~') { + char *new; + char *home; + + if ((home = getenv("HOME")) == NULL) + return; + + if ((new = malloc(strlen(home) + strlen(path) + 2)) == NULL) + return; + + strcpy(new, home); + strcat(new, "/"); + strcat(new, path + 1); + + p = new; + } + else { + /* just duplicate */ + p = strdup(path); + } + + /* if no directory path remains, abort */ + if ((ptr = strrchr(p, '/')) == NULL) { + free(p); + return; + } + + /* strip the filename part */ + if (strip) + *ptr = '\0'; + + /* now try to find if that path is already stored */ + for (n = 0; n < n_library_paths; n++) { + if (strcmp(p, library_path[n]) == 0) { + /* found; free and return */ + free(p); + return; + } + } + + /* add room for the new path */ + n_library_paths++; + library_path = + (char **) realloc(library_path, n_library_paths * sizeof(char *)); + + /* store */ + library_path[n_library_paths - 1] = p; } @@ -143,31 +142,31 @@ void libpath_add(const char *path, int strip) */ FILE *libpath_fopen(const char *filename, const char *mode) { - int n; - FILE *f = NULL; - - /* try first here */ - if ((f = fopen(filename, mode)) != NULL) { - strncpy(located_file, filename, sizeof(located_file)); - located_file[sizeof(located_file) - 1] = '\0'; - - libpath_add(filename, 1); - return f; - } - - /* couldn't open; try concatenating all stored paths */ - for (n = n_library_paths - 1; n >= 0; n--) { - snprintf(located_file, sizeof(located_file), "%s/%s", - library_path[n], filename); - located_file[sizeof(located_file) - 1] = '\0'; - - if ((f = fopen(located_file, mode)) != NULL) { - libpath_add(located_file, 1); - break; - } - } - - return f; + int n; + FILE *f = NULL; + + /* try first here */ + if ((f = fopen(filename, mode)) != NULL) { + strncpy(located_file, filename, sizeof(located_file)); + located_file[sizeof(located_file) - 1] = '\0'; + + libpath_add(filename, 1); + return f; + } + + /* couldn't open; try concatenating all stored paths */ + for (n = n_library_paths - 1; n >= 0; n--) { + snprintf(located_file, sizeof(located_file), "%s/%s", + library_path[n], filename); + located_file[sizeof(located_file) - 1] = '\0'; + + if ((f = fopen(located_file, mode)) != NULL) { + libpath_add(located_file, 1); + break; + } + } + + return f; } @@ -182,13 +181,13 @@ FILE *libpath_fopen(const char *filename, const char *mode) */ char *libpath_locate(const char *filename) { - FILE *f; + FILE *f; - if ((f = libpath_fopen(filename, "r")) == NULL) - return NULL; + if ((f = libpath_fopen(filename, "r")) == NULL) + return NULL; - fclose(f); - return located_file; + fclose(f); + return located_file; } @@ -199,14 +198,14 @@ char *libpath_locate(const char *filename) */ void libpath_print(void) { - int n; + int n; - for (n = 0; n < n_library_paths; n++) { - if (n) - printf(";"); + for (n = 0; n < n_library_paths; n++) { + if (n) + printf(";"); - printf("%s", library_path[n]); - } + printf("%s", library_path[n]); + } } /** transparent conversions **/ @@ -214,137 +213,138 @@ void libpath_print(void) void transconv_add(const char *from, const char *to, const char *convcmd) /* adds a converter */ { - struct transconv *t; + struct transconv *t; - GROW(transconvs, n_transconvs, struct transconv); + GROW(transconvs, n_transconvs, struct transconv); - t = &transconvs[n_transconvs++]; + t = &transconvs[n_transconvs++]; - t->from = strdup(from); - t->to = strdup(to); - t->convcmd = strdup(convcmd); + t->from = strdup(from); + t->to = strdup(to); + t->convcmd = strdup(convcmd); } static char *transconv_sha_file(const char *file, const char *ext) /* builds a unique cache file basename using a SHA1 hash */ { - static char c_file[64]; - unsigned char sha1[20]; - SHA_CTX c; - int n; - - SHA1_Init(&c); - SHA1_Update(&c, (char *)file, strlen(file)); - SHA1_Update(&c, (char *)ext, strlen(ext)); - SHA1_Final(sha1, &c); - - for (n = 0; n < sizeof(sha1); n++) { - char tmp[3]; - - snprintf(tmp, sizeof(tmp), "%02x", sha1[n]); - c_file[n * 2] = tmp[0]; - c_file[(n * 2) + 1] = tmp[1]; - } - - c_file[n * 2] = '\0'; - return c_file; + static char c_file[64]; + unsigned char sha1[20]; + SHA_CTX c; + int n; + + SHA1_Init(&c); + SHA1_Update(&c, (char *) file, strlen(file)); + SHA1_Update(&c, (char *) ext, strlen(ext)); + SHA1_Final(sha1, &c); + + for (n = 0; n < sizeof(sha1); n++) { + char tmp[3]; + + snprintf(tmp, sizeof(tmp), "%02x", sha1[n]); + c_file[n * 2] = tmp[0]; + c_file[(n * 2) + 1] = tmp[1]; + } + + c_file[n * 2] = '\0'; + return c_file; } -static char *transconv_unique_file(const char *file, const char *ext, const char *dir) +static char *transconv_unique_file(const char *file, const char *ext, + const char *dir) /* builds a unique cache file name with complete path */ { - static char tmp[2048]; - char *c_path = NULL; + static char tmp[2048]; + char *c_path = NULL; - if ((c_path = getenv("TEMP")) == NULL) - if ((c_path = getenv("TMP")) == NULL) - c_path = "/tmp"; + if ((c_path = getenv("TEMP")) == NULL) + if ((c_path = getenv("TMP")) == NULL) + c_path = "/tmp"; - /* build the directory cache name */ - snprintf(tmp, sizeof(tmp), "%s/%s-%d", c_path, dir, getuid()); - tmp[sizeof(tmp) - 1] = '\0'; + /* build the directory cache name */ + snprintf(tmp, sizeof(tmp), "%s/%s-%d", c_path, dir, getuid()); + tmp[sizeof(tmp) - 1] = '\0'; - /* create the cache directory */ + /* create the cache directory */ #if CONFOPT_MKDIR_ARGS == 2 - mkdir(tmp, 0755); + mkdir(tmp, 0755); #else - mkdir(tmp); + mkdir(tmp); #endif - strcat(tmp, "/"); - strcat(tmp, transconv_sha_file(file, ext)); - strcat(tmp, ext); + strcat(tmp, "/"); + strcat(tmp, transconv_sha_file(file, ext)); + strcat(tmp, ext); - return tmp; + return tmp; } char *transconv_pipe(const char *cmd, const char *ext, const char *dir) /* executes cmd as a pipe */ { - char *c_file = transconv_unique_file(cmd, ext, dir); + char *c_file = transconv_unique_file(cmd, ext, dir); - /* does the file already exist? */ - if (access(c_file, R_OK)) { - char tmp[2048]; + /* does the file already exist? */ + if (access(c_file, R_OK)) { + char tmp[2048]; - snprintf(tmp, sizeof(tmp), cmd, c_file); - tmp[sizeof(tmp) - 1] = '\0'; + snprintf(tmp, sizeof(tmp), cmd, c_file); + tmp[sizeof(tmp) - 1] = '\0'; - if (verbose >= 2) - printf("Converting: %s\n", tmp); + if (verbose >= 2) + printf("Converting: %s\n", tmp); - system(tmp); - } + system(tmp); + } - return c_file; + return c_file; } char *transconv(const char *file, const char *ext, const char *dir) /* converts using the transparent converters and the cache, if needed */ { - char *this_ext; - char *c_file; - int n; - struct transconv *t; - - /* gets this file extension */ - if (file == NULL || (this_ext = strrchr(file, '.')) == NULL) - return NULL; - - /* if it's already the desired type, do nothing */ - if (strcmp(ext, this_ext) == 0) - return (char *)file; - - /* get a unique name */ - c_file = transconv_unique_file(file, ext, dir); - - /* does the file already exist? */ - if (access(c_file, R_OK) == 0) - return c_file; - - /* no; look for a suitable converter */ - for (n = 0, t = transconvs; n < n_transconvs; n++, t++) { - if (strcmp(t->from, ".*") == 0 || - (strcmp(ext, t->to) == 0 && strcmp(this_ext, t->from) == 0)) { - char tmp[2048]; - - /* found a converter! just do it */ - snprintf(tmp, sizeof(tmp), t->convcmd, c_file, file); - tmp[sizeof(tmp) - 1] = '\0'; - - if (verbose >= 2) - printf("Executing: %s\n", tmp); - - if (system(tmp) == 0) - break; - else - unlink(c_file); - } - } - - return c_file; + char *this_ext; + char *c_file; + int n; + struct transconv *t; + + /* gets this file extension */ + if (file == NULL || (this_ext = strrchr(file, '.')) == NULL) + return NULL; + + /* if it's already the desired type, do nothing */ + if (strcmp(ext, this_ext) == 0) + return (char *) file; + + /* get a unique name */ + c_file = transconv_unique_file(file, ext, dir); + + /* does the file already exist? */ + if (access(c_file, R_OK) == 0) + return c_file; + + /* no; look for a suitable converter */ + for (n = 0, t = transconvs; n < n_transconvs; n++, t++) { + if (strcmp(t->from, ".*") == 0 || + (strcmp(ext, t->to) == 0 && strcmp(this_ext, t->from) == 0)) { + char tmp[2048]; + + /* found a converter! just do it */ + snprintf(tmp, sizeof(tmp), t->convcmd, c_file, file); + tmp[sizeof(tmp) - 1] = '\0'; + + if (verbose >= 2) + printf("Executing: %s\n", tmp); + + if (system(tmp) == 0) + break; + else + unlink(c_file); + } + } + + return c_file; } -- 2.11.4.GIT