Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Master.cpp 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Master.cpp - It sends Midi Messages to Parts, receives samples from parts,
  4. process them with system/insertion effects and mix them
  5. Copyright (C) 2002-2005 Nasca Octavian Paul
  6. Author: Nasca Octavian Paul
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of version 2 of the GNU General Public License
  9. as published by the Free Software Foundation.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License (version 2 or later) for more details.
  14. You should have received a copy of the GNU General Public License (version 2)
  15. along with this program; if not, write to the Free Software Foundation,
  16. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. */
  18. #include "Master.h"
  19. #include "Part.h"
  20. #include "../Misc/Stereo.h"
  21. #include "../Misc/Util.h"
  22. #include "../Params/LFOParams.h"
  23. #include "../Effects/EffectMgr.h"
  24. #include "../DSP/FFTwrapper.h"
  25. #include "../Misc/Allocator.h"
  26. #include "../Nio/Nio.h"
  27. #include "PresetExtractor.h"
  28. #include <rtosc/ports.h>
  29. #include <rtosc/port-sugar.h>
  30. #include <rtosc/thread-link.h>
  31. #include <stdio.h>
  32. #include <sys/stat.h>
  33. #include <sys/types.h>
  34. #include <iostream>
  35. #include <algorithm>
  36. #include <cmath>
  37. #include <atomic>
  38. #include <unistd.h>
  39. using namespace std;
  40. using namespace rtosc;
  41. #define rObject Master
  42. static const Ports sysefxPort =
  43. {
  44. {"part#" STRINGIFY(NUM_MIDI_PARTS) "::i", rProp(parameter)
  45. rDoc("gain on part to sysefx routing"), 0,
  46. [](const char *m, RtData&d)
  47. {
  48. //ok, this is going to be an ugly workaround
  49. //we know that if we are here the message previously MUST have
  50. //matched Psysefxvol#/
  51. //and the number is one or two digits at most
  52. const char *index_1 = m;
  53. index_1 -=2;
  54. assert(isdigit(*index_1));
  55. if(isdigit(index_1[-1]))
  56. index_1--;
  57. int ind1 = atoi(index_1);
  58. //Now get the second index like normal
  59. while(!isdigit(*m)) m++;
  60. int ind2 = atoi(m);
  61. Master &mast = *(Master*)d.obj;
  62. if(rtosc_narguments(m)) {
  63. mast.setPsysefxvol(ind2, ind1, rtosc_argument(m,0).i);
  64. d.broadcast(d.loc, "i", mast.Psysefxvol[ind1][ind2]);
  65. } else
  66. d.reply(d.loc, "i", mast.Psysefxvol[ind1][ind2]);
  67. }}
  68. };
  69. static const Ports sysefsendto =
  70. {
  71. {"to#" STRINGIFY(NUM_SYS_EFX) "::i",
  72. rProp(parameter) rDoc("sysefx to sysefx routing gain"), 0, [](const char *m, RtData&d)
  73. {
  74. //same ugly workaround as before
  75. const char *index_1 = m;
  76. index_1 -=2;
  77. assert(isdigit(*index_1));
  78. if(isdigit(index_1[-1]))
  79. index_1--;
  80. int ind1 = atoi(index_1);
  81. //Now get the second index like normal
  82. while(!isdigit(*m)) m++;
  83. int ind2 = atoi(m);
  84. Master &master = *(Master*)d.obj;
  85. if(rtosc_narguments(m))
  86. master.setPsysefxsend(ind1, ind2, rtosc_argument(m,0).i);
  87. else
  88. d.reply(d.loc, "i", master.Psysefxsend[ind1][ind2]);
  89. }}
  90. };
  91. static const Ports master_ports = {
  92. rString(last_xmz, XMZ_PATH_MAX, "File name for last name loaded if any."),
  93. rRecursp(part, 16, "Part"),//NUM_MIDI_PARTS
  94. rRecursp(sysefx, 4, "System Effect"),//NUM_SYS_EFX
  95. rRecursp(insefx, 8, "Insertion Effect"),//NUM_INS_EFX
  96. rRecur(microtonal, "Micrtonal Mapping Functionality"),
  97. rRecur(ctl, "Controller"),
  98. rArrayI(Pinsparts, NUM_INS_EFX, "Part to insert part onto"),
  99. {"Pkeyshift::i", rProp(parameter) rLinear(0,127) rDoc("Global Key Shift"), 0, [](const char *m, RtData&d) {
  100. if(rtosc_narguments(m)==0) {
  101. d.reply(d.loc, "i", ((Master*)d.obj)->Pkeyshift);
  102. } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') {
  103. ((Master*)d.obj)->setPkeyshift(limit<char>(rtosc_argument(m,0).i,0,127));
  104. d.broadcast(d.loc, "i", ((Master*)d.obj)->Pkeyshift);}}},
  105. {"echo", rDoc("Hidden port to echo messages"), 0, [](const char *m, RtData&d) {
  106. d.reply(m-1);}},
  107. {"get-vu:", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
  108. Master *m = (Master*)d.obj;
  109. d.reply("/vu-meter", "bb", sizeof(m->vu), &m->vu, sizeof(float)*NUM_MIDI_PARTS, m->vuoutpeakpart);}},
  110. {"reset-vu:", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
  111. Master *m = (Master*)d.obj;
  112. m->vuresetpeaks();}},
  113. {"load-part:ib", rProp(internal) rDoc("Load Part From Middleware"), 0, [](const char *msg, RtData &d) {
  114. Master *m = (Master*)d.obj;
  115. Part *p = *(Part**)rtosc_argument(msg, 1).b.data;
  116. int i = rtosc_argument(msg, 0).i;
  117. m->part[i]->cloneTraits(*p);
  118. m->part[i]->kill_rt();
  119. d.reply("/free", "sb", "Part", sizeof(void*), &m->part[i]);
  120. m->part[i] = p;
  121. p->initialize_rt();
  122. }},
  123. {"Pvolume::i", rProp(parameter) rLinear(0,127) rDoc("Master Volume"), 0,
  124. [](const char *m, rtosc::RtData &d) {
  125. if(rtosc_narguments(m)==0) {
  126. d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume);
  127. } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') {
  128. ((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127));
  129. d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}},
  130. {"volume::i", rProp(parameter) rLinear(0,127) rDoc("Master Volume"), 0,
  131. [](const char *m, rtosc::RtData &d) {
  132. if(rtosc_narguments(m)==0) {
  133. d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume);
  134. } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') {
  135. ((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127));
  136. d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}},
  137. {"Psysefxvol#" STRINGIFY(NUM_SYS_EFX) "/::i", 0, &sysefxPort,
  138. [](const char *msg, rtosc::RtData &d) {
  139. SNIP;
  140. sysefxPort.dispatch(msg, d);
  141. }},
  142. {"sysefxfrom#" STRINGIFY(NUM_SYS_EFX) "/", rDoc("Routing Between System Effects"), &sysefsendto,
  143. [](const char *msg, RtData&d) {
  144. SNIP;
  145. sysefsendto.dispatch(msg, d);
  146. }},
  147. {"noteOn:iii", rDoc("Noteon Event"), 0,
  148. [](const char *m,RtData &d){
  149. Master *M = (Master*)d.obj;
  150. M->noteOn(rtosc_argument(m,0).i,rtosc_argument(m,1).i,rtosc_argument(m,2).i);}},
  151. {"noteOff:ii", rDoc("Noteoff Event"), 0,
  152. [](const char *m,RtData &d){
  153. Master *M = (Master*)d.obj;
  154. M->noteOff(rtosc_argument(m,0).i,rtosc_argument(m,1).i);}},
  155. {"virtual_midi_cc:iii", rDoc("MIDI CC Event"), 0,
  156. [](const char *m,RtData &d){
  157. Master *M = (Master*)d.obj;
  158. M->setController(rtosc_argument(m,0).i,rtosc_argument(m,1).i,rtosc_argument(m,2).i);}},
  159. {"setController:iii", rDoc("MIDI CC Event"), 0,
  160. [](const char *m,RtData &d){
  161. Master *M = (Master*)d.obj;
  162. M->setController(rtosc_argument(m,0).i,rtosc_argument(m,1).i,rtosc_argument(m,2).i);}},
  163. {"Panic:", rDoc("Stop all sound"), 0,
  164. [](const char *, RtData &d) {
  165. Master &M = *(Master*)d.obj;
  166. M.ShutUp();
  167. }},
  168. {"freeze_state:", rProp(internal) rDoc("Disable OSC event handling\n"
  169. "This sets up a read-only mode from which it's safe for another"
  170. " thread to save parameters"), 0,
  171. [](const char *,RtData &d) {
  172. Master *M = (Master*)d.obj;
  173. std::atomic_thread_fence(std::memory_order_release);
  174. M->frozenState = true;
  175. d.reply("/state_frozen", "");}},
  176. {"thaw_state:", rProp(internal) rDoc("Resume handling OSC messages\n"
  177. "See /freeze_state for more information"), 0,
  178. [](const char *,RtData &d) {
  179. Master *M = (Master*)d.obj;
  180. M->frozenState = false;}},
  181. {"midi-learn/", 0, &rtosc::MidiMapperRT::ports,
  182. [](const char *msg, RtData &d) {
  183. Master *M = (Master*)d.obj;
  184. SNIP;
  185. printf("residue message = <%s>\n", msg);
  186. d.obj = &M->midi;
  187. rtosc::MidiMapperRT::ports.dispatch(msg,d);}},
  188. {"close-ui:", rDoc("Request to close any connection named \"GUI\""), 0,
  189. [](const char *, RtData &d) {
  190. d.reply("/close-ui", "");}},
  191. {"add-rt-memory:bi", rProp(internal) rDoc("Add Additional Memory To RT MemPool"), 0,
  192. [](const char *msg, RtData &d)
  193. {
  194. Master &m = *(Master*)d.obj;
  195. char *mem = *(char**)rtosc_argument(msg, 0).b.data;
  196. int i = rtosc_argument(msg, 1).i;
  197. m.memory->addMemory(mem, i);
  198. m.pendingMemory = false;
  199. }},
  200. {"samplerate:", rMap(unit, Hz) rDoc("Get synthesizer sample rate"), 0, [](const char *, RtData &d) {
  201. Master &m = *(Master*)d.obj;
  202. d.reply("/samplerate", "f", m.synth.samplerate_f);
  203. }},
  204. {"oscilsize:", rDoc("Get synthesizer oscillator size"), 0, [](const char *, RtData &d) {
  205. Master &m = *(Master*)d.obj;
  206. d.reply("/oscilsize", "f", m.synth.oscilsize_f);
  207. d.reply("/oscilsize", "i", m.synth.oscilsize);
  208. }},
  209. {"undo_pause:",rProp(internal) rDoc("pause undo event recording"),0,
  210. [](const char *, rtosc::RtData &d) {d.reply("/undo_pause", "");}},
  211. {"undo_resume:",rProp(internal) rDoc("resume undo event recording"),0,
  212. [](const char *, rtosc::RtData &d) {d.reply("/undo_resume", "");}},
  213. {"config/", rDoc("Top Level Application Configuration Parameters"), &Config::ports,
  214. [](const char *, rtosc::RtData &d){d.forward();}},
  215. {"presets/", rDoc("Parameter Presets"), &preset_ports, rBOIL_BEGIN
  216. SNIP
  217. preset_ports.dispatch(msg, data);
  218. rBOIL_END},
  219. };
  220. const Ports &Master::ports = master_ports;
  221. class DataObj:public rtosc::RtData
  222. {
  223. public:
  224. DataObj(char *loc_, size_t loc_size_, void *obj_, rtosc::ThreadLink *bToU_)
  225. {
  226. memset(loc_, 0, loc_size_);
  227. loc = loc_;
  228. loc_size = loc_size_;
  229. obj = obj_;
  230. bToU = bToU_;
  231. forwarded = false;
  232. }
  233. virtual void reply(const char *path, const char *args, ...) override
  234. {
  235. va_list va;
  236. va_start(va,args);
  237. char *buffer = bToU->buffer();
  238. rtosc_vmessage(buffer,bToU->buffer_size(),path,args,va);
  239. reply(buffer);
  240. va_end(va);
  241. }
  242. virtual void reply(const char *msg) override
  243. {
  244. if(rtosc_message_length(msg, -1) == 0)
  245. fprintf(stderr, "Warning: Invalid Rtosc message '%s'\n", msg);
  246. bToU->raw_write(msg);
  247. }
  248. virtual void broadcast(const char *path, const char *args, ...) override{
  249. va_list va;
  250. va_start(va,args);
  251. reply("/broadcast", "");
  252. char *buffer = bToU->buffer();
  253. rtosc_vmessage(buffer,bToU->buffer_size(),path,args,va);
  254. reply(buffer);
  255. va_end(va);
  256. }
  257. virtual void broadcast(const char *msg) override
  258. {
  259. reply("/broadcast", "");
  260. reply(msg);
  261. }
  262. virtual void forward(const char *reason) override
  263. {
  264. assert(message);
  265. reply("/forward", "");
  266. printf("forwarding '%s'\n", message);
  267. forwarded = true;
  268. }
  269. bool forwarded;
  270. private:
  271. rtosc::ThreadLink *bToU;
  272. };
  273. vuData::vuData(void)
  274. :outpeakl(0.0f), outpeakr(0.0f), maxoutpeakl(0.0f), maxoutpeakr(0.0f),
  275. rmspeakl(0.0f), rmspeakr(0.0f), clipped(0)
  276. {}
  277. Master::Master(const SYNTH_T &synth_, Config* config)
  278. :HDDRecorder(synth_), ctl(synth_),
  279. microtonal(config->cfg.GzipCompression), bank(config),
  280. frozenState(false), pendingMemory(false),
  281. synth(synth_), time(synth), gzip_compression(config->cfg.GzipCompression)
  282. {
  283. bToU = NULL;
  284. uToB = NULL;
  285. //Setup MIDI
  286. midi.frontend = [this](const char *msg) {bToU->raw_write(msg);};
  287. midi.backend = [this](const char *msg) {applyOscEvent(msg);};
  288. memory = new AllocatorClass();
  289. swaplr = 0;
  290. off = 0;
  291. smps = 0;
  292. bufl = new float[synth.buffersize];
  293. bufr = new float[synth.buffersize];
  294. last_xmz[0] = 0;
  295. fft = new FFTwrapper(synth.oscilsize);
  296. shutup = 0;
  297. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  298. vuoutpeakpart[npart] = 1e-9;
  299. fakepeakpart[npart] = 0;
  300. }
  301. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  302. part[npart] = new Part(*memory, synth, time, config->cfg.GzipCompression,
  303. config->cfg.Interpolation, &microtonal, fft);
  304. //Insertion Effects init
  305. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  306. insefx[nefx] = new EffectMgr(*memory, synth, 1);
  307. //System Effects init
  308. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx)
  309. sysefx[nefx] = new EffectMgr(*memory, synth, 0);
  310. defaults();
  311. mastercb = 0;
  312. mastercb_ptr = 0;
  313. }
  314. void Master::applyOscEvent(const char *msg)
  315. {
  316. char loc_buf[1024];
  317. DataObj d{loc_buf, 1024, this, bToU};
  318. memset(loc_buf, 0, sizeof(loc_buf));
  319. d.matches = 0;
  320. if(strcmp(msg, "/get-vu") && false) {
  321. fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 5 + 30, 0 + 40);
  322. fprintf(stdout, "backend[*]: '%s'<%s>\n", msg,
  323. rtosc_argument_string(msg));
  324. fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
  325. }
  326. ports.dispatch(msg, d, true);
  327. if(d.matches == 0 && !d.forwarded)
  328. fprintf(stderr, "Unknown path '%s:%s'\n", msg, rtosc_argument_string(msg));
  329. if(d.forwarded)
  330. bToU->raw_write(msg);
  331. }
  332. void Master::defaults()
  333. {
  334. volume = 1.0f;
  335. setPvolume(80);
  336. setPkeyshift(64);
  337. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  338. part[npart]->defaults();
  339. part[npart]->Prcvchn = npart % NUM_MIDI_CHANNELS;
  340. }
  341. partonoff(0, 1); //enable the first part
  342. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) {
  343. insefx[nefx]->defaults();
  344. Pinsparts[nefx] = -1;
  345. }
  346. //System Effects init
  347. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) {
  348. sysefx[nefx]->defaults();
  349. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  350. setPsysefxvol(npart, nefx, 0);
  351. for(int nefxto = 0; nefxto < NUM_SYS_EFX; ++nefxto)
  352. setPsysefxsend(nefx, nefxto, 0);
  353. }
  354. microtonal.defaults();
  355. ShutUp();
  356. }
  357. /*
  358. * Note On Messages (velocity=0 for NoteOff)
  359. */
  360. void Master::noteOn(char chan, char note, char velocity)
  361. {
  362. if(velocity) {
  363. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  364. if(chan == part[npart]->Prcvchn) {
  365. fakepeakpart[npart] = velocity * 2;
  366. if(part[npart]->Penabled)
  367. part[npart]->NoteOn(note, velocity, keyshift);
  368. }
  369. }
  370. else
  371. this->noteOff(chan, note);
  372. HDDRecorder.triggernow();
  373. }
  374. /*
  375. * Note Off Messages
  376. */
  377. void Master::noteOff(char chan, char note)
  378. {
  379. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  380. if((chan == part[npart]->Prcvchn) && part[npart]->Penabled)
  381. part[npart]->NoteOff(note);
  382. }
  383. /*
  384. * Pressure Messages (velocity=0 for NoteOff)
  385. */
  386. void Master::polyphonicAftertouch(char chan, char note, char velocity)
  387. {
  388. if(velocity) {
  389. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  390. if(chan == part[npart]->Prcvchn)
  391. if(part[npart]->Penabled)
  392. part[npart]->PolyphonicAftertouch(note, velocity, keyshift);
  393. }
  394. else
  395. this->noteOff(chan, note);
  396. }
  397. /*
  398. * Controllers
  399. */
  400. void Master::setController(char chan, int type, int par)
  401. {
  402. if(frozenState)
  403. return;
  404. //TODO add chan back
  405. midi.handleCC(type,par);
  406. if((type == C_dataentryhi) || (type == C_dataentrylo)
  407. || (type == C_nrpnhi) || (type == C_nrpnlo)) { //Process RPN and NRPN by the Master (ignore the chan)
  408. ctl.setparameternumber(type, par);
  409. int parhi = -1, parlo = -1, valhi = -1, vallo = -1;
  410. if(ctl.getnrpn(&parhi, &parlo, &valhi, &vallo) == 0) { //this is NRPN
  411. switch(parhi) {
  412. case 0x04: //System Effects
  413. if(parlo < NUM_SYS_EFX)
  414. sysefx[parlo]->seteffectparrt(valhi, vallo);
  415. break;
  416. case 0x08: //Insertion Effects
  417. if(parlo < NUM_INS_EFX)
  418. insefx[parlo]->seteffectparrt(valhi, vallo);
  419. break;
  420. }
  421. }
  422. } else { //other controllers
  423. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) //Send the controller to all part assigned to the channel
  424. if((chan == part[npart]->Prcvchn) && (part[npart]->Penabled != 0))
  425. part[npart]->SetController(type, par);
  426. if(type == C_allsoundsoff) { //cleanup insertion/system FX
  427. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx)
  428. sysefx[nefx]->cleanup();
  429. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  430. insefx[nefx]->cleanup();
  431. }
  432. }
  433. }
  434. void Master::vuUpdate(const float *outl, const float *outr)
  435. {
  436. //Peak computation (for vumeters)
  437. vu.outpeakl = 1e-12;
  438. vu.outpeakr = 1e-12;
  439. for(int i = 0; i < synth.buffersize; ++i) {
  440. if(fabs(outl[i]) > vu.outpeakl)
  441. vu.outpeakl = fabs(outl[i]);
  442. if(fabs(outr[i]) > vu.outpeakr)
  443. vu.outpeakr = fabs(outr[i]);
  444. }
  445. if((vu.outpeakl > 1.0f) || (vu.outpeakr > 1.0f))
  446. vu.clipped = 1;
  447. if(vu.maxoutpeakl < vu.outpeakl)
  448. vu.maxoutpeakl = vu.outpeakl;
  449. if(vu.maxoutpeakr < vu.outpeakr)
  450. vu.maxoutpeakr = vu.outpeakr;
  451. //RMS Peak computation (for vumeters)
  452. vu.rmspeakl = 1e-12;
  453. vu.rmspeakr = 1e-12;
  454. for(int i = 0; i < synth.buffersize; ++i) {
  455. vu.rmspeakl += outl[i] * outl[i];
  456. vu.rmspeakr += outr[i] * outr[i];
  457. }
  458. vu.rmspeakl = sqrt(vu.rmspeakl / synth.buffersize_f);
  459. vu.rmspeakr = sqrt(vu.rmspeakr / synth.buffersize_f);
  460. //Part Peak computation (for Part vumeters or fake part vumeters)
  461. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  462. vuoutpeakpart[npart] = 1.0e-12f;
  463. if(part[npart]->Penabled != 0) {
  464. float *outl = part[npart]->partoutl,
  465. *outr = part[npart]->partoutr;
  466. for(int i = 0; i < synth.buffersize; ++i) {
  467. float tmp = fabs(outl[i] + outr[i]);
  468. if(tmp > vuoutpeakpart[npart])
  469. vuoutpeakpart[npart] = tmp;
  470. }
  471. vuoutpeakpart[npart] *= volume;
  472. }
  473. else
  474. if(fakepeakpart[npart] > 1)
  475. fakepeakpart[npart]--;
  476. }
  477. }
  478. /*
  479. * Enable/Disable a part
  480. */
  481. void Master::partonoff(int npart, int what)
  482. {
  483. if(npart >= NUM_MIDI_PARTS)
  484. return;
  485. if(what == 0) { //disable part
  486. fakepeakpart[npart] = 0;
  487. part[npart]->Penabled = 0;
  488. part[npart]->cleanup();
  489. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) {
  490. if(Pinsparts[nefx] == npart)
  491. insefx[nefx]->cleanup();
  492. }
  493. }
  494. else { //enabled
  495. part[npart]->Penabled = 1;
  496. fakepeakpart[npart] = 0;
  497. }
  498. }
  499. void Master::setMasterChangedCallback(void(*cb)(void*,Master*), void *ptr)
  500. {
  501. mastercb = cb;
  502. mastercb_ptr = ptr;
  503. }
  504. #if 0
  505. template <class T>
  506. struct def_skip
  507. {
  508. static void skip(const char*& argptr) { argptr += sizeof(T); }
  509. };
  510. template <class T>
  511. struct str_skip
  512. {
  513. static void skip(const char*& argptr) { while(argptr++); /*TODO: 4 padding */ }
  514. };
  515. template<class T, class Display = T, template<class TMP> class SkipsizeFunc = def_skip>
  516. void _dump_prim_arg(const char*& argptr, std::ostream& os)
  517. {
  518. os << ' ' << (Display)*(const T*)argptr;
  519. SkipsizeFunc<T>::skip(argptr);
  520. }
  521. void dump_msg(const char* ptr, std::ostream& os = std::cerr)
  522. {
  523. assert(*ptr == '/');
  524. os << ptr;
  525. while(*++ptr) ; // skip address
  526. while(!*++ptr) ; // skip 0s
  527. assert(*ptr == ',');
  528. os << ' ' << (ptr + 1);
  529. const char* argptr = ptr;
  530. while(*++argptr) ; // skip type string
  531. while(!*++argptr) ; // skip 0s
  532. char c;
  533. while((c = *++ptr))
  534. {
  535. switch(c)
  536. {
  537. case 'i':
  538. _dump_prim_arg<int32_t>(argptr, os); break;
  539. case 'c':
  540. _dump_prim_arg<int32_t, char>(argptr, os); break;
  541. // case 's':
  542. // _dump_prim_arg<char, const char*>(argptr, os); break;
  543. default:
  544. exit(1);
  545. }
  546. }
  547. }
  548. #endif
  549. int msg_id=0;
  550. /*
  551. * Master audio out (the final sound)
  552. */
  553. void Master::AudioOut(float *outl, float *outr)
  554. {
  555. //Danger Limits
  556. if(memory->lowMemory(2,1024*1024))
  557. printf("QUITE LOW MEMORY IN THE RT POOL BE PREPARED FOR WEIRD BEHAVIOR!!\n");
  558. //Normal Limits
  559. if(!pendingMemory && memory->lowMemory(4,1024*1024)) {
  560. printf("Requesting more memory\n");
  561. bToU->write("/request-memory", "");
  562. pendingMemory = true;
  563. }
  564. //Handle user events TODO move me to a proper location
  565. char loc_buf[1024];
  566. DataObj d{loc_buf, 1024, this, bToU};
  567. memset(loc_buf, 0, sizeof(loc_buf));
  568. int events = 0;
  569. while(uToB && uToB->hasNext() && events < 100) {
  570. const char *msg = uToB->read();
  571. if(!strcmp(msg, "/load-master")) {
  572. Master *this_master = this;
  573. Master *new_master = *(Master**)rtosc_argument(msg, 0).b.data;
  574. new_master->AudioOut(outl, outr);
  575. Nio::masterSwap(new_master);
  576. if (mastercb)
  577. mastercb(mastercb_ptr, new_master);
  578. bToU->write("/free", "sb", "Master", sizeof(Master*), &this_master);
  579. return;
  580. }
  581. //XXX yes, this is not realtime safe, but it is useful...
  582. if(strcmp(msg, "/get-vu") && false) {
  583. fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 5 + 30, 0 + 40);
  584. fprintf(stdout, "backend[%d]: '%s'<%s>\n", msg_id++, msg,
  585. rtosc_argument_string(msg));
  586. fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
  587. }
  588. ports.dispatch(msg, d, true);
  589. events++;
  590. if(!d.matches) {// && !ports.apropos(msg)) {
  591. fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
  592. fprintf(stderr, "Unknown address<BACKEND> '%s:%s'\n", uToB->peak(), rtosc_argument_string(uToB->peak()));
  593. #if 0
  594. if(strstr(msg, "PFMVelocity"))
  595. dump_msg(msg);
  596. if(ports.apropos(msg))
  597. fprintf(stderr, " -> best match: '%s'\n", ports.apropos(msg)->name);
  598. if(ports.apropos(msg+1))
  599. fprintf(stderr, " -> best match: '%s'\n", ports.apropos(msg+1)->name);
  600. #endif
  601. fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
  602. }
  603. }
  604. if(events>1 && false)
  605. fprintf(stderr, "backend: %d events per cycle\n",events);
  606. //Swaps the Left channel with Right Channel
  607. if(swaplr)
  608. swap(outl, outr);
  609. //clean up the output samples (should not be needed?)
  610. memset(outl, 0, synth.bufferbytes);
  611. memset(outr, 0, synth.bufferbytes);
  612. //Compute part samples and store them part[npart]->partoutl,partoutr
  613. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  614. if(part[npart]->Penabled)
  615. part[npart]->ComputePartSmps();
  616. //Insertion effects
  617. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  618. if(Pinsparts[nefx] >= 0) {
  619. int efxpart = Pinsparts[nefx];
  620. if(part[efxpart]->Penabled)
  621. insefx[nefx]->out(part[efxpart]->partoutl,
  622. part[efxpart]->partoutr);
  623. }
  624. //Apply the part volumes and pannings (after insertion effects)
  625. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  626. if(!part[npart]->Penabled)
  627. continue;
  628. Stereo<float> newvol(part[npart]->volume),
  629. oldvol(part[npart]->oldvolumel,
  630. part[npart]->oldvolumer);
  631. float pan = part[npart]->panning;
  632. if(pan < 0.5f)
  633. newvol.l *= pan * 2.0f;
  634. else
  635. newvol.r *= (1.0f - pan) * 2.0f;
  636. //if(npart==0)
  637. //printf("[%d]vol = %f->%f\n", npart, oldvol.l, newvol.l);
  638. //the volume or the panning has changed and needs interpolation
  639. if(ABOVE_AMPLITUDE_THRESHOLD(oldvol.l, newvol.l)
  640. || ABOVE_AMPLITUDE_THRESHOLD(oldvol.r, newvol.r)) {
  641. for(int i = 0; i < synth.buffersize; ++i) {
  642. Stereo<float> vol(INTERPOLATE_AMPLITUDE(oldvol.l, newvol.l,
  643. i, synth.buffersize),
  644. INTERPOLATE_AMPLITUDE(oldvol.r, newvol.r,
  645. i, synth.buffersize));
  646. part[npart]->partoutl[i] *= vol.l;
  647. part[npart]->partoutr[i] *= vol.r;
  648. }
  649. part[npart]->oldvolumel = newvol.l;
  650. part[npart]->oldvolumer = newvol.r;
  651. }
  652. else {
  653. for(int i = 0; i < synth.buffersize; ++i) { //the volume did not changed
  654. part[npart]->partoutl[i] *= newvol.l;
  655. part[npart]->partoutr[i] *= newvol.r;
  656. }
  657. }
  658. }
  659. //System effects
  660. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) {
  661. if(sysefx[nefx]->geteffect() == 0)
  662. continue; //the effect is disabled
  663. float tmpmixl[synth.buffersize];
  664. float tmpmixr[synth.buffersize];
  665. //Clean up the samples used by the system effects
  666. memset(tmpmixl, 0, synth.bufferbytes);
  667. memset(tmpmixr, 0, synth.bufferbytes);
  668. //Mix the channels according to the part settings about System Effect
  669. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  670. //skip if the part has no output to effect
  671. if(Psysefxvol[nefx][npart] == 0)
  672. continue;
  673. //skip if the part is disabled
  674. if(part[npart]->Penabled == 0)
  675. continue;
  676. //the output volume of each part to system effect
  677. const float vol = sysefxvol[nefx][npart];
  678. for(int i = 0; i < synth.buffersize; ++i) {
  679. tmpmixl[i] += part[npart]->partoutl[i] * vol;
  680. tmpmixr[i] += part[npart]->partoutr[i] * vol;
  681. }
  682. }
  683. // system effect send to next ones
  684. for(int nefxfrom = 0; nefxfrom < nefx; ++nefxfrom)
  685. if(Psysefxsend[nefxfrom][nefx] != 0) {
  686. const float vol = sysefxsend[nefxfrom][nefx];
  687. for(int i = 0; i < synth.buffersize; ++i) {
  688. tmpmixl[i] += sysefx[nefxfrom]->efxoutl[i] * vol;
  689. tmpmixr[i] += sysefx[nefxfrom]->efxoutr[i] * vol;
  690. }
  691. }
  692. sysefx[nefx]->out(tmpmixl, tmpmixr);
  693. //Add the System Effect to sound output
  694. const float outvol = sysefx[nefx]->sysefxgetvolume();
  695. for(int i = 0; i < synth.buffersize; ++i) {
  696. outl[i] += tmpmixl[i] * outvol;
  697. outr[i] += tmpmixr[i] * outvol;
  698. }
  699. }
  700. //Mix all parts
  701. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  702. if(part[npart]->Penabled) //only mix active parts
  703. for(int i = 0; i < synth.buffersize; ++i) { //the volume did not changed
  704. outl[i] += part[npart]->partoutl[i];
  705. outr[i] += part[npart]->partoutr[i];
  706. }
  707. //Insertion effects for Master Out
  708. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  709. if(Pinsparts[nefx] == -2)
  710. insefx[nefx]->out(outl, outr);
  711. //Master Volume
  712. for(int i = 0; i < synth.buffersize; ++i) {
  713. outl[i] *= volume;
  714. outr[i] *= volume;
  715. }
  716. vuUpdate(outl, outr);
  717. //Shutup if it is asked (with fade-out)
  718. if(shutup) {
  719. for(int i = 0; i < synth.buffersize; ++i) {
  720. float tmp = (synth.buffersize_f - i) / synth.buffersize_f;
  721. outl[i] *= tmp;
  722. outr[i] *= tmp;
  723. }
  724. ShutUp();
  725. }
  726. //update the global frame timer
  727. time++;
  728. }
  729. //TODO review the respective code from yoshimi for this
  730. //If memory serves correctly, libsamplerate was used
  731. void Master::GetAudioOutSamples(size_t nsamples,
  732. unsigned samplerate,
  733. float *outl,
  734. float *outr)
  735. {
  736. off_t out_off = 0;
  737. //Fail when resampling rather than doing a poor job
  738. if(synth.samplerate != samplerate) {
  739. printf("darn it: %d vs %d\n", synth.samplerate, samplerate);
  740. return;
  741. }
  742. while(nsamples) {
  743. //use all available samples
  744. if(nsamples >= smps) {
  745. memcpy(outl + out_off, bufl + off, sizeof(float) * smps);
  746. memcpy(outr + out_off, bufr + off, sizeof(float) * smps);
  747. nsamples -= smps;
  748. //generate samples
  749. AudioOut(bufl, bufr);
  750. off = 0;
  751. out_off += smps;
  752. smps = synth.buffersize;
  753. }
  754. else { //use some samples
  755. memcpy(outl + out_off, bufl + off, sizeof(float) * nsamples);
  756. memcpy(outr + out_off, bufr + off, sizeof(float) * nsamples);
  757. smps -= nsamples;
  758. off += nsamples;
  759. nsamples = 0;
  760. }
  761. }
  762. }
  763. Master::~Master()
  764. {
  765. delete []bufl;
  766. delete []bufr;
  767. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  768. delete part[npart];
  769. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  770. delete insefx[nefx];
  771. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx)
  772. delete sysefx[nefx];
  773. delete fft;
  774. delete memory;
  775. }
  776. /*
  777. * Parameter control
  778. */
  779. void Master::setPvolume(char Pvolume_)
  780. {
  781. Pvolume = Pvolume_;
  782. volume = dB2rap((Pvolume - 96.0f) / 96.0f * 40.0f);
  783. }
  784. void Master::setPkeyshift(char Pkeyshift_)
  785. {
  786. Pkeyshift = Pkeyshift_;
  787. keyshift = (int)Pkeyshift - 64;
  788. }
  789. void Master::setPsysefxvol(int Ppart, int Pefx, char Pvol)
  790. {
  791. Psysefxvol[Pefx][Ppart] = Pvol;
  792. sysefxvol[Pefx][Ppart] = powf(0.1f, (1.0f - Pvol / 96.0f) * 2.0f);
  793. }
  794. void Master::setPsysefxsend(int Pefxfrom, int Pefxto, char Pvol)
  795. {
  796. Psysefxsend[Pefxfrom][Pefxto] = Pvol;
  797. sysefxsend[Pefxfrom][Pefxto] = powf(0.1f, (1.0f - Pvol / 96.0f) * 2.0f);
  798. }
  799. /*
  800. * Panic! (Clean up all parts and effects)
  801. */
  802. void Master::ShutUp()
  803. {
  804. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  805. part[npart]->cleanup();
  806. fakepeakpart[npart] = 0;
  807. }
  808. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
  809. insefx[nefx]->cleanup();
  810. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx)
  811. sysefx[nefx]->cleanup();
  812. vuresetpeaks();
  813. shutup = 0;
  814. }
  815. /*
  816. * Reset peaks and clear the "cliped" flag (for VU-meter)
  817. */
  818. void Master::vuresetpeaks()
  819. {
  820. vu.outpeakl = 1e-9;
  821. vu.outpeakr = 1e-9;
  822. vu.maxoutpeakl = 1e-9;
  823. vu.maxoutpeakr = 1e-9;
  824. vu.clipped = 0;
  825. }
  826. void Master::applyparameters(void)
  827. {
  828. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
  829. part[npart]->applyparameters();
  830. }
  831. void Master::initialize_rt(void)
  832. {
  833. for(int i=0; i<NUM_SYS_EFX; ++i)
  834. sysefx[i]->init();
  835. for(int i=0; i<NUM_INS_EFX; ++i)
  836. insefx[i]->init();
  837. for(int i=0; i<NUM_MIDI_PARTS; ++i)
  838. part[i]->initialize_rt();
  839. }
  840. void Master::add2XML(XMLwrapper *xml)
  841. {
  842. xml->addpar("volume", Pvolume);
  843. xml->addpar("key_shift", Pkeyshift);
  844. xml->addparbool("nrpn_receive", ctl.NRPN.receive);
  845. xml->beginbranch("MICROTONAL");
  846. microtonal.add2XML(xml);
  847. xml->endbranch();
  848. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  849. xml->beginbranch("PART", npart);
  850. part[npart]->add2XML(xml);
  851. xml->endbranch();
  852. }
  853. xml->beginbranch("SYSTEM_EFFECTS");
  854. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) {
  855. xml->beginbranch("SYSTEM_EFFECT", nefx);
  856. xml->beginbranch("EFFECT");
  857. sysefx[nefx]->add2XML(xml);
  858. xml->endbranch();
  859. for(int pefx = 0; pefx < NUM_MIDI_PARTS; ++pefx) {
  860. xml->beginbranch("VOLUME", pefx);
  861. xml->addpar("vol", Psysefxvol[nefx][pefx]);
  862. xml->endbranch();
  863. }
  864. for(int tonefx = nefx + 1; tonefx < NUM_SYS_EFX; ++tonefx) {
  865. xml->beginbranch("SENDTO", tonefx);
  866. xml->addpar("send_vol", Psysefxsend[nefx][tonefx]);
  867. xml->endbranch();
  868. }
  869. xml->endbranch();
  870. }
  871. xml->endbranch();
  872. xml->beginbranch("INSERTION_EFFECTS");
  873. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) {
  874. xml->beginbranch("INSERTION_EFFECT", nefx);
  875. xml->addpar("part", Pinsparts[nefx]);
  876. xml->beginbranch("EFFECT");
  877. insefx[nefx]->add2XML(xml);
  878. xml->endbranch();
  879. xml->endbranch();
  880. }
  881. xml->endbranch();
  882. }
  883. int Master::getalldata(char **data)
  884. {
  885. XMLwrapper *xml = new XMLwrapper();
  886. xml->beginbranch("MASTER");
  887. add2XML(xml);
  888. xml->endbranch();
  889. *data = xml->getXMLdata();
  890. delete (xml);
  891. return strlen(*data) + 1;
  892. }
  893. void Master::putalldata(const char *data)
  894. {
  895. XMLwrapper *xml = new XMLwrapper();
  896. if(!xml->putXMLdata(data)) {
  897. delete (xml);
  898. return;
  899. }
  900. if(xml->enterbranch("MASTER") == 0)
  901. return;
  902. getfromXML(xml);
  903. xml->exitbranch();
  904. delete (xml);
  905. }
  906. int Master::saveXML(const char *filename)
  907. {
  908. XMLwrapper *xml = new XMLwrapper();
  909. xml->beginbranch("MASTER");
  910. add2XML(xml);
  911. xml->endbranch();
  912. int result = xml->saveXMLfile(filename, gzip_compression);
  913. delete (xml);
  914. return result;
  915. }
  916. int Master::loadXML(const char *filename)
  917. {
  918. XMLwrapper *xml = new XMLwrapper();
  919. if(xml->loadXMLfile(filename) < 0) {
  920. delete (xml);
  921. return -1;
  922. }
  923. if(xml->enterbranch("MASTER") == 0)
  924. return -10;
  925. getfromXML(xml);
  926. xml->exitbranch();
  927. delete (xml);
  928. initialize_rt();
  929. return 0;
  930. }
  931. void Master::getfromXML(XMLwrapper *xml)
  932. {
  933. setPvolume(xml->getpar127("volume", Pvolume));
  934. setPkeyshift(xml->getpar127("key_shift", Pkeyshift));
  935. ctl.NRPN.receive = xml->getparbool("nrpn_receive", ctl.NRPN.receive);
  936. part[0]->Penabled = 0;
  937. for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) {
  938. if(xml->enterbranch("PART", npart) == 0)
  939. continue;
  940. part[npart]->getfromXML(xml);
  941. xml->exitbranch();
  942. }
  943. if(xml->enterbranch("MICROTONAL")) {
  944. microtonal.getfromXML(xml);
  945. xml->exitbranch();
  946. }
  947. sysefx[0]->changeeffect(0);
  948. if(xml->enterbranch("SYSTEM_EFFECTS")) {
  949. for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) {
  950. if(xml->enterbranch("SYSTEM_EFFECT", nefx) == 0)
  951. continue;
  952. if(xml->enterbranch("EFFECT")) {
  953. sysefx[nefx]->getfromXML(xml);
  954. xml->exitbranch();
  955. }
  956. for(int partefx = 0; partefx < NUM_MIDI_PARTS; ++partefx) {
  957. if(xml->enterbranch("VOLUME", partefx) == 0)
  958. continue;
  959. setPsysefxvol(partefx, nefx,
  960. xml->getpar127("vol", Psysefxvol[partefx][nefx]));
  961. xml->exitbranch();
  962. }
  963. for(int tonefx = nefx + 1; tonefx < NUM_SYS_EFX; ++tonefx) {
  964. if(xml->enterbranch("SENDTO", tonefx) == 0)
  965. continue;
  966. setPsysefxsend(nefx, tonefx,
  967. xml->getpar127("send_vol",
  968. Psysefxsend[nefx][tonefx]));
  969. xml->exitbranch();
  970. }
  971. xml->exitbranch();
  972. }
  973. xml->exitbranch();
  974. }
  975. if(xml->enterbranch("INSERTION_EFFECTS")) {
  976. for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) {
  977. if(xml->enterbranch("INSERTION_EFFECT", nefx) == 0)
  978. continue;
  979. Pinsparts[nefx] = xml->getpar("part",
  980. Pinsparts[nefx],
  981. -2,
  982. NUM_MIDI_PARTS);
  983. if(xml->enterbranch("EFFECT")) {
  984. insefx[nefx]->getfromXML(xml);
  985. xml->exitbranch();
  986. }
  987. xml->exitbranch();
  988. }
  989. xml->exitbranch();
  990. }
  991. }