Rev 337 |
Rev 354 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* main.cc
* DIN Is Noise is copyright (c) 2006-2017 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/
#include <SDL/SDL.h>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <list>
#include <algorithm>
#include <tcl.h>
#include "dingl.h"
#include "main.h"
#include "box.h"
#include "utils.h"
#include "font.h"
#include "ui_list.h"
#include "console.h"
#include "input.h"
#include "viewwin.h"
#include "curve.h"
#include "multi_curve.h"
#include "solver.h"
#include "chrono.h"
#include "curve_editor.h"
#include "font_editor.h"
#include "din.h"
#include "curve_library.h"
#include "console_iterator.h"
#include "delay.h"
#include "random.h"
#include "globals.h"
#include "command.h"
#include "scalelist.h"
#include "morse_code.h"
#include "sine_mixer.h"
#include "tcl_interp.h"
#include "ansi_color_codes.h"
#include "compressor.h"
#include "oscilloscope.h"
#include "keyboard_keyboard.h"
#include "fft.h"
#include "authors_note.h"
#include "midi_in.h"
#include "menu.h"
#include "curve_picker.h"
#include "fractaliser.h"
#include "rose_milker.h"
#include "circler.h"
#include "spiraler.h"
#include "starrer.h"
#include "lissajous.h"
#include "superformula.h"
#include "warper.h"
#include "recorder.h"
#include "mondrian.h"
#include "instrument.h"
#include "countries.h"
#include "morpher.h"
#include "number.h"
#include "sounding_board.h"
using namespace std;
// declare / define all global vars
//
ofstream dlog ("log", ios::out); // log of DIN operation
struct startup_shutdown {
startup_shutdown () {
dlog << "!!! started DIN Is Noise !!!" << endl;
seed_rand_gen (clock());
dlog << "+++ initialised random number generator +++" << endl;
}
~startup_shutdown () {
SDL_Quit ();
dlog << "!!! cleaned up SDL !!!" << endl;
dlog << "*** [Mondrian] box count = " << rect::ref << " ***" << endl;
dlog << "*** [Mondrian] ball count = " << ball::ref << " ***" << endl;
dlog << "*** [Mondrian] slit count = " << slit::ref << " ***" << endl;
dlog << "*** [Microtonal-Keyboard] drone count = " << drone::ref << " ***" << endl;
dlog << "!!! DIN Is Noise has shut down !!!" << endl;
dlog.flush ();
}
} _startup_shutdown;
std::string STRING;
#if defined (__UNIX_JACK__) || defined (__LINUX_ALSA__)
string home = getenv ("HOME");
std::string user_data_dir (home + "/.din/"); // contains defaults, user savings and preferences
std::string country_data_dir (user_data_dir + "country/"); // contains country data used by countries plugin (see countries.cc)
#elif __WINDOWS_DS__
std::string user_data_dir = "user\\";
std::string country_data_dir = "user\\country\\";
#elif __MACOSX_CORE__
std::string user_data_dir = "user/";
std::string country_data_dir = "user/country/";
#endif
tcl_interp interpreter; // integrated TCL interpreter
// din clocks
double TIME_NOW = 0; // time now in seconds on the audio clock stored in variable timenow in Tcl interpreter
audio_clock clk; // audio clock
ui_clock ui_clk; // UI clock
// keyboard and mouse state
keyboard keybd;
int mousex = 0, mousey = 0, mouseyy = 0; // absolute mouse x, y & main viewport y
int lmb = 0, rmb = 0, mmb = 0; // mouse buttons
is_lmb_t is_lmb; // for acquiring lmb
int TURN_OFF_UI = 0;
list<crvpt> LIST_OF_POINTS; // list of points (used by curve.h/cc)
int drone::UID = 0; // unique id for drones
int drone::ref = 0; // for ref counting drones
double drone::LIFE_TIME = 10; // for launched drones (seconds)
double drone::INSERT_TIME = 3; // for launched drones to get into orbit (seconds)
int drone::SNAP_TO_NOTES = 0; // snap drones to notes?
// for trails on drones and mondrian
float* trail_t::tpts = 0;
int trail_t::n_tpts = 0;
int basic_editor::hide_cursor = 0; // to hide cursor when mouse is on a ui control
int plugin::change_curve_name = 1;
int* mesh::gl_pts = 0;
int mesh::n_glpts = 0;
double fader::TIME; // loaded from din_info
float curve_mixer::TIME = 5.0f; // curve (waveform/envelope) mixing time in seconds
double curve_mixer::ELAPSEDT = 0.0;
curve_mixer* curve_mixer::LAST_MIXER = 0;
int curve_mixer::NMIXES = 0;
extern const float GOLDEN_RATIO = 1.618033;
extern const float PI = 3.1415961;
extern const float TWO_PI = 2 * PI;
extern const float PI_BY_180 = PI / 180.;
extern const int MILLION = 1000000;
extern const std::string DEFAULT_DELIMITER = " "; // see tokenizer.h
const char SPC = ' ';
// for sprintf
const int BUFFER_SIZE = 1 << 15;
char BUFFER [BUFFER_SIZE] = {0};
// musical key
//
int NUM_NOTES = 13;
const char* WESTERN_SHARP [] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C"};
const char* WESTERN_FLAT [] = {"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B", "C"};
float WIKIPEDIA_KEY_FREQUENCIES [] = { // for the octave of Middle-C; from wikipedia - piano key frequencies page.
261.626f, 277.183f, 293.665f, 311.127f, 329.628f, 349.228f, 369.994f, 391.995f, 415.305f,
440.0f, 466.164f, 493.883f, 523.251f
};
std::string NOTATION = "western";
string NEAREST_NOTE; // note nearest to key of DIN
float NEAREST_NOTE_DISTANCE; // distance in Hz of the nearest note from the key of DIN
float NEAREST_NOTE_FREQUENCY; // frequency in Hz of the nearest note to the key of DIN
widget* widget::focus = 0; // widget that has focus
widget* widget::next_focus = 0; // widget waiting to have focus
widget* ui_list::mm_last = 0; // last button clicked on the label field sliders (see min_max_clicked below)
const std::string VERSION_NUMBER ("30-WIP");
std::string LOCATION (" @ Chennai, India");
std::string APP_NAME;
void make_app_name () {
#ifdef __EVALUATION__
APP_NAME = "DIN Is Noise " + VERSION_NUMBER + LOCATION + " | EVALUATION VERSION";
#elif defined __LICENSED__
APP_NAME = "DIN Is Noise " + VERSION_NUMBER + LOCATION + " | LICENSED VERSION";
#endif
}
void set_window_caption () {
make_app_name ();
SDL_WM_SetCaption (APP_NAME.c_str(), APP_NAME.c_str());
}
int SCREEN_WIDTH, SCREEN_HEIGHT; // initial screen width & height (from user/globals)
const int SCREEN_DEPTH = 24; // fixed color depth
int FULL_SCREEN = 0; // full screen?
viewport view; // display - using OpenGL
int SAMPLE_RATE; // sample rate of DIN
float SAMPLE_DURATION; // duration of an audio sample in seconds
std::string SCALE; // current scale
int NUM_OCTAVES; // number of octaves in DIN
std::string TUNING; // current tuning
int NUM_INTERVALS; // number of intervals in tuning
std::string INTERVALS_FILE; // file name that contains interval info
std::map <std::string, float> INTERVALS; // interval name -> value
std::vector<std::string> INTERVAL_NAMES; // sequential interval names (eg., 1 2b 2 3b 3 ... 7b 7 8)
std::vector<float> INTERVAL_VALUES; // sequential interval values (eg., value of 1 2b 3 3b ... 7b 7 8)
std::map <std::string, int> NOTE_POS; // interval name -> note number (eg., 1 => 0, 2b => 1, 3 => 2, etc)
// for microtonal keyboard
//
int LEFT = 0, BOTTOM, RIGHT, TOP, HEIGHT; // absolute extents
float BOTTOM01, HEIGHT01; // as proportion of window height
int NUM_MICROTONES; // number of microtones in a range
int NUM_VOLUMES, LAST_VOLUME; // number of volume levels
float DELTA_VOLUME; // change in volume every pixel of board height
int TRAIL_LENGTH = 1; // default drone trail length (== number of trail points)
int DRONE_HANDLE_SIZE; // default drone handle size
float DELTA_DRONE_MASTER_VOLUME; // change in drone master volume
float PHRASE_TEMPO = 1.0; // playback recorded phrase at recorded speed
int FPS = 0; // frames per second, wanted
double TIME_PER_FRAME; // in seconds
int GOT_FPS = 0; // got
int IPS; // keyboard/mouse inputs per second
double TIME_PER_INPUT; // in seconds
int PITCH_BEND; // in Hz; used for pitch bending notes on keyboard-keyboard
float PITCH_BEND_PER_PIXEL;
// see curve_samples in curve_editor.h
float HZ;
float curve_samples::dm = 0.0f;
float curve_samples::nsec = 2.0f;
// screens - 1 is instrument; 2 - 8 are editors
//
const Uint8 ui_list::key [] = {SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8}; // keys 2 - 8
ui* ui_list::ed [] = {0};
// solver xhandlers; see solver.cc
atmin _atmin;
atmax _atmax;
tomin _tomin;
loopmin _loopmin;
loopmax _loopmax;
pongmin _pongmin;
pongmax _pongmax;
// see multi_curve.cc
multi_curve curve_editor::copy;
multi_curve mix;
// 0 init correct for oscilloscope; see oscilloscope.cc
float oscilloscope::sample_t::lmin = 0, oscilloscope::sample_t::lmax = 0;
float oscilloscope::sample_t::rmin = 0, oscilloscope::sample_t::rmax = 0;
oscilloscope scope ("scope.osc");
// see range.cc
int range::char_height, range::ybot1, range::ybot2, range::ytop1, range::ytop2;
// see sine_mixer.cc
int sine_mixer::NUM_SINE_SAMPLES = 100;
const int sine_mixer::MIN_SINE_SAMPLES = 4;
// see viewwin.cc
int viewport::handle_radius = 50;
float viewport::handle_factor = 0.0f;
int window::PAN_RATE = 100, window::ZOOM_RATE = 100;
double window::PAN_REPEAT = 1.0 / PAN_RATE, window::ZOOM_REPEAT = 1.0 / ZOOM_RATE;
float window::PAN_AMOUNT = 0.1f, window::ZOOM_AMOUNT = 0.1f;
// load initial globals
load_globals lg;
// custom vector font
#ifdef __SVG_OUT__
font fnt ("laser.fnt");
#elif __PLOTTER_OUT__
font fnt ("plotter.fnt");
#else
font fnt ("jag.fnt");
#endif
// console
// possible text colors of console
const float cc = 0.55f;
const color console::yellow (1, 1, cc);
const color console::green (cc, 1, cc);
const color console::red (1, cc, cc);
const color console::cyan (cc, 1, 1);
const color console::white (1, 1, 1);
string CHARSET [] = { // list of input chars
// default is US layout
"abcdefghijklmnopqrstuvwxyz0123456789 .=-/;\\,[]'`", // normal
"ABCDEFGHIJKLMNOPQRSTUVWXYZ)!@#$%^&*( >+_?:|<{}\"~", // shift
};
const int CHARSET_LENGTH = CHARSET[0].length ();
console cons;
char get_typed_char () { // get char typed on an input area
const string& norm = CHARSET[0];
const string& shift = CHARSET[1];
for (int i = 0; i < CHARSET_LENGTH; ++i) {
if (keypressedd (norm[i])) {
if (shift_down() || keydown (SDLK_CAPSLOCK))
return shift[i];
else
return norm[i];
}
}
return 0;
}
// audio output
//
audio_out aout;
// list of scales
scalelist scalelst;
//
// L and R delays
//
delay left_delay (1000, "feedback-l.crv", "volume-l.crv"), right_delay (1000, "feedback-r.crv", "volume-r.crv");
curve_editor delayed ("delay.ed");
// vars in Tcl interpreter
//
// midi bpm from external midi clock
double MIDI_BPM = 0;
// tap bpm from computer keyboard
double TAP_BPM = 0;
// din board height (0 to 1)
float VOLUME = 0;
fft fft0; // FFT of waveform in waveform editors
cmdlist cmdlst; // list of din commands
// 1 oscillator / waveform for lead
//
float VOICE_VOLUME = 0.15f;
//
// curve libraries
//
curve_library wav_lib ("waveforms.lib"); // waveforms
curve_library sin_lib ("sin.lib"); // custom sine curves
curve_library cos_lib ("cos.lib"); // custom cosine curves
curve_library attack_lib ("attack.lib", 1); // attack curves [1 = has_sustain]
curve_library decay_lib ("decay.lib"); // decay curves
// compressor
compressor coml ("coml.crv"), comr ("comr.crv");
curve_editor comed ("compressor.ed");
// octave shift
//
beat2value octave_shift ("os", "octave-shift.crv");
curve_editor octed ("octave-shift.ed");
curve_library octlib ("octave-shift-patterns.lib");
beat2value_listener octlis;
// drone modulation
//
beat2value drone_modulation::am_crv ("drone AM", "dam.crv");
beat2value drone_modulation::fm_crv ("drone FM", "dfm.crv");
curve_editor dmod_ed ("drone-modulation.ed");
beat2value_listener damlis, dfmlis;
recorder recorder0; // for recording sounds made in DIN
// microtonal-keyboard see din.cc/.h
//
din din0 (cmdlst);
// mondrian (see mondrian.cc/h)
//
rnd<float> rect::rd (0.0f, 1.0f); // to make box color
int rect::ref = 0, ball::ref = 0, slit::ref = 0;
const int mondrian::gutter = 2;
const int mondrian::gutter2 = mondrian::gutter * mondrian::gutter;
float mondrian::min_split_size = 32;
float slit::HALF_SIZE = 20;
float slit::MIN_HALF_SIZE = 1;
float slit::MIN_SIZE = 2 * slit::MIN_HALF_SIZE;
const char* ball::types_str [3] = {"bouncer", "wrecker", "healer"};
float ball::recent_attack_time = 0.01f; // secs
float ball::recent_decay_time = 2.0f; // secs
float ball::recent_pitch_mult = 1.0f; // modulation
const char* mondrian_listener::split_types [3] = {" into 2 boxes", " at notes", " into N boxes"};
const char* mondrian_listener::selection_targets [2] = {"Selection target = slits", "Selection target = balls"};
const double slit::INITIAL_OPEN_CLOSE_TIME = 2.0;
mondrian mondrian0;
// sounding board (see sounding_board.cc/h)
//
sounding_board sounding_board0;
int sounder::NUM_FADERS = 0;
//wavdoh wavdoh0;
gotog _gotomax (1, &mondrian0.attacked);
// keyboard-keyboard
//
float NOTE_VOLUME = 0.75f * VOICE_VOLUME;
// in secs
float ATTACK_TIME = 0.05f;
float DECAY_TIME = 5.0f;
float DELTA_TIME = 0.025f;
color keyboard_keyboard::note_color[2]; // midi keybd note color
const int keyboard_keyboard::color_index [] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0}; // 0 - white, 1 - black; 1 octave
keyboard_keyboard keybd2;
gotog _gotog (1, &keybd2.attacked); // default sustain (see keyboard-keyboard.cc)
// available instruments
const char* INSTRUMENTS [] = {"keyboard_keyboard", "microtonal_keyboard", "mondrian", "sounding_board"};
const char* INSTRUMENTS_SHORT [] = {"kkb", "mkb", "mon", "sbd"};
int CURRENT_INSTRUMENT = 0;
extern const int NUM_INSTRUMENTS = 4;
std::string INSTRUMENT = INSTRUMENTS [CURRENT_INSTRUMENT];
instrument* INSTRUMENT_PTR [] = {&keybd2, &din0, &mondrian0, &sounding_board0};
checkbutton* LAST_TABS [NUM_INSTRUMENTS] = {0, 0, 0, 0};
box_selector mkb_selector; // selector for microtonal keyboard
box_selector mon_selector; // selector for mondrian
std::string style_listener::styles [] = {"loop", "pong"};
std::vector<multi_curve*> curve_list;
void setup_curve_list () {
multi_curve* lst [] = {
&din0.wave,
&keybd2.wave,
&din0.fm.crv,
&din0.am.crv,
&din0.gatr.crv,
&octave_shift.crv,
&din0.drone_wave,
&left_delay.fbk_crv,
&left_delay.vol_crv,
&right_delay.fbk_crv,
&right_delay.vol_crv
};
for (int i = 0; i < 11; ++i) curve_list.push_back (lst[i]);
}
const char* bpm_com::str [bpm_com::NUM] = {"os", "gr", "am", "fm"};
beat2value* bpm_com::bv [] = {&octave_shift, &din0.gatr, &din0.am, &din0.fm};
#define DEFINE_TCL_FUNC(X) inline int (X) (ClientData cd, Tcl_Interp* ti, int objc, Tcl_Obj* CONST objv[]) { return tcl_run (cd, ti, objc, objv);}
DEFINE_TCL_FUNC(tcl_key)
DEFINE_TCL_FUNC(tcl_setv)
DEFINE_TCL_FUNC(tcl_getv)
DEFINE_TCL_FUNC(tcl_set_delay)
DEFINE_TCL_FUNC(tcl_get_delay)
DEFINE_TCL_FUNC(tcl_set_bpm)
DEFINE_TCL_FUNC(tcl_get_bpm)
DEFINE_TCL_FUNC (tcl_set_beat);
DEFINE_TCL_FUNC (tcl_get_beat);
DEFINE_TCL_FUNC(tcl_set_style)
DEFINE_TCL_FUNC(tcl_get_style)
DEFINE_TCL_FUNC(tcl_set_kern)
DEFINE_TCL_FUNC(tcl_get_kern)
DEFINE_TCL_FUNC(tcl_set_font_size)
DEFINE_TCL_FUNC(tcl_get_font_size)
DEFINE_TCL_FUNC(tcl_note_distance)
DEFINE_TCL_FUNC(tcl_chord)
DEFINE_TCL_FUNC(tcl_notation)
DEFINE_TCL_FUNC(tcl_echo)
DEFINE_TCL_FUNC(tcl_curve_value)
DEFINE_TCL_FUNC(tcl_curve_name)
DEFINE_TCL_FUNC(tcl_curve_library)
DEFINE_TCL_FUNC(tcl_morse_code)
DEFINE_TCL_FUNC (tcl_set_editor);
DEFINE_TCL_FUNC (tcl_set_kb_layout);
DEFINE_TCL_FUNC (tcl_set_scope);
DEFINE_TCL_FUNC (tcl_get_scope);
DEFINE_TCL_FUNC (tcl_get_drone);
DEFINE_TCL_FUNC (tcl_set_drone);
DEFINE_TCL_FUNC (tcl_text_color);
DEFINE_TCL_FUNC (tcl_paste_gater);
DEFINE_TCL_FUNC (tcl_get_intervals);
DEFINE_TCL_FUNC (tcl_num_octaves);
DEFINE_TCL_FUNC (tcl_set_audio);
DEFINE_TCL_FUNC (tcl_load_scale);
DEFINE_TCL_FUNC (tcl_scale_curve);
DEFINE_TCL_FUNC (tcl_sounder);
DEFINE_TCL_FUNC (tcl_set_sine_mixer);
DEFINE_TCL_FUNC (tcl_change_sine_mixer);
DEFINE_TCL_FUNC (tcl_update_sine_mixer);
/*DEFINE_TCL_FUNC (tcl_write_svg);
DEFINE_TCL_FUNC (tcl_write_hpgl);*/
// din commands
//
// format: long name, short name
// for L and R delays
set_delay sd (&left_delay, &right_delay, "set-delay", "sd");
get_delay gd (&left_delay, &right_delay, "get-delay", "gd");
// to load the scale
load_scale los (&din0, "load-scale", "los");
// set and get din variables
set_var sv (&din0, "set-var", "sv");
get_var gv (&din0, "get-var", "gv");
// bpm commands
//
set_bpm sb ("set-bpm", "sb");
get_bpm gb ("get-bpm", "gb");
set_beat sn ("set-beat", "sbt");
get_beat gn ("get-beat", "gbt");
set_style ss ("set-style", "ss");
get_style gs ("get-style", "gs");
// set key/tonic
key ky (&din0, "key", "key");
// display notation on the keyboard
notation no (&din0, "notation", "no");
// music utils
note_distance nd ("note-distance", "nd");
chord ch ("chord", "ch");
// font cmds
set_font_size sfs ("set-font-size", "sfs");
get_font_size gfs ("get-font-size", "gfs");
set_kern sk ("set-kern", "sk");
get_kern gk ("get-kern", "gk");
// curve cmds
curve_name cn ("curve-name", "cn");
curve_value cv ("curve-value", "cv");
curve__library cl ("curve-library", "cl");
set_curve_editor sced ("set-curve-editor", "sced");
paste_gater pasg ("paste-gater", "paste-gater");
scale_curve scrv ("scale-curve", "scrv");
// morse code
morse_code mc ("morse-code", "mc");
// to replace curves in a multi curve with a seed curve
fractaliser fractaliser_;
// to generate curve from polar equation R = sin (K * theta)
rose_milker rosemilker;
// to generate a regular polygon
circler circler_;
// to generate a spiral with R = A * theta
spiraler spiraler_;
// to connect dots to make star polygons
starrer starrer_;
// to generate lissajous curve
lissajous lissajous_;
// to generate superformula curve
superformula superformula_;
// to warp XY of segments of a curve
warper warper_;
// to turn country outlines into curves
countries countries_;
// to morph one curve into another
morpher morpher_;
// to convert a number into a curve
number number_;
// sine mixer for waveform edit
sine_mixer sinemixer;
// unix like echo
echo ech ("echo", "eo");
set_kb_layout kbl ("set-kb-layout", "kbl");
// oscilloscope
set_scope ssco ("set-scope", "ssco", &din0, &sounding_board0);
get_scope gsco ("get-scope", "gsco", &din0);
// drone
get_drone gdro ("get-drone", "gdro", din0);
set_drone sdro ("set-drone", "sdro", din0);
// console
set_text_color stc ("set-text-color", "stc");
// get scale intervals
get_intervals gint ("get-intervals", "gint");
// set number of octaves
num_octaves noct ("num-octaves", "noct", din0);
// set audio
set_audio sau ("set-audio", "sa");
#ifdef __SVG__
// write curve into svg file
write_svg wsvg ("write-svg", "wsvg");
#endif
#ifdef __HPGL__
// write curve into hp-gl file for output on graphtec plotters
write_hpgl whpgl ("write-hpgl", "hpgl");
#endif
// used by binaural drones instrument
cmd_sounder snd ("sounder", "snd");
set_sine_mixer ssm ("set-sine-mixer", "ssm");
change_sine_mixer csm ("change-sine-mixer", "csm");
update_sine_mixer usm ("update-sine-mixer", "usm");
void add_commands (Tcl_Interp* interp) { // add din commands to Tcl interpreter
unsigned int ncmds = 40; // +2 for write-svg, write-hpgl if included
tclcmd cmd_funcs [] = {
tcl_key,
tcl_setv,
tcl_getv,
tcl_set_delay,
tcl_get_delay,
tcl_set_bpm,
tcl_get_bpm,
tcl_set_beat,
tcl_get_beat,
tcl_set_style,
tcl_get_style,
tcl_set_kern,
tcl_get_kern,
tcl_set_font_size,
tcl_get_font_size,
tcl_note_distance,
tcl_chord,
tcl_notation,
tcl_echo,
tcl_curve_value,
tcl_curve_name,
tcl_curve_library,
tcl_morse_code,
tcl_set_editor,
tcl_set_scope,
tcl_get_scope,
tcl_get_drone,
tcl_set_drone,
tcl_text_color,
tcl_paste_gater,
tcl_get_intervals,
tcl_num_octaves,
tcl_set_kb_layout,
tcl_set_audio,
tcl_load_scale,
tcl_scale_curve,
tcl_sounder,
tcl_set_sine_mixer,
tcl_change_sine_mixer,
tcl_update_sine_mixer,
/*tcl_write_svg,
tcl_write_hpgl,*/
};
command* cmds [] = {
&ky,
&sv,
&gv,
&sd,
&gd,
&sb,
&gb,
&sn,
&gn,
&ss,
&gs,
&sk,
&gk,
&sfs,
&gfs,
&nd,
&ch,
&no,
&ech,
&cv,
&cn,
&cl,
&mc,
&sced,
&ssco,
&gsco,
&gdro,
&sdro,
&stc,
&pasg,
&gint,
&noct,
&kbl,
&sau,
&los,
&scrv,
&snd,
&ssm,
&csm,
&usm,
/*
&wsvg,
&whpgl,*/
};
extern cmdlist cmdlst;
for (unsigned int i = 0; i < ncmds; ++i) {
command* cmdp = cmds [i];
cmdlst.add (cmdp);
Tcl_CreateObjCommand (interp, cmdp->longname.c_str(), cmd_funcs[i], (ClientData) i, 0);
Tcl_CreateObjCommand (interp, cmdp->shortname.c_str(), cmd_funcs[i], (ClientData) i, 0);
}
dlog << "+++ added " << ncmds << " din commands to the Tcl interpreter +++" << endl;
}
authors_note anote;
curve_picker_t curve_picker;
mouse_slider mouse_slider0;
ui_list uis;
void modulate_down () {
instrument* instr = get_current_instrument ();
if (instr->osd.active == 0) {
static const std::string down = "down";
start_octave_shift (instr, 0, down);
}
}
void modulate_up () {
instrument* instr = get_current_instrument ();
if (instr->osd.active == 0) {
static const std::string up = "up";
start_octave_shift (instr, 1, up);
}
}
void start_octave_shift (instrument* instr, int idir, const std::string& sdir) {
octave_shift_data& osd = instr->osd;
osd.tonic = instr->scaleinfo.tonic;
osd.dir = idir;
osd.active = 1;
osd.now = octave_shift.sol.firstx;
}
void do_octave_shift () {
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
instrument* instr = INSTRUMENT_PTR [i];
octave_shift_data& osd = instr->osd;
if (osd.active) {
osd.now += (octave_shift.delta * aout.samples_per_channel);
static const std::string octave_shift_str = "Octave Shift ", percent = "%";
float now = osd.now - octave_shift.sol.firstx;
float delta = octave_shift.sol.lastx - octave_shift.sol.firstx;
osd.percent_complete = (int) (now / delta * 100);
stringstream ss; ss << octave_shift_str << osd.percent_complete << percent;
string txt (ss.str());
uis.main_menu.l_octave_shift.set_text (txt);
uis.l_octave_shift.set_text (txt);
if (osd.now > octave_shift.sol.lastx) { // finished
osd.now = octave_shift.sol.lastx;
osd.active = 0;
uis.main_menu.l_octave_shift.set_text (octave_shift_str);
uis.l_octave_shift.set_text (octave_shift_str);
}
float shift = octave_shift.sol (osd.now);
if (shift != 0) {
if (osd.dir) set_tonic (instr, osd.tonic * shift); // go up
else set_tonic (instr, osd.tonic / shift); // go down
}
if (!osd.active) cons ("key");
}
}
}
void setup_screens () {
dlog << "*** setting up screens ***" << endl;
left_delay.setup ();
right_delay.setup ();
coml.apply (&coml.crv);
comr.apply (&comr.crv);
plugin* pgns [] = {&fractaliser_, &rosemilker, &circler_, &spiraler_, &starrer_, &lissajous_, &superformula_, &warper_, &countries_, &sinemixer, &morpher_, &number_};
for (int i = 0, j = 12; i < j; ++i) {dlog << "*** setting up plugin: " << pgns[i]->name; pgns[i]->setup (); dlog << " +++" << endl;}
uis.add_widgets ();
uis.setup ();
curve_picker.setup ();
fft0.setup ();
din0.setup ();
keybd2.setup ();
mondrian0.setup ();
// in delay editor load feedback & volume curves
delayed.add (&left_delay.fbk_crv, &left_delay.fbk_lis);
delayed.add (&left_delay.vol_crv, &left_delay.vol_lis);
delayed.add (&right_delay.fbk_crv, &right_delay.fbk_lis);
delayed.add (&right_delay.vol_crv, &right_delay.vol_lis);
// add L & R compressor curves to compressor editor
comed.add (&coml.crv, &coml.lis);
comed.add (&comr.crv, &comr.lis);
// octave shift
octave_shift.setup ();
octlis.set (&octave_shift);
octave_shift.xmin = &_atmin;
octave_shift.xmax = &_atmax;
octed.add (&octave_shift.crv, &octlis);
octed.attach_library (&octlib);
// drone modulation
damlis.set (&drone_modulation::am_crv);
dfmlis.set (&drone_modulation::fm_crv);
dmod_ed.add (&drone_modulation::am_crv.crv, &damlis);
dmod_ed.add (&drone_modulation::fm_crv.crv, &dfmlis);
dmod_ed.attach_library (&wav_lib);
drone_modulation::am_crv.setup ();
drone_modulation::fm_crv.setup ();
dlog << "+++ setup screens complete +++" << endl;
}
void setup_plugin_labels () {
fractaliser_.b_edit.set_label ("Edit");
warper_.b_edit.set_label ("Edit");
}
void load_instrument () {
ui* inst = 0;
int dont_call_listener = 0;
scope.load_current_instrument ();
uis.main_menu.b_microtonal_keyboard.turn_off (dont_call_listener);
uis.main_menu.b_keyboard_keyboard.turn_off (dont_call_listener);
uis.main_menu.b_mondrian.turn_off (dont_call_listener);
uis.main_menu.b_binaural_drones.turn_off (dont_call_listener);
if (INSTRUMENT == "keyboard_keyboard") {
inst = &keybd2;
uis.main_menu.b_keyboard_keyboard.turn_on ();
uis.main_menu.cb_instrument.turn_on ();
} else if (INSTRUMENT == "microtonal_keyboard") {
inst = &din0;
uis.main_menu.b_microtonal_keyboard.turn_on ();
checkbutton* pcb = LAST_TABS [CURRENT_INSTRUMENT];
if (pcb) uis.main_menu.changed (*pcb); else uis.main_menu.changed (uis.main_menu.cb_mkb_voice);
} else if (INSTRUMENT == "mondrian") {
inst = &mondrian0;
uis.main_menu.b_mondrian.turn_on ();
uis.main_menu.cb_instrument.turn_on ();
checkbutton* pcb = LAST_TABS [CURRENT_INSTRUMENT];
if (pcb) uis.main_menu.changed (*pcb); else uis.main_menu.changed (uis.main_menu.cb_mon_tools);
} else {
inst = &sounding_board0;
uis.main_menu.b_binaural_drones.turn_on ();
uis.main_menu.cb_instrument.turn_on ();
checkbutton* pcb = LAST_TABS [CURRENT_INSTRUMENT];
if (pcb) uis.main_menu.changed (*pcb); else uis.main_menu.changed (uis.main_menu.cb_sounding_board_tools);
}
uis.set_current (inst);
uis.main_menu.hide_editors ();
uis.main_menu.show_editors (inst);
if (inst != &anote) uis.main_menu.setup_tabs (inst);
setup_plugin_labels ();
cons ("setup-editors");
uis.update_bottom_line ();
}
void goto_next_instrument () {
scope.save_current_instrument ();
++CURRENT_INSTRUMENT;
if (CURRENT_INSTRUMENT >= NUM_INSTRUMENTS) CURRENT_INSTRUMENT = 0;
INSTRUMENT = INSTRUMENTS [CURRENT_INSTRUMENT];
}
void find_instrument () {
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
if (INSTRUMENT == INSTRUMENTS[i]) {
CURRENT_INSTRUMENT = i;
break;
}
}
}
int is_instrument (ui* u) {
for (int i = 0; i < NUM_INSTRUMENTS; ++i) if ((void *) u == (void *) INSTRUMENT_PTR) return 1;
return 0;
}
instrument* find_instrument (const string& inst) {
for (int i = 0; i < NUM_INSTRUMENTS; ++i) if (inst == INSTRUMENTS[i] || inst == INSTRUMENTS_SHORT[i]) return INSTRUMENT_PTR[i];
return get_current_instrument ();
}
instrument* get_current_instrument () {
return INSTRUMENT_PTR [CURRENT_INSTRUMENT];
}
void update_window (int wnow, int hnow, int wprev, int hprev) { // called when main window resized
glViewport (0, 0, wnow, hnow);
view (wnow, hnow);
curve_picker.update ();
plugin* pgns [] = {&fractaliser_, &rosemilker, &circler_, &spiraler_, &starrer_, &lissajous_, &superformula_, &warper_, &countries_, &sinemixer, &morpher_, &number_};
for (int i = 0, j = 12; i < j; ++i) pgns[i]->update ();
fft0.update ();
int wx = wnow - 1, hy = hnow - 1;
cons.set_window (box<int>(0, 0, wx, hy));
din0.win (din0.win.left, din0.win.bottom, din0.win.left + wx, din0.win.bottom + hy);
HEIGHT = HEIGHT01 * view.ymax;
din0.board_height_changed ();
int quiet = 1;
din0.clear_all_phrases (quiet);
uis.update_widgets (wnow, hnow, wprev, hprev);
keybd2.calc_visual_params ();
if (uis.crved) uis.crved->calc_visual_params ();
if (uis.current == &din0) {
if (FULL_SCREEN) warp_mouse (0, view.ymax);
din0.prev_mousex = mousex;
din0.prev_mousey = mousey;
din0.find_current_range ();
}
mondrian0.calc_visual_params ();
}
void setup_sdl_surface (SDL_Surface* surface, int w, int h, int fs = 0) {
if (surface) SDL_FreeSurface (surface);
if (fs)
surface = SDL_SetVideoMode (w, h, SCREEN_DEPTH, SDL_OPENGL | SDL_FULLSCREEN);
else {
char* sdl_pos = (char *) "SDL_VIDEO_CENTERED=center";
SDL_putenv (sdl_pos);
surface = SDL_SetVideoMode (w, h, SCREEN_DEPTH, SDL_OPENGL | SDL_RESIZABLE);
}
if (surface) dlog << "+++ setup video mode " << w << ' ' << h << ' ' << SCREEN_DEPTH << " +++" << endl; else {
dlog << "!!! couldnt set video mode: " << w << ' ' << h << ' ' << SCREEN_DEPTH << endl;
exit (1);
}
}
void save_window () {
std::string fname = user_data_dir + "window";
ofstream file (fname.c_str(), ios::out);
extern viewport view;
if (file) {
file << "view_width " << view.width << eol;
file << "view_height " << view.height << eol;
file << "full_screen " << FULL_SCREEN << eol;
file << "mode " << uis.settings_scr.imode << eol;
file << "win_left " << din0.win.left << eol;
file << "win_bottom " << din0.win.bottom << eol;
} else {
dlog << "!!! couldnt save window in " << fname << " !!!" << endl;
return;
}
dlog << "+++ saved window in " << fname << " +++" << endl;
}
void restore_last_window () {
dlog << "*** reading last window ***" << endl;
int width = 0, height = 0;
std::string fname (user_data_dir + "window");
ifstream file (fname.c_str(), ios::in);
std::string ignore;
// last window size
file >> ignore >> width;
file >> ignore >> height;
file >> ignore >> FULL_SCREEN;
file >> ignore >> uis.settings_scr.imode;
if (FULL_SCREEN == 0) {
uis.settings_scr.add_display_mode (width, height);
uis.settings_scr.imode = uis.settings_scr.num_modes - 1;
} else
uis.settings_scr.add_display_mode (800, 600); // one windowed mode for sanity
// last microtonal board position
file >> ignore >> din0.win.left;
file >> ignore >> din0.win.bottom;
view (width, height);
din0.prev_mousey = view.ymax;
}
SDL_Surface* surface = 0;
struct dialog_pos {
// dialogs
point<int> dx_plugin_browser;
point<int> dx_fft;
point<int> dx_parameters;
void note_position_of_dialogs () {
point<int>* dp[] = {&dx_plugin_browser, &dx_fft, &dx_parameters};
label* lbl [] = {&uis.plugin__browser.l_title, &fft0.l_title, &uis.d_parameters};
for (int i = 0; i < 3; ++i) {
label* li = lbl[i];
point<int>* dpi = dp[i];
dpi->x = view.xmax - li->posx;
dpi->y = view.ymax - li->posy;
}
}
void reposition_dialogs () {
point<int>* dp[] = {&dx_plugin_browser, &dx_fft, &dx_parameters};
label* lbl [] = {&uis.plugin__browser.l_title, &fft0.l_title, &uis.d_parameters};
for (int i = 0; i < 3; ++i) {
label* li = lbl[i];
point<int>* dpi = dp[i];
li->move (view.xmax - dpi->x - li->posx, view.ymax - dpi->y - li->posy);
}
}
};
void setup_video_mode (int w, int h, int vw, int vh, int fs) {
dialog_pos dp; dp.note_position_of_dialogs ();
setup_sdl_surface (surface, w, h, fs);
update_window (w, h, vw, vh);
dp.reposition_dialogs ();
glEnableClientState (GL_VERTEX_ARRAY);
}
int quit = DONT;
void try_quit () {
dlog << "*** started to quit DIN Is Noise ***" << endl;
din0.save_scale ();
din0.dinfo.save ();
keybd2.scaleinfo.save_scale ();
mondrian0.scaleinfo.save_scale ();
sounding_board0.scaleinfo.save_scale ();
save_window ();
interpreter ("src save_settings");
dlog << "+++ saved DIN settings +++" << endl;
uis.cb_voice.turn_off ();
uis.cb_delay.turn_off ();
din0.delete_all_drones ();
sounding_board0.save ();
uis.main_menu.bdl.clicked (uis.main_menu.b_delete_all_binaurals);
scope.save_current_instrument ();
quit = SOON;
dlog << "!!! Quitting SOON !!!" << endl;
}
int read_input () {
// handle window events
static SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_VIDEORESIZE:
if (FULL_SCREEN == 0) {
setup_video_mode (event.resize.w, event.resize.h, view.width, view.height, FULL_SCREEN);
uis.settings_scr.update_windowed_mode (event.resize.w, event.resize.h);
}
break;
case SDL_QUIT:
quit = IMMEDIATE;
break;
}
}
// read keyboard
keybd.read ();
// read mouse
int buttons = SDL_GetMouseState (&mousex, &mousey);
mouseyy = view.ymax - mousey;
lmb = buttons & SDL_BUTTON_LMASK;
rmb = buttons & SDL_BUTTON_RMASK;
//if (!lmb) is_lmb.clear ();
return 1;
}
midi_in midiin;
const char* menu::modulation_targets [2] = {" Modulate Drones", " Modulate Voice"};
void applyfx (float* out0, float* out1, int do_delay, int do_compress) {
//
// apply delays
//
float fdr = uis.fdr_delay.amount;
float* outl = out0; left_delay (outl, aout.samples_per_channel, fdr);
float* outr = out1; right_delay (outr, aout.samples_per_channel, fdr);
// apply compression
//
if (do_compress) {
float* outl = out0, *outr = out1;
coml.apply (outl, aout.samples_per_channel);
comr.apply (outr, aout.samples_per_channel);
}
}
int main (int argc, char** argv) {
// MIDI note colors
keyboard_keyboard::note_color [0] = color (0.9f, 0.9f, 0.9f); // white
keyboard_keyboard::note_color [1] = color (0.2f, 0.2f, 0.2f); // black
dlog << "*** Starting DIN Is Noise " << VERSION_NUMBER << " ***" << endl;
//
// bring up OpenGL window
//
if (SDL_Init (SDL_INIT_VIDEO) < 0) {
dlog << "!!! couldnt initialise SDL video !!!" << endl;
exit (1);
} else {
dlog << "+++ initialised SDL video +++" << endl;
}
uis.settings_scr.load_fullscreen_modes ();
if (SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1) < 0) {
dlog << "!!! couldnt setup SDL/OpenGL double buffer !!!" << endl;
exit(1);
} else {
dlog << "+++ setup SDL/OpenGL double buffer +++" << endl;
}
restore_last_window ();
setup_screens ();
setup_curve_list ();
interpreter.add_din_specific ();
string init_tcl ("source " + user_data_dir + "init.tcl");
string load_init_tcl (init_tcl); // init scripts
interpreter (load_init_tcl);
dlog << "+++ loaded DIN scripts (init.tcl) +++" << endl;
/*string load_settings_tcl ("source " + user_data_dir + "settings.tcl"); // init din settings
interpreter (load_settings_tcl);*/
interpreter ("src settings");
dlog << "+++ loaded DIN settings (settings.tcl) +++" << endl;
midiin.open ();
#ifdef __EVALUATION__
//uis.set_current (&anote, 0, 0); // open with author's note
uis.set_current (&anote);
#elif defined __LICENSED__
load_instrument (); // open with last used instrument
#endif
// init menu items
uis.lfs_attack_time.set_val (ATTACK_TIME);
uis.lfs_decay_time.set_val (DECAY_TIME);
uis.lfs_num_voices.set_val ((int)(1.0f / NOTE_VOLUME + 0.5f));
uis.sp_pitch_bend.set_value (PITCH_BEND_PER_PIXEL);
float obpm = octave_shift.get_bpm ();
uis.main_menu.sp_octave_shift_bpm.set_value (obpm);
uis.sp_octave_shift_bpm.set_value (obpm);
uis.main_menu.sp_gater_bpm.set_value (din0.gatr.get_bpm());
uis.main_menu.sp_voice_volume.set_value (VOICE_VOLUME);
uis.main_menu.cb_show_anchors.set_state (din0.dinfo.anchor);
uis.main_menu.cb_show_vel.set_state (din0.dinfo.vel);
uis.main_menu.cb_show_accel.set_state (din0.dinfo.accel);
uis.main_menu.cb_show_gravity.set_state (din0.dinfo.gravity.visible);
uis.main_menu.dcl.changed (uis.main_menu.cb_show_gravity);
uis.main_menu.lf_delta_drone_master_volume.fld.set_text (DELTA_DRONE_MASTER_VOLUME);
uis.main_menu.td_tap_display.set_bpm (din0.gatr.get_bpm ());
uis.main_menu.mark_tap_target ();
uis.main_menu.set_drone_master_volume ();
uis.main_menu.sp_mesh_rows.set_value (din0.dinfo.rows);
uis.main_menu.sp_mesh_cols.set_value (din0.dinfo.cols);
uis.main_menu.sp_bounces.set_value (din0.dinfo.bounces);
uis.main_menu.sp_rebound.set_value (din0.dinfo.rebound);
uis.main_menu.sp_mondrian_min_voices.set_value (mondrian0.min_voices);
uis.main_menu.sp_mondrian_change_attack_time.set_value (0);
uis.main_menu.sp_mondrian_change_decay_time.set_value (0);
uis.main_menu.sp_mondrian_change_speed.set_delta (mondrian0.delta_speed);
uis.main_menu.sp_mondrian_change_dir.set_delta (mondrian0.delta_rotate_velocity);
uis.main_menu.cb_mondrian_auto_adjust_voices.set_state (mondrian0.auto_adjust_voices);
uis.main_menu.cb_draw_balls.set_state (mondrian0.draw__balls);
uis.main_menu.cb_draw_boxes.set_state (mondrian0.draw__boxes);
uis.main_menu.cb_fill_boxes.set_state (mondrian0.fill_boxes);
uis.main_menu.cb_draw_notes.set_state (mondrian0.draw__notes);
uis.main_menu.cb_label_notes.set_state (mondrian0.label_notes);
uis.main_menu.ol_ball_types.set_text (ball::types_str[mondrian0.added_ball_type]);
uis.main_menu.sp_mondrian_num_boxes.set_value (mondrian0.num_boxes);
uis.settings_scr.update_mode_display ();
mondrian0.make_notes ();
sounding_board0.load (); // load binaural drones
curve_picker.widget::hide();
cons.home (); // display all text in console
setup_video_mode (view.width, view.height, view.width, view.height, FULL_SCREEN);
glClearColor(0, 0, 0, 0); // black bg
aout.start (); // start audio loop in a separate thread. see audio_wanted (..)
// ui loop
double framet = 0;
double inputt = 0;
/*wavdoh0.open_file ("input.wav");
while (wavdoh0.read_some ());*/
const string loop ("loop");
const char* timenow = "timenow";
const string s_goodbye ("Goodbye!"), s_drones (" | Drones: "), s_kbkb (" | Keyboard-Keyboard: "), s_mondrian (" | Mondrian: "), s_binaurals (" | Fading Binaurals: ");
const char percent = '%';
while (1) {
// try to write audio
if (aout.can_write ()) {
float* out0 = aout.writep; // left channel
float* out1 = out0 + aout.samples_per_channel; // right channel
do_octave_shift ();
memset (aout.writep, 0, aout.samples_buffer_size); // silence everything
interpreter (loop); // run loop on tcl proc
// audio from instruments
din0.render_audio (out0, out1);
keybd2.render_audio (out0, out1);
mondrian0.render_audio (out0, out1);
sounding_board0.render_audio (out0, out1);
// delay and compressor
applyfx (out0, out1, din0.dinfo.delay, din0.dinfo.compress);
// to oscilloscope
if (scope.visible) scope.add_samples (out0, out1, aout.samples_per_channel);
// record?
if (uis.cb_record.state) {
recorder0.add (aout.writep, aout.samples_buffer_size, aout.samples_per_buffer, uis.cb_record, uis.main_menu.cb_record);
}
// stream status
aout.available [aout.writei] = 1;
if (++aout.writei >= aout.num_samples_buffers) {
aout.writep = aout.samples_buffers;
aout.writei = 0;
} else aout.writep += aout.samples_per_buffer;
// store timenow in TCL. timenow is seconds on din audio clock
TIME_NOW = clk.secs;
Tcl_UpdateLinkedVar (interpreter.interp, timenow);
}
if (recorder0.saving_started) { // save recording to disk
if (recorder0.save_some (uis.main_menu.cb_record) == 0)
uis.main_menu.b_save.set_label ("Overwrite");
}
// draw frame
double T = ui_clk ();
if (T >= framet) {
double deltat = T - framet;
GOT_FPS = 1.0 / deltat;
uis.draw ();
SDL_GL_SwapBuffers ();
framet = TIME_PER_FRAME + ui_clk ();
}
// handle input [mouse, keys and midi] and bg
T = ui_clk ();
if (T >= inputt) {
read_input ();
if (quit == DONT);
else if (quit == SOON) {
cons << console::yellow << s_goodbye << s_drones << din0.num_drones << s_kbkb << keybd2.num_triggered_notes << s_mondrian << mondrian0.num_triggered_notes;
if (sounding_board0.num_sounders) cons << s_binaurals << int(sounding_board0.xt*100+0.5) << percent;
cons << eol;
if (
(din0.num_drones == 0) &&
(uis.fdr_voice.on == 0) &&
(uis.fdr_delay.on == 0) &&
(keybd2.num_triggered_notes == 0) &&
(mondrian0.num_triggered_notes == 0) &&
(sounding_board0.fading == 0)
)
break;
}
else if (quit == IMMEDIATE) break;
uis.handle_input ();
midiin.handle_input ();
keybd.save ();
uis.bg ();
inputt = TIME_PER_INPUT + ui_clk ();
}
}
aout.close ();
mesh::destroy ();
if (trail_t::tpts) delete[] trail_t::tpts;
#if defined (__SVG_OUT__) || defined (__PLOTTER_OUT__)
ifstream textf ("text.txt", ios::in);
if (textf) {
int x, y;
textf >> x >> y;
string line;
int lh = get_line_height ();
while (!textf.eof()) {
getline (textf, line);
#ifdef __SVG_OUT__
write_string (line, x, y);
y += lh;
#elif __PLOTTER_OUT__
plot_string (line, x, y);
y -= lh;
#endif
}
}
#endif
return 0;
}
void set_tonic (instrument* instr, float f) {
instr->scaleinfo.set_tonic (f);
if (instr == get_current_instrument ()) instr->scaleinfo.update_settings ();
}
float get_tonic (instrument* instr) {
return instr->scaleinfo.tonic;
}
void set_notation (const string& s) {
if (s == "w" || s == "west" || s == "western") NOTATION = "western"; else NOTATION = "numeric";
din0.notate_ranges ();
keybd2.setup_notes (0);
mondrian0.calc_visual_params ();
uis.settings_scr.sn_scale_notes.refresh ();
}
void set_num_octaves (int n) {
if (n < 1) n = 1;
NUM_OCTAVES = n;
din0.setup_ranges (0); // 0 => dont load from disk
din0.update_drone_ranges ();
din0.update_drone_tone ();
}
int hide_menu () {
uis.main_menu.unfilter ();
if (uis.main_menu.show) {
uis.main_menu.toggle ();
return 1;
}
return 0;
}
void show_menu () {
uis.main_menu.show = 0;
uis.main_menu.toggle ();
}
void overlay_instrument () {
get_current_instrument ()->draw ();
}
void hz2step (float& hz, float& step) {
step = hz * 1.0f / SAMPLE_RATE;
}
void set_snap_drones (int what) {
stringstream ss; ss << "set-var snap_drones " << what;
cons (ss.str());
}
void set_snap (int what) {
uis.main_menu.set_snap (what);
}
void dont_call_listener (checkbutton& cb, int state) {
int _dont_call_listener = 0;
if (state) cb.turn_on (_dont_call_listener); else cb.turn_off (_dont_call_listener);
}
int find_nearest_note (string& note, float& frequency, float& dist) {
float left = WIKIPEDIA_KEY_FREQUENCIES [0] / 2048, right = 2 * left;
float outf = frequency;
if (outf < left) return 0;
while (1) {
if ((left <= outf) && (right > outf)) break;
else {
left*=2;
right*=2;
}
}
float oct = left / WIKIPEDIA_KEY_FREQUENCIES[0];
dist = outf - left;
int id = 0;
float tone = 0;
for (int i = 0; i < 13; ++i) {
tone = WIKIPEDIA_KEY_FREQUENCIES[i] * oct;
float newdist = tone - outf; if (newdist < 0) newdist = -newdist;
if (newdist < dist) {
dist = newdist;
id = i;
}
}
string nn;
if (WESTERN_FLAT[id] == WESTERN_SHARP[id])
nn = WESTERN_SHARP[id];
else
nn = (string)WESTERN_FLAT[id] + " / " + (string)WESTERN_SHARP[id];
note = nn;
frequency = WIKIPEDIA_KEY_FREQUENCIES[id] * oct;
dist = outf - frequency;
return id;
}
void turn_on_ui () {
TURN_OFF_UI = 0;
uis.add_widgets ();
}
void turn_off_ui () {
if (!uis.current->ed) {
TURN_OFF_UI = 1;
if (uis.main_menu.show) uis.main_menu.toggle ();
uis.widgets_of.clear ();
} else cons << console::red << "Cant turn off UI in curve editors" << eol;
}
void tween (float* buf1, float* buf2, int n, float amount) {// interpolate buf2 -> buf1 and store in buf1
for (int i = 0; i < n; ++i) {
float b1 = buf1 [i], b2 = buf2[i];
buf1[i] = amount * (b1 - b2) + b2;
}
}
void tween (float* buf1, float* buf2, int n, float* amount) {
for (int i = 0; i < n; ++i) {
float b1 = buf1 [i], b2 = buf2[i];
buf1[i] = amount[i] * (b1 - b2) + b2;
}
}
void fill (float* buf, float start, float end, int n) {
float es = end - start;
float a = 0, da = 1./ (n - 1);
for (int i = 0; i < n; ++i) {
buf[i] = start + a * es;
a += da;
}
}
void multiply (float* out, float* mul, int n) {
for (int i = 0; i < n; ++i) out[i] *= mul[i];
}
void multiply (float* out, int n, float depth) {
for (int i = 0; i < n; ++i) out[i] *= depth;
}
void warp_mouse (int x, int y) {
SDL_WarpMouse (x, y);
mousex = x;
mousey = y;
mouseyy = view.ymax - y;
}