Rev 2321 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* command.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "globals.h"
#include "din.h"
#include "command.h"
#include "console.h"
#include "math.h"
#include "delay.h"
#include "scalelist.h"
#include "font.h"
#include "glyph.h"
#include "chrono.h"
#include "utils.h"
#include "ui_list.h"
#include "curve_editor.h"
#include "tokenizer.h"
#include "tcl_interp.h"
#include "scale_info.h"
#include "keyboard_keyboard.h"
#include "main.h"
#include "audio.h"
#include "midi_in.h"
#include "fft.h"
#include "mondrian.h"
#include "binaural_drones.h"
#include "curve_mixer.h"
#include "recorder.h"
#include "circler.h"
#include "noiser.h"
#include "sine_mixer.h"
#include <string>
#include <fstream>
using namespace std;
extern ofstream dlog;
#define result cmdlst.result
extern i_binaural_drones binaural_drones0;
extern string SCALE;
extern string TUNING;
extern int NOTATION;
extern int TRAILSIZE;
extern int NUM_OCTAVES;
extern float VOICE_VOLUME;
extern float NOTE_VOLUME;
extern float ATTACK_TIME;
extern float DECAY_TIME;
extern float DELTA_TIME;
extern string INSTRUMENT;
extern const char* INSTRUMENTS [];
extern int CURRENT_INSTRUMENT;
extern int PITCH_BEND;
extern float PITCH_BEND_PER_PIXEL;
extern int NUM_NOTES;
extern const char* WESTERN_FLAT [];
extern const char* WESTERN_SHARP [];
extern float WIKIPEDIA_KEY_FREQUENCIES [];
extern load_globals lg;
extern scale_info scaleinfo;
extern string LOCATION;
extern string VERSION_NUMBER;
extern char BUFFER [];
extern const char spc;
extern map <string, float> INTERVALS;
extern scale_info all_notes;
extern int DIN_IS_BINAURAL;
extern int JUSTIFICATION;
extern float SEPARATION;
extern float BPM_MULT;
template <class T> void load_vector_from_string (const string& s, vector<T>& data) {
tokenizer tz (s);
data.clear ();
stringstream ss;
string t;
T tt;
while (1) {
ss.clear (); tz >> t;
if (t == "") break;
ss << t; ss >> tt; data.push_back (tt);
}
}
void cmdlist::add (command* cmd) {
dlog << "added command: " << cmd->longname << " aka " << cmd->shortname << endl;
cmds.push_back (cmd);
ncmds = cmds.size ();
}
cmdlist::~cmdlist () {
dlog << "--- destroyed cmdlist ---" << endl;
}
int set_var::set_scroll (string& varn, tokenizer& tz) {
while (1) {
tz >> varn;
if (varn == "r" || varn == "rate") {
tz >> d->dinfo.scroll.rate;
d->dinfo.scroll.calc_repeat_time ();
} else if (varn == "x") {
tz >> d->dinfo.scroll.dx;
} else if (varn == "y") {
tz >> d->dinfo.scroll.dy;
} else {
if (varn != "") {
result = varn + ": bad scroll param";
return 0;
} else return 1;
}
}
}
int set_var::set_zoom_pan (int& rate, float& amount, string& varn, tokenizer& tz) {
while (1) {
tz >> varn;
if (varn == "r" || varn == "rate") {
tz >> rate;
window::calc_repeats ();
MENU.set_pan_repeat (window::PAN_REPEAT);
} else if (varn == "a" || varn == "amount") {
tz >> amount;
window::calc_repeats ();
MENU.set_zoom_repeat (window::ZOOM_REPEAT);
if (uis.crved) uis.crved->win.calc_panxy ();
} else {
if (varn != "") {
result = varn + ": bad zoom/pan param";
return 0;
} else return 1;
}
}
}
int set_var::operator() (tokenizer& tz) {
string varn;
int extract = 1;
while (1) {
if (extract) {
tz >> varn;
result = "";
} else extract = 1;
//
// variables
if (varn == "spar" || varn == "show_parameters") {
int what; tz >> what;
if (what) uis.ab_parameters.set_dir (arrow_button::right); else uis.ab_parameters.set_dir (arrow_button::down);
uis.pal.clicked (uis.ab_parameters);
} else if (varn == "su" || varn == "sustain") {
float g; tz >> g; _gotog.set (g);
} else if (varn == "vv" || varn == "voice_volume") {
tz >> VOICE_VOLUME;
} else if (varn == "ins" || varn == "instrument") {
tz >> INSTRUMENT;
find_instrument ();
} else if (varn == "tu" || varn == "tuning") {
string name;
tz >> name >> uis.settings_scr.i_current_tuning;
string fname = name + ".tuning";
if (lg.load_intervals (fname)) {
TUNING = name;
result = name;
all_notes.intervals = INTERVALS;
din0.tuning_changed ();
keybd2.setup_notes ();
keybd2.setup_midi_notes ();
keybd2.calc_visual_params ();
mondrian0.calc_visual_params ();
uis.settings_scr.sn_scale_notes.refresh ();
cons ("list2var [get-intervals]");
} else {
result = "bad tuning";
return 0;
}
} else if (varn == "sc" || varn == "scroll") {
extract = set_scroll (varn, tz);
} else if (varn == "zoom" || varn == "z") {
extract = set_zoom_pan (window::ZOOM_RATE, window::ZOOM_AMOUNT, varn, tz);
} else if (varn == "pan" || varn == "p") {
extract = set_zoom_pan (window::PAN_RATE, window::PAN_AMOUNT, varn, tz);
} else if (varn == "fps") {
extern int FPS;
tz >> FPS;
if (FPS < 1) FPS = 120;
extern double TIME_PER_FRAME; TIME_PER_FRAME = 1.0f / FPS;
uis.settings_scr.sp_fps.set_value (FPS);
} else if (varn == "ips") {
extern int IPS; tz >> IPS; if (IPS <= 0) IPS = 100;
extern double TIME_PER_INPUT; TIME_PER_INPUT = 1.0 / IPS;
uis.settings_scr.sp_ips.set_value (IPS);
} else if (varn == "mixt" || varn == "mixing_time") {
tz >> curve_mixer::TIME;
} else if (varn == "tl" || varn == "trail_length") {
tz >> TRAILSIZE;
if (TRAILSIZE < 1) TRAILSIZE = 0;
} else if (varn == "fc" || varn == "fold_console") {
int fold; tz >> fold;
cons.rollup (fold);
} else if (varn == "midi_in") {
tz >> midiin.input_port;
} else if (varn == "stepz") {
string s; tz >> s;
MENU.lf_conn_steps.set_text (s);
MENU.stepsl.typing (MENU.lf_conn_steps.fld);
MENU.stepsl.changed (MENU.lf_conn_steps.fld);
} else if (varn == "current_plugin") {
int c; tz >> c;
uis.plugin__browser.set_cur (c);
} else if (varn == "ds" || varn == "mondrian.delta_speed") {
tz >> mondrian0.delta_speed;
} else if (varn == "drv" || varn == "mondrian.delta_rotate_velocity") {
tz >> mondrian0.delta_rotate_velocity;
} else if (varn == "mondrian.texture") {
tz >> mondrian::patstr;
mondrian::patlen = mondrian::patstr.length ();
mondrian0.fillpatbuf ();
} else if (varn == "mondrian.texstep") {
tz >> mondrian::patstep;
mondrian0.fillpatbuf ();
} else if (varn == "version" || varn == "ver") {
tz >> VERSION_NUMBER;
set_window_caption ();
} else if (varn == "min_mag" || varn == "mm") {
tz >> drone::posafxvelt::minmag;
} else if (varn == "wand" || varn == "drone_wand_dist") {
double d; tz >> d;
drone::wand.set (d);
} else if (varn == "curve-samples-nsec") {
float t; tz >> t;
curve_samples::nsec = t;
} else if (varn == "din-is-binaural") {
tz >> DIN_IS_BINAURAL;
} else if (varn == "justification") {
tz >> JUSTIFICATION;
} else if (varn == "separation") {
tz >> SEPARATION;
} else if (varn == "bm" || varn == "bpmmult") {
tz >> BPM_MULT;
} else if (varn == "c" || varn == "cursor") {
basic_editor* pb = uis.crved;
if (pb) {
basic_editor& b = *pb;
string x, y; tz >> x >> y;
if (x == "."); else b.cursor.ox = atof (x.c_str());
if (y == "."); else b.cursor.oy = atof (y.c_str());
b.cursor.calcv (pb);
warp_mouse (b.cursor.vx, view.ymax - b.cursor.vy);
cons.toggle_command_mode ();
} else
cons << RED << "set-var cursor can be used on curve editors only!" << eol;
} else {
if (varn != "") {
result = varn + ": variable not found.";
return 0;
} else
break;
}
}
return 1;
}
int get_var::operator() (tokenizer& tz) {
stringstream ss;
string varn;
while (1) {
tz >> varn;
if (varn == "spar" || varn == "show_parameters") {
int show_parameters = 0;
if (uis.ab_parameters.dir == arrow_button::down) show_parameters = 1;
ss << show_parameters << spc;
} else if (varn == "vv" || varn == "voice_volume") {
ss << VOICE_VOLUME << spc;
} else if (varn == "su" || varn == "sustain") {
ss << _gotog.g << spc;
} else if (varn == "ins" || varn == "instrument") {
ss << INSTRUMENTS [CURRENT_INSTRUMENT] << spc;
} else if (varn == "tu" || varn == "tuning") {
ss << TUNING << spc << uis.settings_scr.i_current_tuning << spc;
} else if (varn == "sc" || varn == "scroll") {
sprintf (BUFFER, "rate %d x %d y %d ", d->dinfo.scroll.rate, d->dinfo.scroll.dx, d->dinfo.scroll.dy);
ss << BUFFER << spc;
} else if (varn == "zoom") {
ss << "rate " << window::ZOOM_RATE << " amount " << window::ZOOM_AMOUNT << spc;
} else if (varn == "pan") {
ss << "rate " << window::PAN_RATE << " amount " << window::PAN_AMOUNT << spc;
} else if (varn == "fps") {
extern int FPS;
extern double FPSNOW;
ss << FPS << " wanted, " << FPSNOW << " got ";
} else if (varn == "ips") {
extern int IPS; ss << IPS << spc;
} else if (varn == "mixt" || varn == "mixing_time") {
ss << curve_mixer::TIME << spc;
} else if (varn == "mixs" || varn == "mixing_samples") {
ss << int (curve_mixer::TIME * SAMPLE_RATE + 0.5) << spc;
} else if (varn == "tl" || varn == "trail_length") {
ss << TRAILSIZE << spc;
} else if (varn == "fc" || varn == "fold_console") {
ss << cons.rollup () << spc;
} else if (varn == "midi_in") {
ss << midiin.input_port << spc;
} else if (varn == "stepz") {
ss << MENU.lf_conn_steps.fld.text << spc;
} else if (varn == "curve-samples-nsec") {
ss << curve_samples::nsec << spc;
} else if (varn == "current_plugin") {
ss << uis.plugin__browser.cur << spc;
} else if (varn == "mondrian.delta_speed") {
ss << mondrian0.delta_speed << spc;
} else if (varn == "mondrian.delta_rotate_velocity") {
ss << mondrian0.delta_rotate_velocity << spc;
} else if (varn == "mondrian.texture") {
ss << mondrian0.patstr << spc;
} else if (varn == "mondrian.texstep") {
ss << mondrian0.patstep << spc;
} else if (varn == "microtonal_keyboard.scale") {
ss << din0.scaleinfo.name << spc;
} else if (varn == "keyboard_keyboard.scale") {
ss << keybd2.scaleinfo.name << spc;
} else if (varn == "mondrian.scale") {
ss << mondrian0.scaleinfo.name << spc;
} else if (varn == "notation") {
ss << NOTATION << spc;
} else if (varn == "version") {
ss << VERSION_NUMBER << spc;
} else if (varn == "min_mag" || varn == "mm") {
ss << drone::posafxvelt::minmag << spc;
} else if (varn == "wand" || varn == "drone_wand_dist") {
ss << drone::wand.dist << spc;
} else if (varn == "binaural_drones.scale") {
ss << binaural_drones0.scaleinfo.name << spc;
} else if (varn == "binaural_drones.master_volume") {
ss << binaural_drones0.master_volume << spc;
} else if (varn == "binaural_drones.justification") {
ss << binaural_drones0.just << spc;
} else if (varn == "is_curve_editor") {
ss << uis.current->ed << spc;
} else if (varn == "curve_editor_id") {
sprintf (BUFFER, "%u", (uintptr_t) uis.crved);
ss << BUFFER << spc;
} else if (varn == "din-is-binaural") {
ss << DIN_IS_BINAURAL << spc;
} else if (varn == "justification") {
ss << JUSTIFICATION << spc;
} else if (varn == "separation") {
ss << SEPARATION << spc;
} else if (varn == "bm" || varn == "bpmmult") {
ss << BPM_MULT << spc;
}
else {
if (varn != "") {
result = varn + ": not found.";
dlog << result << endl;
return 0;
} else break;
}
}
result = ss.str().substr (0, ss.str().length() - 1);
return 1;
}
int set_delay::operator() (tokenizer& tz) {
string name;
float value;
delay* d[2] = {left, right};
delay** pd = d;
int n = -1;
tz >> name >> value;
if (name == "a" || name == "all") n = 2;
else if (name == "l" || name == "left") n = 1;
else if (name == "r" || name == "right") {
pd++;
n = 1;
} else {
result = "bad delay name";
return 0;
}
for (int i = 0; i < n; ++i, pd++) {
(*pd)->set (value);
}
return 1;
}
int get_delay::operator() (tokenizer& tz) {
delay* d;
string s; tz >> s;
if (s == "left" || s == "l") d = left;
else if (s == "right" || s == "r") d = right;
else {
result = "bad delay name";
return 0;
}
float t; d->get (t);
sprintf (BUFFER, "%0.2f", t);
result = BUFFER;
return 1;
}
int bpm_com::get_bpm_id_from_name (const string& name) {
for (int i = 0; i < NUM; ++i) {
if (name == str[i]) {
return i;
}
}
return -1;
}
int ls_bpm::operator() (tokenizer& tz) {
for (int i = 0;i < NUM; ++i) {
result = result + str[i] + spc;
}
return 1;
}
int set_bpm::operator() (tokenizer& tz) {
string name;
float bpm;
tz >> name >> bpm;
int id = get_bpm_id_from_name (name);
if (id != -1) {
bv[id]->set_bpm (bpm);
MENU.update_bpm (name, bpm);
}
return 1;
}
int get_bpm::operator() (tokenizer& tz) {
vector<string> names;
string s; tz >> s; load_vector_from_string (s, names);
stringstream ss;
for (int i = 0, j = names.size (); i < j; ++i) {
int id = get_bpm_id_from_name (names[i]);
if (id != -1) ss << bv[id]->bpm << spc;
}
result = ss.str ();
return 1;
}
int set_beat::operator() (tokenizer& tz) {
vector<string> names;
vector<float> nows;
string s;
tz >> s; load_vector_from_string (s, names);
tz >> s; load_vector_from_string (s, nows);
for (int i = 0, j = names.size (), k = nows.size (), l = k - 1; i < j; ++i) {
int id = get_bpm_id_from_name (names[i]);
if (id != -1) {
if (i < k) bv[id]->now = nows[i]; else if (l > -1) bv[id]->now = nows[l];
}
}
return 1;
}
int get_beat::operator() (tokenizer& tz) {
vector<string> names;
stringstream ss;
string s; tz >> s; load_vector_from_string (s, names);
string what; tz >> what;
for (int i = 0, j = names.size (); i < j; ++i) {
int id = get_bpm_id_from_name (names[i]);
if (id != -1) {
if (what == "") ss << bv[id]->now << spc;
else if (what == "first") ss << bv[id]->sol.firstx << spc;
else if (what == "last") ss << bv[id]->sol.lastx << spc;
else if (what == "all") ss << '{' << bv[id]->now << spc << bv[id]->sol.firstx << spc << bv[id]->sol.lastx << "} ";
}
}
result = ss.str ();
return 1;
}
int set_style::operator() (tokenizer& tz) {
vector<string> names;
vector<string> styles;
string s;
tz >> s; load_vector_from_string (s, names);
tz >> s; load_vector_from_string (s, styles);
for (int i = 0, j = names.size (), k = styles.size (), l = k - 1; i < j; ++i) {
int id = get_bpm_id_from_name (names[i]);
if (id != -1) {
string style;
if (i < k) style = styles[i]; else if (l > -1) style = styles[l];
xhandler *xmin = 0, *xmax = 0;
if (style == "loop") {
xmin = &_loopmin;
xmax = &_loopmax;
} else if (style == "pong") {
xmin = &_pongmin;
xmax = &_pongmax;
} else {
result = "bad style: " + style;
return 0;
}
beat2value* b = bv[id];
b->xmin = xmin;
b->xmax = xmax;
b->style = style;
}
}
return 1;
}
int get_style::operator() (tokenizer& tz) {
vector<string> names;
string s; tz >> s; load_vector_from_string (s, names);
stringstream ss;
for (int i = 0, j = names.size (); i < j; ++i) {
int id = get_bpm_id_from_name (names[i]);
if (id != -1) ss << bv[id]->style << spc;
}
result = ss.str ();
return 1;
}
int add_scale::operator() (tokenizer& tz) {
extern scalelist scalelst;
scalelst.add (tz);
return 1;
}
int ls_scales::operator() (tokenizer& tz) {
extern scalelist scalelst;
scalelst.ls ();
return 1;
}
int remove_scale::operator() (tokenizer& tz) {
string nam; tz >> nam;
if (nam != "") {
extern scalelist scalelst;
scalelst.remove (nam);
return 1;
}
result = "bad scale name";
return 0;
}
int load_scale::operator() (tokenizer& tz) {
string inst, scale;
tz >> inst >> scale;
if (scale != "") {
instrument* instr = find_instrument (inst);
if (instr) {
instr->scaleinfo.load_scale (scale);
SCALE = scale;
result = "scale is " + scale;
return 1;
} else return 0;
} else {
result = scale + ": not found";
return 0;
}
}
int ls_notes::operator() (tokenizer& tz) {
string name; tz >> name;
extern scalelist scalelst;
scale r;
if (scalelst.get (name, r)) {
result = r.notes;
return 1;
} else {
result = name + ": bad scale";
return 0;
}
}
int set_kern::operator() (tokenizer& tz) {
extern font fnt;
char a, b;
int k;
tz >> a >> b >> k;
if (a == '.') {
map<char, glyph>& m = fnt.characters;
for (map<char, glyph>::iterator i = m.begin(), j = m.end(); i != j; ++i) fnt.kern[(*i).first][b] = k * fnt.cellsize.x;
fnt.mod = 1;
} else if (b == '.') {
map<char, glyph>& m = fnt.characters;
for (map<char, glyph>::iterator i = m.begin(), j = m.end(); i != j; ++i) fnt.kern[a][(*i).first] = k * fnt.cellsize.x;
fnt.mod = 1;
} else {
fnt.kern[a][b] = k * fnt.cellsize.x;
fnt.mod = 1;
}
return 1;
}
int get_kern::operator() (tokenizer& tz) {
extern font fnt;
char a, b;
int k;
tz >> a >> b >> k;
if (a == '.') {
map<char, glyph>& m = fnt.characters;
for (map<char, glyph>::iterator i = m.begin(), j = m.end(); i != j; ++i) {
a = (*i).first;
cons << a << spc << b << spc << fnt.kern[a][b] / fnt.cellsize.x << eol;
}
} else if (b == '.') {
map<char, glyph>& m = fnt.characters;
for (map<char, glyph>::iterator i = m.begin(), j = m.end(); i != j; ++i) {
b = (*i).first;
cons << a << spc << b << spc << fnt.kern[a][b] / fnt.cellsize.x << eol;
}
} else {
cons << a << spc << b << spc << fnt.kern[a][b] / fnt.cellsize.x << eol;
}
return 1;
}
int set_font_size::operator() (tokenizer& tz) {
extern font fnt;
int xsize, ysize, ch, headroom;
tz >> xsize >> ysize >> ch >> headroom;
if (xsize < 1) xsize = fnt.cellsize.x;
if (ysize < 1) ysize = fnt.cellsize.y;
if (ch < 1) ch = fnt.spacing.ch;
if (headroom < 1) headroom = fnt.headroom;
fnt.cellsize.x = xsize;
fnt.cellsize.y = ysize;
fnt.load (fnt.fname);
fnt.spacing.ch = ch;
fnt.headroom = headroom;
fnt.spacing.word = 2 * fnt.spacing.ch;
return 1;
}
int get_font_size::operator() (tokenizer& tz) {
sprintf (BUFFER, "%d %d %d %d", fnt.cellsize.x, fnt.cellsize.y, fnt.spacing.ch, fnt.headroom);
result = BUFFER;
return 1;
}
int set_kb_layout::operator() (tokenizer& tz) {
// keyboard layout; qwerty us/uk for now
static string norm_us ("abcdefghijklmnopqrstuvwxyz0123456789 .=-/;\\,[]'`");
static string shift_us ("ABCDEFGHIJKLMNOPQRSTUVWXYZ)!@#$%^&*( >+_?:|<{}\"~");
static string norm_uk ("abcdefghijklmnopqrstuvwxyz0123456789 .=-/;\\,[]'`#");
static string shift_uk ("ABCDEFGHIJKLMNOPQRSTUVWXYZ)!\"#$%^&*( >+_?:|<{}@~~");
extern string CHARSET [];
string name; tz >> name;
if (name == "us" || name == "usa") {
layout = name;
CHARSET [0] = norm_us;
CHARSET [1] = shift_us;
} else if (name == "gb" || name == "uk") {
layout = name;
CHARSET [0] = norm_uk;
CHARSET [1] = shift_uk;
} else {
result = layout;
return 0;
}
return 1;
}
int get_note_num (const string& s) {
for (int i = 0; i < NUM_NOTES; ++i) {
if (s == WESTERN_SHARP [i] || s == WESTERN_FLAT[i]) return i;
}
return -1;
}
int note_distance::operator() (tokenizer& tz) {
string note1, note2, verbose;
tz >> note1 >> note2 >> verbose;
if (note1.length() && note2.length()) {
note1[0] = toupper (note1[0]);
note2[0] = toupper (note2[0]);
} else return 0;
static const char* dist1 [] = {
"1", "2b", "2", "3b", "3", "4", "4#", "5", "6b", "6", "7b", "7", "8"
};
static const char* dist2 [] = {
"same", "minor_second", "second", "minor_third", "third", "perfect_fourth", "diminished_fifth", "perfect_fifth", "minor_sixth", "sixth", "minor_seventh", "seventh", "octave"
};
int i = get_note_num (note1), j = get_note_num (note2);
if (i == -1 || j == -1) return 0; else {
if (j <= i) j += 12;
int ji = j - i;
if (verbose.length()) {
sprintf (BUFFER, "%s %s", dist1[ji], dist2[ji]);
result = BUFFER;
return 1;
} else {
result = dist1[ji];
return 1;
}
}
}
int chord::operator() (tokenizer& tz) {
string root, type;
tz >> root >> type;
if (root.length()) root[0] = toupper (root[0]); else return 0;
int nn = get_note_num (root);
if (nn == -1) {
result = root + ": bad note";
return 0;
} else {
const int ntypes = 20;
static const char* types[] = {
"", // major
"m", // minor
"maj7", // major 7
"m7", // minor 7
"sus4", // suspended 4th
"7sus4", // dominant 7th, suspended 4th
"6", // major 6th
"m6", // minor 6th
"7", // dominant 7th
"9", // dominant 9th
"5", // power chord
"69", // maj 6th, add 9
"11", // dominant 11th
"13", // dominant 13th
"add9", // major add 9th
"m9", // minor 9th
"maj9", // major 9th
"+", // augmented
"07", // diminished 7th
"0" // diminished triad
};
static const int steps[][7] = {
{3, 0, 4, 7}, // num_notes, root, note1, note2....
{3, 0, 3, 7},
{4, 0, 4, 7, 11},
{4, 0, 3, 7, 10},
{3, 0, 5, 7},
{4, 0, 5, 7, 10},
{4, 0, 4, 7, 9},
{4, 0, 3, 7, 9},
{4, 0, 4, 7, 10},
{5, 0, 4, 7, 10, 14},
{2, 0, 7},
{5, 0, 4, 7, 9, 14},
{6, 0, 4, 7, 10, 14, 17},
{6, 0, 4, 7, 10, 14, 21},
{4, 0, 4, 7, 14},
{5, 0, 3, 7, 10, 14},
{5, 0, 4, 7, 11, 14},
{3, 0, 4, 8},
{4, 0, 3, 6, 10},
{3, 0, 3, 6}
};
int t = -1;
for (int i = 0; i < ntypes; ++i) {
if (type == types[i]) {
t = i; break;
}
}
if (t == -1) return 0; else {
const int* ch = &steps[t][0];
stringstream ss1, ss2;
for (int i = 0, j = ch[0], k = 1; i < j; ++i, ++k) {
int p = (nn + ch[k]) % 12;
ss1 << WESTERN_FLAT [p] << spc;
ss2 << WESTERN_SHARP [p] << spc;
}
result = ss1.str () + ss2.str ();
return 1;
}
}
}
extern string NEAREST_NOTE;
extern float NEAREST_NOTE_FREQUENCY;
extern float NEAREST_NOTE_DISTANCE;
int key::operator() (tokenizer& tz) {
string inst, s; tz >> inst >> s;
instrument* instr = find_instrument (inst);
string note ("invalid-note");
float tonic = get_tonic (instr);
NEAREST_NOTE_FREQUENCY = tonic;
if (s == "") {
// no args, just print key
find_nearest_note (NEAREST_NOTE, NEAREST_NOTE_FREQUENCY, NEAREST_NOTE_DISTANCE);
sprintf (BUFFER, "Key @ %0.3f Hz, nearest note is %s @ distance %0.3f Hz", tonic, NEAREST_NOTE.c_str(), NEAREST_NOTE_DISTANCE);
result = BUFFER;
return 1;
} else if (s == "value" || s == "v") {
sprintf (BUFFER, "%0.3f", get_tonic (instr));
result = BUFFER;
return 1;
} else if (s == "note" || s == "n") {
find_nearest_note (NEAREST_NOTE, NEAREST_NOTE_FREQUENCY, NEAREST_NOTE_DISTANCE);
result = NEAREST_NOTE;
return 1;
} else {
float freq = 0;
int oct = 0;
float val = (float) atof (s.c_str());
if (val <= 0) { // a note
if (s[0] != '.') {
s[0] = toupper(s[0]);
for (int i = 0; i < 12; ++i) {
if ((s == WESTERN_SHARP[i]) || (s == WESTERN_FLAT[i])) {
freq = WIKIPEDIA_KEY_FREQUENCIES[i];
break;
}
}
} else freq = tonic;
} else { // a value
freq = val;
}
// octave
tz >> s;
oct = atoi (s.c_str());
freq = freq * pow (2.0f, oct);
set_tonic (instr, freq);
}
return 0;
}
int notation::operator () (tokenizer& tz) {
tz >> NOTATION;
return 1;
}
int echo::operator() (tokenizer& tz) {
into_lines (tz.cur2end().c_str(), cons);
return 1;
}
multi_curve* get_curve (const string& name) {
extern vector<multi_curve *> curve_list;
multi_curve* crv = 0;
for (int i = 0, j = curve_list.size (); i < j; ++i) {
multi_curve* mc = curve_list[i];
if (mc->name == name) crv = mc;
}
return crv;
}
int curve_value::operator() (tokenizer& tz) {
string name; tz >> name;
multi_curve* crv = get_curve (name);
if (crv) {
string what;
int id;
string sx, sy;
tz >> what >> id >> sx >> sy;
float x, y, xs = (float) atof (sx.c_str()), ys = (float) atof (sy.c_str());
if (what == "v") {
crv->get_vertex (id, x, y);
if (sx == ".") crv->set_vertex (id, x, ys); else
if (sy == ".") crv->set_vertex (id, xs, y); else
crv->set_vertex (id, xs, ys);
crv->evaluate ();
return 1;
} else if (what == "lt") {
crv->get_left_tangent (id, x, y);
if (sx == ".") crv->set_left_tangent (id, x, ys); else
if (sy == ".") crv->set_left_tangent (id, xs, y); else
crv->set_left_tangent (id, xs, ys);
crv->evaluate ();
return 1;
} else if (what == "rt") {
crv->get_right_tangent (id, x, y);
if (sx == ".") crv->set_right_tangent (id, x, ys); else
if (sy == ".") crv->set_right_tangent (id, xs, y); else
crv->set_right_tangent (id, xs, ys);
crv->evaluate ();
return 1;
} else {
result = "bad target: must be v lt OR rt";
return 0;
}
}
result = "curve " + name + " not found";
return 0;
}
int curve_name::operator() (tokenizer& tz) {
curve_editor* ced = uis.crved;
if (ced && ced->pik()) {
multi_curve* crv = ced->curveinfo[ced->pik.crv_id].curve;
string name; tz >> name;
if (name != "") crv->name = name;
}
return 1;
}
int curve__library::operator() (tokenizer& tz) {
curve_editor* ced = uis.crved;
if (!ced) {
result = "not a curve editor";
return 0;
}
curve_library* cl = ced->library;
if (cl) {
string cmd; tz >> cmd;
if (cmd == "a" || cmd == "add") ced->add_curve (); else
if (cmd == "d" || cmd == "delete") cl->del (); else
if (cmd == "u" || cmd == "update") ced->replace_curve (); else
if (cmd == "i" || cmd == "insert") ced->insert_curve (); else
if (cmd == "+") {int n; tz >> n; cl->move (n);}
else if (cmd == "-") {int n; tz >> n; cl->move (-n);}
else if (cmd == "n" || cmd == "next") {
ced->load_curve (+1);
} else if (cmd == "p" || cmd == "prev") {
ced->load_curve (-1);
}
else {
result = "bad sub-command. see help curve-library";
return 0;
}
} else {
result = "no curve library";
return 0;
}
return 1;
}
int set_curve_editor::operator() (tokenizer& tz) {
string name;
int screen;
tz >> name >> screen;
if (uis.set_editor (name, screen)) {
stringstream ss;
ss << "update-editor " << name << spc << screen;
interpreter (ss.str());
}
return 1;
}
extern oscilloscope scope;
int set_scope::operator() (tokenizer& tz) {
string name, color; tz >> name >> color;
float r, g, b; stringstream ss (color); ss >> r >> g >> b;
if (name == "left" || name == "l") {
scope.lr = r;
scope.lg = g;
scope.lb = b;
return 1;
} else if (name == "right" || name == "r") {
scope.rr = r;
scope.rg = g;
scope.rb = b;
return 1;
} else return 0;
}
int get_scope::operator() (tokenizer& tz) {
string name; tz >> name;
if (name == "left" || name == "l") {
sprintf (BUFFER, "%f %f %f", scope.lr, scope.lg, scope.lb);
result = BUFFER;
return 1;
} else if (name == "right" || name == "r") {
sprintf (BUFFER, "%f %f %f", scope.rr, scope.rg, scope.rb);
result = BUFFER;
return 1;
} else return 0;
}
int set_drone::operator() (tokenizer& tz) {
string param; tz >> param;
if (param == "volume" || param == "v") {
vector<int> ids;
vector<float> vols;
string s;
tz >> s; if (s != "") load_vector_from_string (s, ids); else return 0;
tz >> s; if (s != "") load_vector_from_string (s, vols); else return 0;
float v = 0;
for (int i = 0, j = ids.size(), m = vols.size (); i < j; ++i) {
int k = ids[i];
if (i < m) v = vols[i];
d.set_drone_volume (k, v);
}
return 1;
} else {
result = "bad param";
return 0;
}
}
int get_drone::operator() (tokenizer& tz) {
int num_drones = d.drones.size ();
string param; tz >> param;
if (param == "n" || param == "num_drones") {
sprintf (BUFFER, "%d", num_drones);
result = BUFFER;
return 1;
} else if (param == "volume" || param == "v") {
stringstream ss;
string s; tz >> s;
if (s != "") {
vector<int> ids; load_vector_from_string (s, ids);
for (int i = 0, j = ids.size (); i < j; ++i) {
int id = ids[i];
drone* pd = d.get_drone (id);
if (pd) ss << pd->vol << spc; else ss << "0 ";
}
result = ss.str ();
return 1;
} else return 0;
} else if (param == "selected" || param == "s") {
result = d.get_selected_drones ();
return 1;
}
return 0;
}
int set_text_color::operator() (tokenizer& tz) {
tz >> cons.clr.r >> cons.clr.g >> cons.clr.b;
return 1;
}
int paste_gater::operator() (tokenizer& tz) {
int clr; tz >> clr;
if (curve_editor::copy.num_vertices) {
extern din din0;
float r, g, b;
din0.gatr.crv->get_color (r, g, b);
*din0.gatr.crv = curve_editor::copy;
din0.gatr.crv->set_color (r, g, b);
din0.gatr.sol.update ();
if (clr) curve_editor::copy.clear ();
}
return 1;
}
int get_selection::operator () (tokenizer& tz) {
extern ui_list uis;
if (uis.crved) result = uis.crved -> selection ();
return 1;
}
int get_intervals::operator() (tokenizer& tz) {
string what; tz >> what;
stringstream ss;
if (what == "piano") {
for (int i = 0, j = NUM_NOTES - 1; i < j; ++i) {
ss << WESTERN_FLAT[i] << spc << WIKIPEDIA_KEY_FREQUENCIES[i] << spc;
}
result = ss.str ();
} else {
for (map<string, float>::iterator i = INTERVALS.begin (), j = INTERVALS.end (); i != j; ++i) {
const pair<string, float>& p = *i;
ss << p.first << spc << p.second << spc;
}
}
result = ss.str ();
return 1;
}
#define DONTLOADFROMDISK 0
int num_octaves::operator() (tokenizer& tz) {
int lno = NUM_OCTAVES;
tz >> NUM_OCTAVES;
if (NUM_OCTAVES < 1) NUM_OCTAVES = 1;
d.setup_ranges (lno, DONTLOADFROMDISK);
if (NUM_OCTAVES < lno) d.update_drone_ranges ();
d.refresh_all_drones ();
return 1;
}
int set_audio::operator() (tokenizer& tz) {
string varn;
int cd = aout.current_device, sr = aout.sample_rate, spc = aout.samples_per_channel;
int got = 0;
while (1) {
tz >> varn;
if (varn == "device" || varn == "d") {
tz >> cd;
got = 1;
} else if (varn == "sample_rate" || varn == "sr") {
tz >> sr;
got = 2;
} else if (varn == "samples_per_channel" || varn == "spc") {
tz >> spc;
got = 3;
} else break;
}
if (got != 0) {
aout.close ();
int opened = aout.open (cd, sr, spc);
if (opened) {
//--cons;
switch (got) {
case 1:
case 2:
din0.sample_rate_changed ();
keybd2.setup_notes(0);
binaural_drones0.vol_fader.set_duration (MENU.lf_vol_fade_time.fld);
uis.settings_scr.sample_rate_changed ();
break;
case 3:
din0.samples_per_channel_changed ();
update_triggered_notes (keybd2.triggered_notes);
update_triggered_notes (mondrian0.triggered_notes);
break;
}
//++cons;
aout.start ();
return 1;
}
} else {
aout.list ();
}
return 0;
}
int list_midi::operator() (tokenizer& tz) {
return 1;
}
int set_midi::operator() (tokenizer& tz) {
int port; tz >> port;
return 1;
}
int scale_curve::operator() (tokenizer& tz) {
if (uis.crved) {
float sx, sy;
tz >> sx >> sy;
uis.crved->scale (sx, sy);
}
return 1;
}
#ifdef __SVG__
int write_svg::operator() (tokenizer& tz) {
float h, t, left, top;
string fn;
if (uis.crved) {
tz >> h >> t >> fn >> left >> top;
uis.crved->write_svg (h, t, fn, left, top);
}
return 1;
}
int write_trail::operator() (tokenizer& tz) {
din0.write_trail ();
return 1;
}
#endif
#ifdef __HPGL__
int write_hpgl::operator() (tokenizer& tz) {
if (uis.crved) {
float scale, penmag;
tz >> scale >> penmag;
if (scale <= 0 || penmag <= 0) {
cons << console::red << "write-hpgl <scale> <pen-switch-mag>" << eol;
return 1;
}
uis.crved->write_hpgl (scale, penmag);
}
return 1;
}
#endif
int cmd_binaural_drone::operator() (tokenizer& tz) {
string cmd; tz >> cmd;
if (cmd == "c" || cmd == "create") {
float l_hz, r_hz, vol, sep;
int just;
tz >> l_hz >> r_hz >> vol >> just >> sep;
int id = binaural_drones0.add (l_hz, r_hz, vol, just, sep);
sprintf (BUFFER, "%d", id);
result = BUFFER;
} else if (cmd == "e" || cmd == "edit") {
int which; tz >> which;
string what; tz >> what;
float value; tz >> value;
int num_binaural_drones = binaural_drones0.binaural_drones.size ();
if (which > -1 && which < num_binaural_drones) {
binaural_drone* bw = binaural_drones0.binaural_drones [which];
if (what == "v" || what == "vol") {
bw->set_vol (value);
binaural_drones0.vol_fader.start ("Volume change");
} else if (what == "l" || what == "left") {
bw->set_hz (binaural_drone::LEFT, value);
binaural_drones0.pitch_fader.start ("Set L Hz");
} else if (what == "r" || what == "right") {
bw->set_hz (binaural_drone::RIGHT, value);
binaural_drones0.pitch_fader.start ("Set R Hz");
} else if (what == "b" || what == "both") {
float value2; tz >> value2;
bw->set_hz (binaural_drone::LEFT, value);
bw->set_hz (binaural_drone::RIGHT, value2);
binaural_drones0.pitch_fader.start ("Set L & R Hz");
} else if (what == "s" || what == "separation") {
bw->set_sep (value);
binaural_drones0.pitch_fader.start ("Separation set");
} else if (what == "m" || what == "modulate") {
bw->set_hz (binaural_drone::LEFT, bw->l_hz * value);
bw->set_hz (binaural_drone::RIGHT, bw->r_hz * value);
binaural_drones0.pitch_fader.start ("Modulation");
}
} else cons << "bad binaural drone id" << eol;
} else if (cmd == "d" || cmd == "delete") {
int which; tz >> which;
binaural_drones0.remove (which);
} else if (cmd == "s" || cmd == "sync") {
int n; tz >> n;
string list; tz >> list;
binaural_drones0.sync (n, list);
} else if (cmd == "n" || cmd == "number") {
stringstream ss; ss << (int)binaural_drones0.binaural_drones.size ();
result = ss.str ();
} else if (cmd == "g" || cmd == "get") {
string what; tz >> what; int w;
if (what == "left") w = binaural_drone::LEFT;
else if (what == "right") w = binaural_drone::RIGHT;
else if (what == "separation") w = binaural_drone::SEPARATION;
else if (what == "volume") w = binaural_drone::VOLUME;
else if (what == "selected_volumes") {
result = binaural_drones0.get_sel_vol ();
return 1;
} else if (what == "selected") {
result = MENU.il_binaural_drones.get_selected ();
return 1;
} else {
cons << RED << "syntax error: please type help binaural-drone for more information" << eol;
return 0;
}
stringstream ss;
for (int i = 0; i < binaural_drones0.num_binaural_drones; ++i) {
binaural_drone* bdi = binaural_drones0.binaural_drones[i];
float whata [] = {bdi->l_hz, bdi->r_hz, bdi->sep, bdi->vol * 100.0f};
ss << whata[w] << spc;
}
result = ss.str ();
} else if (cmd == "update-list" || cmd == "ul" ) {
MENU.update_binaurals_list ();
} else if (cmd == "update-selection" || cmd == "us" ) {
MENU.bdl.selected (MENU.il_binaural_drones, MENU.il_binaural_drones.cur);
} else if (cmd == "l" || cmd == "list") {
binaural_drones0.list ();
}
return 1;
}
int set_sine_mixer::operator() (tokenizer& tz) {
int harmonic;
float value;
tz >> harmonic >> value;
sinemixer.harms.set_only (harmonic, value);
return 1;
}
int change_sine_mixer::operator() (tokenizer& tz) {
int harmonic;
float amount;
tz >> harmonic >> amount;
int res = sinemixer.harms.change (harmonic, amount);
sprintf (BUFFER, "%d", res);
result = BUFFER;
return 1;
}
int update_sine_mixer::operator() (tokenizer& tz) {
sinemixer.harms.update ();
return 1;
}