Rev 2097 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* binaural_drones.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 "binaural_drones.h"
#include "console.h"
#include "curve_listener.h"
#include "audio.h"
#include "input.h"
#include "viewwin.h"
#include "fft.h"
#include "utils.h"
#include "ui_list.h"
#include <algorithm>
#include "log.h"
extern string user_data_dir;
extern int mousex, mousey;
extern atmin _atmin;
extern atmax _atmax;
extern int SAMPLE_RATE;
extern char BUFFER[];
extern const char spc;
extern int FPS;
void waveform_listener::edited (curve_editor* ed, int i) {
if (fft0.folded () == 0) fft0.go (ed->curveinfo[i].curve);
sb->update_players (ed->mix);
curve_listener::edited (ed, i);
}
fade_info::fade_info () {
xt = dxt = xui = 0.0f;
active = 0;
after = 0;
}
void fade_info::start (const string& _name) {
name = _name;
xt = xui = 0.0f;
after = 0;
active = 1;
}
void fade_info::set_duration (float d) {
if (d < 0) return;
duration = d;
if (equals (d, 0.0f)) d = 0.001f;
float du = 0.1 * d;
dxt = SAMPLE_DURATION * 1.0 / d;
xu = SAMPLE_DURATION * du;
}
int fade_info::eval (float* out) {
int u = 0;
if (active) {
sol (xt, dxt, aout.samples_per_channel, out, _atmin, _atmax);
if (xt >= 1.0f) {
complete ();
u = 1;
} else {
if ((xt - xui) >= xu) {
xui = xt;
u = 1;
}
}
}
return u;
}
void fade_info::complete () {
xt = 1.0f;
active = 0;
after = 1;
}
void fade_info::abort () {
active = 0;
after = 0;
}
void i_binaural_drones::load () {
ifstream file ((user_data_dir + "binaural_drones").c_str (), ios::in);
string ignore;
file >> ignore >> master_volume;
file >> ignore >> starting_pitch;
file >> ignore >> separation;
file >> ignore >> pairs;
file >> ignore >> spacing;
float d;
file >> ignore >> d; vol_fader.set_duration (d);
file >> ignore >> d; pitch_fader.set_duration (d);
file >> ignore >> just;
file >> ignore >> keynote;
file >> ignore >> close_octave;
file >> ignore >> resize_separation;
file >> ignore >> modulation_amount;
int n; file >> ignore >> n;
if (n) {
for (int i = 0; i < n; ++i) {
float lhz, rhz, vol, sep, lx, rx;
int just;
file >> lhz >> rhz >> vol >> just >> sep >> lx >> rx;
add (lhz, rhz, vol, just, sep, lx, rx);
}
dlog << "+++ loaded " << n << " binaurals +++" << endl;
}
}
void i_binaural_drones::save () {
ofstream file ((user_data_dir + "binaural_drones").c_str (), ios::out);
file << "master_volume " << master_volume << endl;
file << "starting_pitch " << starting_pitch << endl;
file << "separation " << separation << endl;
file << "pairs " << pairs << endl;
file << "spacing " << spacing << endl;
file << "volume_fade_duration " << vol_fader.duration << endl;
file << "pitch_fade_duration " << pitch_fader.duration << endl;
file << "justification " << just << endl;
file << "keynote " << keynote << endl;
file << "close_octave " << close_octave << endl;
file << "resize_separation " << resize_separation << endl;
file << "modulation_amount " << modulation_amount << endl;
file << "num_binaural_drones " << num_binaural_drones << endl;
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bi = binaural_drones[i];
file << bi->l_hz << spc << bi->r_hz << spc << bi->vol << spc << bi->just << spc << bi->sep << spc << bi->playl.x << spc << bi->playr.x << endl;
}
dlog << "+++ saved all binaurals +++" << endl;
}
i_binaural_drones::~i_binaural_drones () {
for (int i = 0; i < num_binaural_drones; ++i) delete binaural_drones[i];
wav.save ("binaural-drones-waveform.crv");
dlog << "--- destroyed binaural_drones ---" << endl;
}
int i_binaural_drones::add (float lhz, float rhz, float vol, int just, float sep, float lx, float rx) {
binaural_drone* bd = new binaural_drone (&wav, lhz, rhz, vol, just, sep, lx, rx);
vol_fader.start ("Volume fade-in");
int id = 0;
if (num_binaural_drones) { // insert sorted by left hz
typedef std::vector<binaural_drone*>::iterator binaural_drone_iterator;
binaural_drone_iterator bd_begin = binaural_drones.begin ();
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bi = binaural_drones [i];
if (bi->l_hz >= bd->l_hz) {
binaural_drone_iterator bd_insert = bd_begin + i;
binaural_drones.insert (bd_insert, bd);
MENU.il_binaural_drones.insert (i, bd->name);
++num_binaural_drones;
id = i;
return id;
}
}
}
binaural_drones.push_back (bd);
id = num_binaural_drones++;
MENU.il_binaural_drones.add (bd->name);
return id;
}
void i_binaural_drones::remove (int which) {
if (which < num_binaural_drones) {
binaural_drone* bw = binaural_drones [which];
binaural_drones.erase (binaural_drones.begin()+which);
--num_binaural_drones;
delete bw;
MENU.il_binaural_drones.remove (which);
} else cons << RED << "bad binaural drone id: " << which << eol;
}
void i_binaural_drones::sync (int n, const string& lst) {
if (n == -1) { // sync all
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bi = binaural_drones[i];
bi->sync ();
}
} else { // sync list
tokenizer tz (lst);
for (int i = 0; i < n; ++i) {
int j; tz >> j;
binaural_drone* bj = binaural_drones[j];
bj->sync ();
}
}
}
void i_binaural_drones::list () {
cons << YELLOW;
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* pbd = binaural_drones[i];
sprintf (BUFFER, "Pair %d: %s", i, pbd->name.c_str());
cons << BUFFER << eol;
}
sprintf (BUFFER, "%d pairs in total", num_binaural_drones);
cons << GREEN << BUFFER << eol;
}
string i_binaural_drones::get_sel_vol () {
stringstream ss;
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bi = binaural_drones[i];
if (bi->sel) ss << bi->vol << spc;
}
return ss.str();
}
int i_binaural_drones::render_audio (float* L0, float* R0) {
int uv = 0, uh = 0;
if (vol_fader.active) uv = vol_fader.eval (aout.vol);
if (pitch_fader.active) uh = pitch_fader.eval (aout.fdr2);
int uvh = uv | uh;
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bd = binaural_drones[i];
float* L = L0, *R = R0;
bd->render (L, R, aout.vol, aout.fdr2, uv, uh, abort);
if (uvh) MENU.il_binaural_drones.items[i].name = bd->name;
}
if (abort) {
vol_fader.abort ();
pitch_fader.abort ();
abort = 0;
cons << RED << "Aborted" << eol;
} else {
if (vol_fader.after) {
for (int i = 0; i < num_binaural_drones; ++i) binaural_drones[i]->fading.vol = binaural_drone::fade_flags::NONE;
cons << GREEN << vol_fader.name << " complete." << eol;
vol_fader.after = 0;
vol_fader.name = "";
cons ("after-fade");
}
if (pitch_fader.after) {
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* bi = binaural_drones[i];
if (bi->fading.hz) {
bi->fill_hz ();
bi->fading.hz = binaural_drone::fade_flags::NONE;
}
}
cons << GREEN << pitch_fader.name << " complete." << eol;
pitch_fader.after = 0;
pitch_fader.name = "";
cons ("after-fade");
}
}
return 1;
}
void i_binaural_drones::update_players (multi_curve& mx) {
int canmix = mx.num_vertices;
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* s = binaural_drones[i];
s->soll.update ();
s->solr.update ();
}
if (canmix) {
for (int i = 0; i < num_binaural_drones; ++i) {
binaural_drone* s = binaural_drones[i];
s->playl.set_mix (mx, "binaural_drones_waveform");
s->playr.set_mix (mx, "binaural_drones_waveform");
}
}
}
int i_binaural_drones::handle_input () {
prev_mousex = mousex;
prev_mousey = mousey;
if (keypressed (SDLK_F1)) hlp();
if (keypressed (SDLK_F3)) aborted ();
return 1;
}
void i_binaural_drones::enter () {
extern void show_menu ();
show_menu ();
}
int i_binaural_drones::change_justification (int d) {
just += d;
if (just < binaural_drone::LEFT) just = binaural_drone::CENTER;
else if (just > binaural_drone::CENTER) just = binaural_drone::LEFT;
return just;
}
int i_binaural_drones::change_key_note (int d) {
keynote += d;
if (keynote < START_PITCH) keynote = FROM_SCALE;
else if (keynote > FROM_SCALE) keynote = START_PITCH;
return keynote;
}
int i_binaural_drones::busy () { return vol_fader.active || pitch_fader.active; }
int i_binaural_drones::aborted () {
if (busy()) abort = 1;
return abort;
}