Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. #/************************************************************************
  2.  
  3. IMPORTANT NOTE : this file contains two clearly delimited sections :
  4. the ARCHITECTURE section (in two parts) and the USER section. Each section
  5. is governed by its own copyright and license. Please check individually
  6. each section for license and copyright information.
  7. *************************************************************************/
  8.  
  9. /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
  10.  
  11. /************************************************************************
  12.  
  13. Bela FAUST Architecture file
  14. Oli Larkin 2016
  15. www.olilarkin.co.uk
  16. Based on owl.cpp
  17.  
  18. FAUST Architecture File
  19. Copyright (C) 2003-2014 GRAME, Centre National de Creation Musicale
  20. ---------------------------------------------------------------------
  21. This Architecture section is free software; you can redistribute it
  22. and/or modify it under the terms of the GNU General Public License
  23. as published by the Free Software Foundation; either version 3 of
  24. the License, or (at your option) any later version.
  25.  
  26. This program is distributed in the hope that it will be useful,
  27. but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. GNU General Public License for more details.
  30.  
  31. You should have received a copy of the GNU General Public License
  32. along with this program; If not, see <http://www.gnu.org/licenses/>.
  33.  
  34. EXCEPTION : As a special exception, you may create a larger work
  35. that contains this FAUST architecture section and distribute
  36. that work under terms of your choice, so long as this FAUST
  37. architecture section is not modified.
  38.  
  39. ************************************************************************
  40. ************************************************************************/
  41.  
  42. #ifndef __FaustBela_H__
  43. #define __FaustBela_H__
  44.  
  45. #include <cstddef>
  46. #include <string>
  47. #include <math.h>
  48. #include <strings.h>
  49. #include <cstdlib>
  50. #include <Bela.h>
  51. #include <Utilities.h>
  52.  
  53. using namespace std;
  54.  
  55. #ifndef __FaustCommonInfrastructure__
  56. #define __FaustCommonInfrastructure__
  57.  
  58. #include "faust/dsp/dsp.h"
  59. #include "faust/gui/UI.h"
  60. #include "faust/gui/MidiUI.h"
  61. #include "faust/midi/bela-midi.h"
  62. #include "faust/dsp/llvm-dsp.h"
  63.  
  64. const char * const pinNamesStrings[] =
  65. {
  66. "ANALOG_0",
  67. "ANALOG_1",
  68. "ANALOG_2",
  69. "ANALOG_3",
  70. "ANALOG_4",
  71. "ANALOG_5",
  72. "ANALOG_6",
  73. "ANALOG_7",
  74. "ANALOG_8",
  75. "DIGITAL_0",
  76. "DIGITAL_1",
  77. "DIGITAL_2",
  78. "DIGITAL_3",
  79. "DIGITAL_4",
  80. "DIGITAL_5",
  81. "DIGITAL_6",
  82. "DIGITAL_7",
  83. "DIGITAL_8",
  84. "DIGITAL_9",
  85. "DIGITAL_10",
  86. "DIGITAL_11",
  87. "DIGITAL_12",
  88. "DIGITAL_13",
  89. "DIGITAL_14",
  90. "DIGITAL_15"
  91. };
  92.  
  93. enum EInputPin
  94. {
  95. kNoPin = -1,
  96. kANALOG_0 = 0,
  97. kANALOG_1,
  98. kANALOG_2,
  99. kANALOG_3,
  100. kANALOG_4,
  101. kANALOG_5,
  102. kANALOG_6,
  103. kANALOG_7,
  104. kANALOG_8,
  105. kDIGITAL_0,
  106. kDIGITAL_1,
  107. kDIGITAL_2,
  108. kDIGITAL_3,
  109. kDIGITAL_4,
  110. kDIGITAL_5,
  111. kDIGITAL_6,
  112. kDIGITAL_7,
  113. kDIGITAL_8,
  114. kDIGITAL_9,
  115. kDIGITAL_10,
  116. kDIGITAL_11,
  117. kDIGITAL_12,
  118. kDIGITAL_13,
  119. kDIGITAL_14,
  120. kDIGITAL_15,
  121. kNumInputPins
  122. };
  123.  
  124. /**************************************************************************************
  125.  
  126. BelaWidget : object used by BelaUI to ensures the connection between an Bela parameter
  127. and a faust widget
  128.  
  129. ***************************************************************************************/
  130.  
  131. class BelaWidget
  132. {
  133. protected:
  134. EInputPin fBelaPin;
  135. FAUSTFLOAT* fZone; // Faust widget zone
  136. const char* fLabel; // Faust widget label
  137. float fMin; // Faust widget minimal value
  138. float fRange; // Faust widget value range (max-min)
  139.  
  140. public:
  141. BelaWidget()
  142. : fBelaPin(kNoPin)
  143. , fZone(0)
  144. , fLabel("")
  145. , fMin(0)
  146. , fRange(1)
  147. {}
  148.  
  149. BelaWidget(const BelaWidget& w)
  150. : fBelaPin(w.fBelaPin)
  151. , fZone(w.fZone)
  152. , fLabel(w.fLabel)
  153. , fMin(w.fMin)
  154. , fRange(w.fRange)
  155. {}
  156.  
  157. BelaWidget(EInputPin pin, FAUSTFLOAT* z, const char* l, float lo, float hi)
  158. : fBelaPin(pin)
  159. , fZone(z)
  160. , fLabel(l)
  161. , fMin(lo)
  162. , fRange(hi-lo)
  163. {}
  164.  
  165. void update(BelaContext *context)
  166. {
  167. switch(fBelaPin)
  168. {
  169. case kANALOG_0:
  170. case kANALOG_1:
  171. case kANALOG_2:
  172. case kANALOG_3:
  173. case kANALOG_4:
  174. case kANALOG_5:
  175. case kANALOG_6:
  176. case kANALOG_7:
  177. *fZone = fMin + fRange * analogRead(context, 0 /* TODO: average frame?*/, (int) fBelaPin);
  178. break;
  179. case kDIGITAL_0:
  180. case kDIGITAL_1:
  181. case kDIGITAL_2:
  182. case kDIGITAL_3:
  183. case kDIGITAL_4:
  184. case kDIGITAL_5:
  185. case kDIGITAL_6:
  186. case kDIGITAL_7:
  187. case kDIGITAL_8:
  188. case kDIGITAL_9:
  189. case kDIGITAL_10:
  190. case kDIGITAL_11:
  191. case kDIGITAL_12:
  192. case kDIGITAL_13:
  193. case kDIGITAL_14:
  194. case kDIGITAL_15:
  195. *fZone = digitalRead(context, 0 /* TODO: average frame?*/, ((int) fBelaPin - kDIGITAL_0)) > 0 ? fMin : fMin+fRange;
  196. break;
  197. default:
  198. break;
  199. };
  200. }
  201.  
  202. };
  203.  
  204. /**************************************************************************************
  205.  
  206. BelaUI : Faust User Interface builder. Passed to buildUserInterface BelaUI allows
  207. the mapping between BELA pins and faust widgets. It relies on specific
  208. metadata "...[BELA:DIGITAL_0]..." in the widget's label for that. For example any
  209. faust widget with metadata [BELA:DIGITAL_0] will be controlled by DIGITAL_0
  210. (the second knob).
  211.  
  212. ***************************************************************************************/
  213.  
  214. // The maximun number of mappings between Bela parameters and faust widgets
  215. #define MAXBELAWIDGETS 8
  216.  
  217. class BelaUI : public UI
  218. {
  219. int fIndex; // number of BelaWidgets collected so far
  220. EInputPin fBelaPin; // current pin id
  221. BelaWidget fTable[MAXBELAWIDGETS]; // kind of static list of BelaWidgets
  222.  
  223. // check if the widget is linked to a Bela parameter and, if so, add the corresponding BelaWidget
  224. void addBelaWidget(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT lo, FAUSTFLOAT hi)
  225. {
  226. if (fBelaPin != kNoPin && (fIndex < MAXBELAWIDGETS))
  227. {
  228. fTable[fIndex] = BelaWidget(fBelaPin, zone, label, lo, hi);
  229. fIndex++;
  230. }
  231. fBelaPin = kNoPin;
  232. }
  233.  
  234. // we dont want to create a widget but we clear fBelaPin just in case
  235. void skip() {
  236. fBelaPin = kNoPin;
  237. }
  238.  
  239. public:
  240.  
  241. BelaUI()
  242. : fIndex(0)
  243. , fBelaPin(kNoPin)
  244. {}
  245.  
  246. virtual ~BelaUI() {}
  247.  
  248. // should be called before compute() to update widget's zones registered as Bela parameters
  249. void update(BelaContext *context)
  250. {
  251. for (int i=0; i<fIndex; i++)
  252. fTable[i].update(context);
  253. }
  254.  
  255. //---------------------- virtual methods called by buildUserInterface ----------------
  256.  
  257. // -- widget's layouts
  258. virtual void openTabBox(const char* label) {}
  259. virtual void openHorizontalBox(const char* label) {}
  260. virtual void openVerticalBox(const char* label) {}
  261. virtual void closeBox() {}
  262.  
  263. // -- active widgets
  264. virtual void addButton(const char* label, FAUSTFLOAT* zone) { skip(); }
  265. virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) { skip(); }
  266. virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT lo, FAUSTFLOAT hi, FAUSTFLOAT step) { addBelaWidget(label, zone, lo, hi); }
  267. virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT lo, FAUSTFLOAT hi, FAUSTFLOAT step) { addBelaWidget(label, zone, lo, hi); }
  268. virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT lo, FAUSTFLOAT hi, FAUSTFLOAT step) { addBelaWidget(label, zone, lo, hi); }
  269.  
  270. // -- passive widgets
  271. virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT lo, FAUSTFLOAT hi) { skip(); }
  272. virtual void addVerticalBargraph (const char* label, FAUSTFLOAT* zone, FAUSTFLOAT lo, FAUSTFLOAT hi) { skip(); }
  273.  
  274. // -- metadata declarations
  275. virtual void declare(FAUSTFLOAT* z, const char* k, const char* id) {
  276. if (strcasecmp(k,"BELA") == 0) {
  277. for(int i=0;i<kNumInputPins;i++) {
  278. if (strcasecmp(id, pinNamesStrings[i]) == 0) {
  279. fBelaPin = (EInputPin) i;
  280. }
  281. }
  282. }
  283. }
  284. };
  285.  
  286. #endif // __FaustCommonInfrastructure__
  287.  
  288. /**************************BEGIN USER SECTION **************************/
  289.  
  290. /***************************END USER SECTION ***************************/
  291.  
  292. /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
  293.  
  294. std::list<GUI*> GUI::fGuiList;
  295. ztimedmap GUI::gTimedZoneMap;
  296.  
  297. /**************************************************************************************
  298.  
  299. Bela render.cpp that calls FAUST generated code
  300.  
  301. ***************************************************************************************/
  302.  
  303. unsigned int gNumBuffers = 0; // the number of de-interleaved buffers for audio and analog i/o
  304. float *gInputBuffers = NULL, *gOutputBuffers = NULL; //de-interleaved input/output buffers for the audio and analog inputs
  305. float* gFaustIns[10]; // array of pointers to gInputBuffer data
  306. float* gFaustOuts[10]; // array of pointers to gOutputBuffers data
  307. dsp* fDSP;
  308. BelaUI fUI;
  309. bela_midi fMIDI;
  310. MidiUI* fMidiUI;
  311.  
  312. dsp_factory* fFactory;
  313.  
  314. bool setup(BelaContext *context, void *userData)
  315. {
  316. gNumBuffers = context->audioInChannels
  317. + context->audioOutChannels
  318. + context->analogInChannels
  319. + context->analogOutChannels;
  320. // rt_printf("context->audioFrames %i\n", context->audioFrames);
  321. // rt_printf("context->audioChannels %i\n", context->audioChannels);
  322. // rt_printf("context->analogChannels %i\n", context->analogChannels);
  323. // rt_printf("context->analogFrames %i\n", context->analogFrames);
  324.  
  325. std::string error_msg;
  326. fFactory = createDSPFactoryFromString ("FaustDSP", "random = +(12345)~*(1103515245); noise = random/2147483647.0; \nprocess = noise * vslider(\"Volume[style:knob]\", 0, 0, 1, 0.1);\n", 0, 0, "", error_msg);
  327. fDSP = fFactory->createDSPInstance();
  328.  
  329. fDSP->init(context->audioSampleRate);
  330. fDSP->buildUserInterface(&fUI); // Maps Bela Analog/Digital IO and faust widgets
  331.  
  332. gInputBuffers = (float *) malloc(gNumBuffers * context->audioFrames * sizeof(float));
  333. gOutputBuffers = (float *) malloc(gNumBuffers * context->audioFrames * sizeof(float));
  334.  
  335. if(gInputBuffers == NULL || gOutputBuffers == NULL)
  336. {
  337. rt_printf("setup() failed: couldn't allocated buffers");
  338. return false;
  339. }
  340.  
  341. if(fDSP->getNumInputs() > 10 || fDSP->getNumOutputs() > 10)
  342. {
  343. rt_printf("setup() failed: FAUST DSP has too many i/o");
  344. return false;
  345. }
  346. // create the table of input channels
  347. for(int ch=0; ch<fDSP->getNumInputs(); ++ch)
  348. gFaustIns[ch] = gInputBuffers + (ch * context->audioFrames);
  349.  
  350. // create the table of output channels
  351. for(int ch=0; ch<fDSP->getNumOutputs(); ++ch)
  352. gFaustOuts[ch] = gOutputBuffers + (ch * context->audioFrames);
  353.  
  354. fMidiUI = new MidiUI(&fMIDI);
  355. fDSP->buildUserInterface(fMidiUI);
  356. fMidiUI->run();
  357.  
  358. return true;
  359. }
  360.  
  361. void render(BelaContext *context, void *userData)
  362. {
  363. // De-interleave the input data
  364. for(unsigned int frame = 0; frame < context->audioFrames; frame++)
  365. {
  366. for(unsigned int ch = 0; ch < gNumBuffers; ch++)
  367. {
  368. if(ch >= context->audioInChannels+context->analogInChannels)
  369. break;
  370. if(ch >= context->audioInChannels) // handle analogChannels
  371. {
  372. unsigned int m = frame/2;
  373. float mIn = (float) context->analogIn[m * context->analogInChannels + (ch-context->audioInChannels)];
  374. gInputBuffers[ch * context->audioFrames + frame] = mIn;
  375. }
  376. else // handle audioInChannels
  377. {
  378. gInputBuffers[ch * context->audioFrames + frame] = context->audioIn[frame * context->audioInChannels + ch];
  379. }
  380. }
  381. }
  382.  
  383. // reads Bela pins and updates corresponding Faust Widgets zones
  384. fUI.update(context);
  385. // Process FAUST DSP
  386. fDSP->compute(context->audioFrames, gFaustIns, gFaustOuts);
  387.  
  388. // Interleave the output data
  389. for(unsigned int frame = 0; frame < context->audioFrames; frame++)
  390. {
  391. for(unsigned int ch = 0; ch < gNumBuffers; ch++)
  392. {
  393. if(ch >= context->audioOutChannels+context->analogOutChannels)
  394. break;
  395. else
  396. {
  397. if(ch >= context->audioOutChannels) // handle analogChannels
  398. {
  399. unsigned int m = frame/2;
  400. context->analogOut[m * context->analogFrames + (ch-context->audioOutChannels)] = gOutputBuffers[ch*context->audioFrames + frame];
  401. }
  402. else // handle audioChannels
  403. {
  404. context->audioOut[frame * context->audioOutChannels + ch] = gOutputBuffers[ch * context->audioFrames + frame];
  405. }
  406. }
  407. }
  408. }
  409. }
  410.  
  411. void cleanup(BelaContext *context, void *userData)
  412. {
  413. if(gInputBuffers != NULL)
  414. free(gInputBuffers);
  415. if(gOutputBuffers != NULL)
  416. free(gOutputBuffers);
  417.  
  418. delete fMidiUI;
  419.  
  420. delete fDSP;
  421. deleteDSPFactory(static_cast<llvm_dsp_factory*>(fFactory));
  422. }
  423.  
  424. #endif // __FaustBela_H__
  425.  
  426. ////////////////////////////////////////////////////////////////////////////////////////////////////