jack2 codebase
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.

537 lines
15KB

  1. /*
  2. Copyright (C) 2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. /* link with */
  16. #include <math.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <limits.h>
  21. #include <math.h>
  22. #include <errno.h>
  23. #include <time.h>
  24. #include <vector>
  25. #include <stack>
  26. #include <string>
  27. #include <map>
  28. #include <iostream>
  29. #include <libgen.h>
  30. #include <jack/jack.h>
  31. // g++ -O3 -lm -lsndfile myfx.cpp
  32. using namespace std;
  33. #define max(x,y) (((x)>(y)) ? (x) : (y))
  34. #define min(x,y) (((x)<(y)) ? (x) : (y))
  35. // abs is now predefined
  36. //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
  37. inline int lsr (int x, int n)
  38. {
  39. return int(((unsigned int)x) >> n);
  40. }
  41. /******************************************************************************
  42. *******************************************************************************
  43. VECTOR INTRINSICS
  44. *******************************************************************************
  45. *******************************************************************************/
  46. inline void *aligned_calloc(size_t nmemb, size_t size)
  47. {
  48. return (void*)((unsigned)(calloc((nmemb*size) + 15, sizeof(char))) + 15 & 0xfffffff0);
  49. }
  50. /******************************************************************************
  51. *******************************************************************************
  52. USER INTERFACE
  53. *******************************************************************************
  54. *******************************************************************************/
  55. class UI
  56. {
  57. bool fStopped;
  58. public:
  59. UI() : fStopped(false)
  60. {}
  61. virtual ~UI()
  62. {}
  63. // -- active widgets
  64. virtual void addButton(char* label, float* zone) = 0;
  65. virtual void addToggleButton(char* label, float* zone) = 0;
  66. virtual void addCheckButton(char* label, float* zone) = 0;
  67. virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
  68. virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
  69. virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0;
  70. // -- passive widgets
  71. virtual void addNumDisplay(char* label, float* zone, int precision) = 0;
  72. virtual void addTextDisplay(char* label, float* zone, char* names[], float min, float max) = 0;
  73. virtual void addHorizontalBargraph(char* label, float* zone, float min, float max) = 0;
  74. virtual void addVerticalBargraph(char* label, float* zone, float min, float max) = 0;
  75. // -- frames and labels
  76. virtual void openFrameBox(char* label) = 0;
  77. virtual void openTabBox(char* label) = 0;
  78. virtual void openHorizontalBox(char* label) = 0;
  79. virtual void openVerticalBox(char* label) = 0;
  80. virtual void closeBox() = 0;
  81. virtual void show() = 0;
  82. virtual void run() = 0;
  83. void stop()
  84. {
  85. fStopped = true;
  86. }
  87. bool stopped()
  88. {
  89. return fStopped;
  90. }
  91. };
  92. struct param
  93. {
  94. float* fZone;
  95. float fMin;
  96. float fMax;
  97. param(float* z, float a, float b) : fZone(z), fMin(a), fMax(b)
  98. {}
  99. };
  100. class CMDUI : public UI
  101. {
  102. int fArgc;
  103. char** fArgv;
  104. stack<string> fPrefix;
  105. map<string, param> fKeyParam;
  106. void addOption(char* label, float* zone, float min, float max)
  107. {
  108. string fullname = fPrefix.top() + label;
  109. fKeyParam.insert(make_pair(fullname, param(zone, min, max)));
  110. }
  111. void openAnyBox(char* label)
  112. {
  113. string prefix;
  114. if (label && label[0]) {
  115. prefix = fPrefix.top() + "-" + label;
  116. } else {
  117. prefix = fPrefix.top();
  118. }
  119. fPrefix.push(prefix);
  120. }
  121. public:
  122. CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv)
  123. {
  124. fPrefix.push("--");
  125. }
  126. virtual ~CMDUI()
  127. {}
  128. virtual void addButton(char* label, float* zone)
  129. {}
  130. ;
  131. virtual void addToggleButton(char* label, float* zone)
  132. {}
  133. ;
  134. virtual void addCheckButton(char* label, float* zone)
  135. {}
  136. ;
  137. virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step)
  138. {
  139. addOption(label, zone, min, max);
  140. }
  141. virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step)
  142. {
  143. addOption(label, zone, min, max);
  144. }
  145. virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step)
  146. {
  147. addOption(label, zone, min, max);
  148. }
  149. // -- passive widgets
  150. virtual void addNumDisplay(char* label, float* zone, int precision)
  151. {}
  152. virtual void addTextDisplay(char* label, float* zone, char* names[], float min, float max)
  153. {}
  154. virtual void addHorizontalBargraph(char* label, float* zone, float min, float max)
  155. {}
  156. virtual void addVerticalBargraph(char* label, float* zone, float min, float max)
  157. {}
  158. virtual void openFrameBox(char* label)
  159. {
  160. openAnyBox(label);
  161. }
  162. virtual void openTabBox(char* label)
  163. {
  164. openAnyBox(label);
  165. }
  166. virtual void openHorizontalBox(char* label)
  167. {
  168. openAnyBox(label);
  169. }
  170. virtual void openVerticalBox(char* label)
  171. {
  172. openAnyBox(label);
  173. }
  174. virtual void closeBox()
  175. {
  176. fPrefix.pop();
  177. }
  178. virtual void show()
  179. {}
  180. virtual void run()
  181. {
  182. char c;
  183. printf("Type 'q' to quit\n");
  184. while ((c = getchar()) != 'q') {
  185. sleep(1);
  186. }
  187. }
  188. void print()
  189. {
  190. map<string, param>::iterator i;
  191. cout << fArgc << "\n";
  192. cout << fArgv[0] << " option list : ";
  193. for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) {
  194. cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax << " ] ";
  195. }
  196. //cout << " infile outfile\n";
  197. }
  198. void process_command()
  199. {
  200. map<string, param>::iterator p;
  201. for (int i = 1; i < fArgc; i++) {
  202. if (fArgv[i][0] == '-') {
  203. p = fKeyParam.find(fArgv[i]);
  204. if (p == fKeyParam.end()) {
  205. cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
  206. print();
  207. exit(1);
  208. }
  209. char* end;
  210. *(p->second.fZone) = float(strtod(fArgv[i + 1], &end));
  211. i++;
  212. }
  213. }
  214. }
  215. void process_init()
  216. {
  217. map<string, param>::iterator p;
  218. for (int i = 1; i < fArgc; i++) {
  219. if (fArgv[i][0] == '-') {
  220. p = fKeyParam.find(fArgv[i]);
  221. if (p == fKeyParam.end()) {
  222. cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
  223. exit(1);
  224. }
  225. char* end;
  226. *(p->second.fZone) = float(strtod(fArgv[i + 1], &end));
  227. i++;
  228. }
  229. }
  230. }
  231. };
  232. //----------------------------------------------------------------
  233. // d�inition du processeur de signal
  234. //----------------------------------------------------------------
  235. class dsp
  236. {
  237. protected:
  238. int fSamplingFreq;
  239. public:
  240. dsp()
  241. {}
  242. virtual ~dsp()
  243. {}
  244. virtual int getNumInputs() = 0;
  245. virtual int getNumOutputs() = 0;
  246. virtual void buildUserInterface(UI* interface) = 0;
  247. virtual void init(int samplingRate) = 0;
  248. virtual void compute(int len, float** inputs, float** outputs) = 0;
  249. virtual void conclude()
  250. {}
  251. };
  252. //----------------------------------------------------------------------------
  253. // FAUST generated code
  254. //----------------------------------------------------------------------------
  255. class mydsp : public dsp
  256. {
  257. private:
  258. class SIG0
  259. {
  260. private:
  261. int fSamplingFreq;
  262. public:
  263. int getNumInputs()
  264. {
  265. return 0;
  266. }
  267. int getNumOutputs()
  268. {
  269. return 1;
  270. }
  271. void init(int samplingFreq)
  272. {
  273. fSamplingFreq = samplingFreq;
  274. }
  275. void fill (int count, float output[])
  276. {
  277. for (int i = 0; i < count; i++) {
  278. output[i] = 0.000000f;
  279. }
  280. }
  281. };
  282. float R0_0;
  283. float fslider0;
  284. float ftbl0[65536];
  285. int R1_0;
  286. float fdata0;
  287. float fslider1;
  288. public:
  289. virtual int getNumInputs()
  290. {
  291. return 1;
  292. }
  293. virtual int getNumOutputs()
  294. {
  295. return 1;
  296. }
  297. virtual void init(int samplingFreq)
  298. {
  299. fSamplingFreq = samplingFreq;
  300. R0_0 = 0.0;
  301. fslider0 = 0.000000f;
  302. SIG0 sig0;
  303. sig0.init(samplingFreq);
  304. sig0.fill(65536, ftbl0);
  305. R1_0 = 0;
  306. fdata0 = (1.000000e-03f * fSamplingFreq);
  307. fslider1 = 0.000000f;
  308. }
  309. virtual void buildUserInterface(UI* interface)
  310. {
  311. interface->openVerticalBox("echo-simple");
  312. interface->openVerticalBox("echo 1000");
  313. interface->addHorizontalSlider("feedback", &fslider0, 0.000000f, 0.000000f, 100.000000f, 0.100000f);
  314. interface->addHorizontalSlider("millisecond", &fslider1, 0.000000f, 0.000000f, 1000.000000f, 0.100000f);
  315. interface->closeBox();
  316. interface->closeBox();
  317. }
  318. virtual void compute (int count, float** input, float** output)
  319. {
  320. float* input0 __attribute__ ((aligned(16)));
  321. input0 = input[0];
  322. float* output0 __attribute__ ((aligned(16)));
  323. output0 = output[0];
  324. float ftemp0 = (1.000000e-02f * fslider0);
  325. int itemp0 = int((int((fdata0 * fslider1)) - 1));
  326. for (int i = 0; i < count; i++) {
  327. R1_0 = ((1 + R1_0) & 65535);
  328. ftbl0[R1_0] = R0_0;
  329. R0_0 = (input0[i] + (ftemp0 * ftbl0[((R1_0 - itemp0) & 65535)]));
  330. output0[i] = R0_0;
  331. }
  332. }
  333. };
  334. mydsp DSP;
  335. /******************************************************************************
  336. *******************************************************************************
  337. JACK AUDIO INTERFACE
  338. *******************************************************************************
  339. *******************************************************************************/
  340. //----------------------------------------------------------------------------
  341. // number of input and output channels
  342. //----------------------------------------------------------------------------
  343. int gNumInChans;
  344. int gNumOutChans;
  345. //----------------------------------------------------------------------------
  346. // Jack ports
  347. //----------------------------------------------------------------------------
  348. jack_port_t *input_ports[256];
  349. jack_port_t *output_ports[256];
  350. //----------------------------------------------------------------------------
  351. // tables of noninterleaved input and output channels for FAUST
  352. //----------------------------------------------------------------------------
  353. float* gInChannel[256];
  354. float* gOutChannel[256];
  355. //----------------------------------------------------------------------------
  356. // Jack Callbacks
  357. //----------------------------------------------------------------------------
  358. int srate(jack_nframes_t nframes, void *arg)
  359. {
  360. printf("the sample rate is now %u/sec\n", nframes);
  361. return 0;
  362. }
  363. void jack_shutdown(void *arg)
  364. {
  365. exit(1);
  366. }
  367. int process (jack_nframes_t nframes, void *arg)
  368. {
  369. for (int i = 0; i < gNumInChans; i++) {
  370. gInChannel[i] = (float *)jack_port_get_buffer(input_ports[i], nframes);
  371. }
  372. for (int i = 0; i < gNumOutChans; i++) {
  373. gOutChannel[i] = (float *)jack_port_get_buffer(output_ports[i], nframes);
  374. }
  375. DSP.compute(nframes, gInChannel, gOutChannel);
  376. return 0;
  377. }
  378. //-------------------------------------------------------------------------
  379. // MAIN
  380. //-------------------------------------------------------------------------
  381. int main(int argc, char *argv[] )
  382. {
  383. char jackname[256];
  384. char** physicalInPorts;
  385. char** physicalOutPorts;
  386. jack_client_t* client;
  387. CMDUI* interface = new CMDUI(argc, argv);
  388. DSP.buildUserInterface(interface);
  389. snprintf(jackname, 255, "%s", basename(argv[0]));
  390. if ((client = jack_client_new(jackname)) == 0) {
  391. fprintf(stderr, "jack server not running?\n");
  392. return 1;
  393. }
  394. jack_set_process_callback(client, process, 0);
  395. jack_set_sample_rate_callback(client, srate, 0);
  396. jack_on_shutdown(client, jack_shutdown, 0);
  397. gNumInChans = DSP.getNumInputs();
  398. gNumOutChans = DSP.getNumOutputs();
  399. for (int i = 0; i < gNumInChans; i++) {
  400. char buf[256];
  401. snprintf(buf, 256, "in_%d", i);
  402. input_ports[i] = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
  403. }
  404. for (int i = 0; i < gNumOutChans; i++) {
  405. char buf[256];
  406. snprintf(buf, 256, "out_%d", i);
  407. output_ports[i] = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  408. }
  409. DSP.init(jack_get_sample_rate(client));
  410. DSP.buildUserInterface(interface);
  411. interface->process_command();
  412. physicalInPorts = (char **)jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
  413. physicalOutPorts = (char **)jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
  414. if (jack_activate(client)) {
  415. fprintf(stderr, "cannot activate client");
  416. return 1;
  417. }
  418. if (physicalOutPorts != NULL) {
  419. for (int i = 0; i < gNumInChans && physicalOutPorts[i]; i++) {
  420. jack_connect(client, physicalOutPorts[i], jack_port_name(input_ports[i]));
  421. }
  422. }
  423. if (physicalInPorts != NULL) {
  424. for (int i = 0; i < gNumOutChans && physicalInPorts[i]; i++) {
  425. jack_connect(client, jack_port_name(output_ports[i]), physicalInPorts[i]);
  426. }
  427. }
  428. interface->run();
  429. jack_deactivate(client);
  430. for (int i = 0; i < gNumInChans; i++) {
  431. jack_port_unregister(client, input_ports[i]);
  432. }
  433. for (int i = 0; i < gNumOutChans; i++) {
  434. jack_port_unregister(client, output_ports[i]);
  435. }
  436. jack_client_close(client);
  437. return 0;
  438. }