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.

268 lines
6.3KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. OssMultiEngine.cpp - Multi channel audio output for Open Sound System
  4. Copyright (C) 2014 Hans Petter Selasky
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. #include <cstring>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <fcntl.h>
  14. #include <errno.h>
  15. #include <sys/soundcard.h>
  16. #include <sys/stat.h>
  17. #include <sys/ioctl.h>
  18. #include <unistd.h>
  19. #include <iostream>
  20. #include <signal.h>
  21. #include "Nio.h"
  22. #include "../Misc/Master.h"
  23. #include "../Misc/Part.h"
  24. #include "../Misc/MiddleWare.h"
  25. #include "../Misc/Util.h"
  26. #include "OssMultiEngine.h"
  27. #include "Compressor.h"
  28. extern MiddleWare *middleware;
  29. using namespace std;
  30. OssMultiEngine :: OssMultiEngine(const SYNTH_T &synth,
  31. const oss_devs_t &oss_devs)
  32. :AudioOut(synth),
  33. linux_oss_wave_out_dev(oss_devs.linux_wave_out)
  34. {
  35. /* setup variables */
  36. name = "OSS-MULTI";
  37. audioThread = 0;
  38. handle = -1;
  39. channels = 0;
  40. en = false;
  41. is32bit = false;
  42. buffersize = 0;
  43. /* compute worst case buffer size */
  44. maxbuffersize = NUM_MIDI_PARTS * sizeof(int) * synth.buffersize * 2;
  45. /* allocate buffer */
  46. smps.ps32 = new int[maxbuffersize / sizeof(int)];
  47. memset(smps.ps32, 0, maxbuffersize);
  48. /* setup compressor */
  49. unsigned peaksize = NUM_MIDI_PARTS * sizeof(float);
  50. peaks = new float[peaksize / sizeof(float)];
  51. memset(peaks, 0, peaksize);
  52. }
  53. OssMultiEngine :: ~OssMultiEngine()
  54. {
  55. Stop();
  56. delete [] smps.ps32;
  57. delete [] peaks;
  58. }
  59. bool
  60. OssMultiEngine :: openAudio()
  61. {
  62. int snd_samplerate;
  63. int snd_fragment;
  64. int x;
  65. /* check if already open */
  66. if (handle != -1)
  67. return (true);
  68. const char *device = getenv("DSP_DEVICE");
  69. if(device == 0)
  70. device = linux_oss_wave_out_dev;
  71. /* NOTE: PIPEs and FIFOs can block when opening them */
  72. handle = open(device, O_WRONLY, O_NONBLOCK);
  73. if (handle == -1) {
  74. cerr << "ERROR - I can't open the "
  75. << device << '.' << endl;
  76. return (false);
  77. }
  78. ioctl(handle, SNDCTL_DSP_RESET, 0);
  79. /* Figure out the correct format first */
  80. int snd_format16 = AFMT_S16_NE;
  81. #ifdef AFMT_S32_NE
  82. int snd_format32 = AFMT_S32_NE;
  83. if (ioctl(handle, SNDCTL_DSP_SETFMT, &snd_format32) == 0) {
  84. is32bit = true;
  85. } else
  86. #endif
  87. if (ioctl(handle, SNDCTL_DSP_SETFMT, &snd_format16) == 0) {
  88. is32bit = false;
  89. } else {
  90. cerr << "ERROR - Cannot set DSP format for "
  91. << device << '.' << endl;
  92. goto error;
  93. }
  94. for (x = NUM_MIDI_PARTS * 2; x >= 2; x -= 2) {
  95. if (ioctl(handle, SNDCTL_DSP_CHANNELS, &x) == 0)
  96. break;
  97. }
  98. if (x == 0) {
  99. cerr << "ERROR - Cannot set DSP channels for "
  100. << device << '.' << endl;
  101. goto error;
  102. }
  103. channels = x;
  104. snd_samplerate = synth.samplerate;
  105. ioctl(handle, SNDCTL_DSP_SPEED, &snd_samplerate);
  106. if (snd_samplerate != (int)synth.samplerate) {
  107. cerr << "ERROR - Cannot set samplerate for "
  108. << device << ". " << snd_samplerate
  109. << " != " << synth.samplerate << endl;
  110. goto error;
  111. }
  112. /* compute buffer size for 16-bit samples */
  113. buffersize = 2 * synth.buffersize * channels;
  114. if (is32bit)
  115. buffersize *= 2;
  116. for (x = 4; x < 20; x++) {
  117. if ((1 << x) >= buffersize)
  118. break;
  119. }
  120. snd_fragment = 0x20000 | x; /* 2x buffer */
  121. ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment);
  122. pthread_attr_t attr;
  123. pthread_attr_init(&attr);
  124. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  125. pthread_create(&audioThread, &attr, _audioThreadCb, this);
  126. return (true);
  127. error:
  128. close(handle);
  129. handle = -1;
  130. return (false);
  131. }
  132. void
  133. OssMultiEngine :: stopAudio()
  134. {
  135. int fd = handle;
  136. /* check if already closed */
  137. if (fd == -1)
  138. return;
  139. handle = -1;
  140. /* close handle first, so that write() exits */
  141. close(fd);
  142. pthread_join(audioThread, 0);
  143. audioThread = 0;
  144. }
  145. bool
  146. OssMultiEngine :: Start()
  147. {
  148. return (openAudio());
  149. }
  150. void
  151. OssMultiEngine :: Stop()
  152. {
  153. stopAudio();
  154. }
  155. void
  156. OssMultiEngine :: setAudioEn(bool enable)
  157. {
  158. if (enable)
  159. openAudio();
  160. else
  161. stopAudio();
  162. }
  163. bool
  164. OssMultiEngine :: getAudioEn() const
  165. {
  166. return (handle != -1);
  167. }
  168. void *
  169. OssMultiEngine :: _audioThreadCb(void *arg)
  170. {
  171. return (static_cast<OssMultiEngine *>(arg))->audioThreadCb();
  172. }
  173. void *
  174. OssMultiEngine :: audioThreadCb()
  175. {
  176. /*
  177. * In case the audio device is a PIPE/FIFO, we need to ignore
  178. * any PIPE signals:
  179. */
  180. signal(SIGPIPE, SIG_IGN);
  181. set_realtime();
  182. while(getAudioEn()) {
  183. int error;
  184. int x;
  185. int y;
  186. /* get next buffer */
  187. getNext();
  188. /* extract audio from the "channels / 2" first parts */
  189. for (x = 0; x != channels; x += 2) {
  190. Part *part = middleware->spawnMaster()->part[x / 2];
  191. if (is32bit) {
  192. for (y = 0; y != synth.buffersize; y++) {
  193. float l = part->partoutl[y];
  194. float r = part->partoutr[y];
  195. stereoCompressor(synth.samplerate, peaks[x/2], l, r);
  196. smps.ps32[y * channels + x] = (int)(l * 2147483647.0f);
  197. smps.ps32[y * channels + x + 1] = (int)(r * 2147483647.0f);
  198. }
  199. } else {
  200. for (y = 0; y != synth.buffersize; y++) {
  201. float l = part->partoutl[y];
  202. float r = part->partoutr[y];
  203. stereoCompressor(synth.samplerate, peaks[x/2], l, r);
  204. smps.ps16[y * channels + x] = (short int)(l * 32767.0f);
  205. smps.ps16[y * channels + x + 1] = (short int)(r * 32767.0f);
  206. }
  207. }
  208. }
  209. /* write audio buffer to DSP device */
  210. do {
  211. /* make a copy of handle, in case of OSS audio disable */
  212. int fd = handle;
  213. if (fd == -1)
  214. goto done;
  215. error = write(fd, smps.ps32, buffersize);
  216. } while (error == -1 && errno == EINTR);
  217. if(error == -1)
  218. goto done;
  219. }
  220. done:
  221. pthread_exit(0);
  222. return (0);
  223. }