This repository has been archived on 2017-07-22. You can view files and clone it, but cannot push or open issues/pull-requests.
jlsampler/init.c

262 lines
6.9 KiB
C

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ini.h"
#include "parse.h"
#include "init.h"
static int sound_index(Sampler *s, const char *name) {
for(int i = 0; i < s->num_sounds; ++i) {
if(strncmp(s->index[i], name, MAX_NAME) == 0) {
return i;
}
}
return -1;
}
static int sound_index_add(Sampler *s, const char *name) {
if(s->num_sounds >= MAX_SOUNDS) {
printf("Maximum number of sounds exceeded: %s\n", name);
exit(1);
}
strncpy(s->index[s->num_sounds], name, MAX_NAME);
s->num_sounds += 1;
return s->num_sounds - 1;
}
static int sampler_handler(void *user,
const char *section,
const char *name,
const char *value) {
Sampler *s = (Sampler*)user;
if(strcmp(section, "SAMPLER") != 0) {
return 1;
}
printf("%s: %s = %s\n", section, name, value);
if(strcmp(name, "base_dir") == 0) {
strncpy(s->base_dir, value, PATH_MAX);
}
else if(strcmp(name, "midi_min") == 0) {
s->midi_min_vel = parse_int(value);
}
else if(strcmp(name, "midi_max") == 0) {
s->midi_max_vel = parse_int(value);
}
else {
printf("Unknown setting.\n");
exit(1);
}
return 1;
}
static int trigger_handler(void *user,
const char *section,
const char *name,
const char *value) {
Sampler *s = (Sampler*)user;
if(strcmp(section, "TRIGGERS") != 0) {
return 1;
}
printf("%s: %s = %s\n", section, name, value);
int from = parse_int(name);
if(from < 0 || from > 127) {
printf("Illegal trigger: %i\n", from);
exit(1);
}
int to = sound_index(s, value);
if(to == -1) {
to = sound_index_add(s, value);
}
s->trigger_map[from][s->num_triggers[from]] = to;
s->num_triggers[from]++;
return 1;
}
static int cut_handler(void *user,
const char *section,
const char *name,
const char *value) {
Sampler *s = (Sampler*)user;
if(strcmp(section, "CUTS") != 0) {
return 1;
}
printf("%s: %s = %s\n", section, name, value);
int from = sound_index(s, name);
if(from == -1) {
printf("Sound is not triggered: %s\n", name);
return 1;
}
int to = sound_index(s, value);
if(to == -1) {
printf("Sound is not triggered: %s\n", value);
return 1;
}
s->cut_map[from][s->num_cuts[from]] = to;
s->num_cuts[from]++;
return 1;
}
static void value_handler(SoundConfig *conf,
const char *name,
const char *value) {
if(strcmp(name, "path") == 0) {
strncpy((char*)&conf->path, value, PATH_MAX);
}
else if(strcmp(name, "gamma_amp") == 0) {
conf->gamma_amp = parse_double(value);
if(conf->gamma_amp <= 0) {
printf("Illegal gamma_amp value: %s\n", value);
exit(1);
}
}
else if(strcmp(name, "gamma_layer") == 0) {
conf->gamma_layer = parse_double(value);
if(conf->gamma_layer <= 0) {
printf("Illegal gamma_layer value: %s\n", value);
exit(1);
}
}
else if(strcmp(name, "tau_off") == 0) {
conf->tau_off = parse_double(value);
conf->tau_off = proc_raw_tau_value(conf->tau_off);
}
else if(strcmp(name, "tau_cut") == 0) {
conf->tau_cut = parse_double(value);
conf->tau_cut = proc_raw_tau_value(conf->tau_cut);
}
else if(strcmp(name, "fx_pre") == 0 || strcmp(name, "fx") == 0) {
soundconfig_proc_fx(conf, value, true);
}
else if(strcmp(name, "fx_post") == 0) {
soundconfig_proc_fx(conf, value, false);
}
else {
printf("Unknown value.\n");
exit(1);
}
}
static int sound_handler(void *user,
const char *section,
const char *name,
const char *value) {
Sampler *s = (Sampler*)user;
// Is this a new section? If so, record the name.
bool new_section = strcmp(s->section, section) != 0;
if(new_section) {
strncpy(s->section, section, MAX_NAME);
}
// Skip non-sound sections.
if(strcmp(section, "TRIGGERS") == 0 ||
strcmp(section, "CUTS") == 0 ||
strcmp(section, "SAMPLER") == 0) {
return 1;
}
printf("%s: %s = %s\n", section, name, value);
// Process a global section.
if(strcmp(section, "GLOBAL") == 0) {
if(new_section) {
soundconfig_load_defaults(&s->global_conf);
}
value_handler(&s->global_conf, name, value);
return 1;
}
// Otherwise this is a sound.
int i = sound_index(s, section);
if(i == -1) {
printf("Sound is not triggered: %s\n", section);
return 1;
}
Sound *sound = &s->sounds[i];
// If it's a new sound, apply the globals.
if(new_section) {
soundconfig_copy_globals(&sound->conf, &s->global_conf);
}
value_handler(&s->sounds[i].conf, name, value);
return 1;
}
void sampler_init(Sampler *sampler, char *conf_path) {
sampler->section[0] = '\0';
sampler->num_sounds = 0;
sampler->midi_min_vel = 0;
sampler->midi_max_vel = 127;
sampler->midi_free = jlrb_new(MAX_PLAYING);
sampler->midi_new = jlrb_new(MAX_PLAYING);
sampler->sustainControl = 64;
for(int i = 0; i < MAX_PLAYING; ++i) {
jlrb_put(sampler->midi_free, jl_malloc_exit(sizeof(MidiEvt)));
}
for(int i = 0; i < MAX_SOUNDS; ++i) {
sampler->index[i][0] = '\0';
sound_init(&sampler->sounds[i]);
sampler->num_triggers[i] = 0;
sampler->num_cuts[i] = 0;
}
// 1) Load sampler settings.
if(ini_parse(conf_path, sampler_handler, sampler) < 0) {
printf("Failed to parse config file %s (sampler).\n", conf_path);
exit(1);
}
// 2) Load the triggers.
if(ini_parse(conf_path, trigger_handler, sampler) < 0) {
printf("Failed to parse config file %s (triggers).\n", conf_path);
exit(1);
}
// 3) Load cuts.
if(ini_parse(conf_path, cut_handler, sampler) < 0) {
printf("Failed to parse config file %s (cuts).\n", conf_path);
exit(1);
}
// 4) Load configuration defaults before parsing sound section. We do this
// in case the user hasn't provided a GLOBAL section.
soundconfig_load_defaults(&sampler->global_conf);
// 5) Load sounds from the config file.
if(ini_parse(conf_path, sound_handler, sampler) < 0) {
printf("Failed to parse config file %s (sounds).\n", conf_path);
exit(1);
}
// Change into base directory.
if(chdir(sampler->base_dir) != 0) {
printf("Failed to change directory: %s\n", sampler->base_dir);
exit(1);
}
printf("Loaded %i sounds.\n", sampler->num_sounds);
}