zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 9092e7a36562273c6581b5dfa2f3977dbb57edd0
parent aa88b902ca1ff87779c1172f4e35d58ca3b0fb88
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Sat,  1 Nov 2014 11:27:29 -0400

Fix OSS Under Linux

Diffstat:
Msrc/Nio/OssEngine.cpp | 41+++++++++++++++++++++++++----------------
Msrc/Nio/OssMultiEngine.cpp | 424++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Nio/OssMultiEngine.h | 78+++++++++++++++++++++++++++++++++++++++---------------------------------------
3 files changed, 280 insertions(+), 263 deletions(-)

diff --git a/src/Nio/OssEngine.cpp b/src/Nio/OssEngine.cpp @@ -212,7 +212,7 @@ bool OssEngine::openAudio() const char *device = getenv("DSP_DEVICE"); if(device == NULL) - device = config.cfg.LinuxOSSWaveOutDev; + device = config.cfg.LinuxOSSWaveOutDev; /* NOTE: PIPEs and FIFOs can block when opening them */ audio.handle = open(device, O_WRONLY, O_NONBLOCK); @@ -224,6 +224,9 @@ bool OssEngine::openAudio() ioctl(audio.handle, SNDCTL_DSP_RESET, NULL); /* Figure out the correct format first */ +#ifdef __linux__ + int snd_format16 = AFMT_S16_NE; +#else #if defined(AFMT_S16_NE) && defined(AFMT_S32_NE) int snd_format32 = AFMT_S32_NE; int snd_format16 = AFMT_S16_NE; @@ -239,15 +242,21 @@ bool OssEngine::openAudio() int snd_format32 = AFMT_S32_LE; int snd_format16 = AFMT_S16_LE; #endif +#endif - if (ioctl(audio.handle, SNDCTL_DSP_SETFMT, &snd_format32) == 0) { - audio.is32bit = true; +#ifdef __linux__ +#define SND_32_INIT -1 +#else +#define SND_32_INIT ioctl(audio.handle, SNDCTL_DSP_SETFMT, &snd_format32) +#endif + if (SND_32_INIT == 0) { + audio.is32bit = true; } else if (ioctl(audio.handle, SNDCTL_DSP_SETFMT, &snd_format16) == 0) { - audio.is32bit = false; + audio.is32bit = false; } else { - cerr << "ERROR - I cannot set DSP format for " - << device << '.' << endl; - goto error; + cerr << "ERROR - I cannot set DSP format for " + << device << '.' << endl; + goto error; } ioctl(audio.handle, SNDCTL_DSP_STEREO, &snd_stereo); ioctl(audio.handle, SNDCTL_DSP_SPEED, &snd_samplerate); @@ -359,7 +368,7 @@ bool OssEngine::openMidi() const char *device = getenv("MIDI_DEVICE"); if(device == NULL) - device = config.cfg.LinuxOSSSeqInDev; + device = config.cfg.LinuxOSSSeqInDev; /* NOTE: PIPEs and FIFOs can block when opening them */ handle = open(device, O_RDONLY, O_NONBLOCK); @@ -431,13 +440,13 @@ void *OssEngine::audioThreadCb() if(r > 1.0f) r = 1.0f; - if (audio.is32bit) { - audio.smps.ps32[i * 2] = (int) (l * 2147483647.0f); - audio.smps.ps32[i * 2 + 1] = (int) (r * 2147483647.0f); - } else { /* 16bit */ - audio.smps.ps16[i * 2] = (short int) (l * 32767.0f); - audio.smps.ps16[i * 2 + 1] = (short int) (r * 32767.0f); - } + if (audio.is32bit) { + audio.smps.ps32[i * 2] = (int) (l * 2147483647.0f); + audio.smps.ps32[i * 2 + 1] = (int) (r * 2147483647.0f); + } else {/* 16bit */ + audio.smps.ps16[i * 2] = (short int) (l * 32767.0f); + audio.smps.ps16[i * 2 + 1] = (short int) (r * 32767.0f); + } } int error; @@ -446,7 +455,7 @@ void *OssEngine::audioThreadCb() int handle = audio.handle; if(handle == -1) goto done; - error = write(handle, audio.smps.ps32, audio.buffersize); + error = write(handle, audio.smps.ps32, audio.buffersize); } while (error == -1 && errno == EINTR); if(error == -1) diff --git a/src/Nio/OssMultiEngine.cpp b/src/Nio/OssMultiEngine.cpp @@ -1,21 +1,21 @@ /* - ZynAddSubFX - a software synthesizer + ZynAddSubFX - a software synthesizer - OssMultiEngine.cpp - Multi channel audio output for Open Sound System - Copyright (C) 2014 Hans Petter Selasky + OssMultiEngine.cpp - Multi channel audio output for Open Sound System + Copyright (C) 2014 Hans Petter Selasky - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -45,250 +45,258 @@ using namespace std; OssMultiEngine :: OssMultiEngine() { - /* setup variables */ - name = "OSS-MULTI"; - audioThread = 0; - handle = -1; - channels = 0; - en = false; - is32bit = false; - buffersize = 0; - - /* compute worst case buffer size */ - maxbuffersize = NUM_MIDI_PARTS * sizeof(int) * synth->buffersize * 2; - /* allocate buffer */ - smps.ps32 = new int[maxbuffersize / sizeof(int)]; - memset(smps.ps32, 0, maxbuffersize); + /* setup variables */ + name = "OSS-MULTI"; + audioThread = 0; + handle = -1; + channels = 0; + en = false; + is32bit = false; + buffersize = 0; + + /* compute worst case buffer size */ + maxbuffersize = NUM_MIDI_PARTS * sizeof(int) * synth->buffersize * 2; + /* allocate buffer */ + smps.ps32 = new int[maxbuffersize / sizeof(int)]; + memset(smps.ps32, 0, maxbuffersize); } OssMultiEngine :: ~OssMultiEngine() { - Stop(); - delete [] smps.ps32; + Stop(); + delete [] smps.ps32; } -bool + bool OssMultiEngine :: openAudio() { - int snd_samplerate; - int snd_format32; - int snd_format16; - int snd_fragment; - int x; - - /* check if already open */ - if (handle != -1) - return (true); - - const char *device = getenv("DSP_DEVICE"); - if(device == 0) - device = config.cfg.LinuxOSSWaveOutDev; - - /* NOTE: PIPEs and FIFOs can block when opening them */ - handle = open(device, O_WRONLY, O_NONBLOCK); - if (handle == -1) { - cerr << "ERROR - I can't open the " - << device << '.' << endl; - return (false); - } - ioctl(handle, SNDCTL_DSP_RESET, 0); - - /* Figure out the correct format first */ + int snd_samplerate; + int snd_fragment; + int x; + + /* check if already open */ + if (handle != -1) + return (true); + + const char *device = getenv("DSP_DEVICE"); + if(device == 0) + device = config.cfg.LinuxOSSWaveOutDev; + + /* NOTE: PIPEs and FIFOs can block when opening them */ + handle = open(device, O_WRONLY, O_NONBLOCK); + if (handle == -1) { + cerr << "ERROR - I can't open the " + << device << '.' << endl; + return (false); + } + ioctl(handle, SNDCTL_DSP_RESET, 0); + + /* Figure out the correct format first */ +#ifdef __linux__ + int snd_format16 = AFMT_S16_NE; +#else #if defined(AFMT_S16_NE) && defined(AFMT_S32_NE) - snd_format32 = AFMT_S32_NE; - snd_format16 = AFMT_S16_NE; + int snd_format32 = AFMT_S32_NE; + int snd_format16 = AFMT_S16_NE; #elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) #if BYTE_ORDER == LITTLE_ENDIAN - snd_format32 = AFMT_S32_LE; - snd_format16 = AFMT_S16_LE; + int snd_format32 = AFMT_S32_LE; + int snd_format16 = AFMT_S16_LE; #else - snd_format32 = AFMT_S32_BE; - snd_format16 = AFMT_S16_BE; + int snd_format32 = AFMT_S32_BE; + int snd_format16 = AFMT_S16_BE; #endif #else - snd_format32 = AFMT_S32_LE; - snd_format16 = AFMT_S16_LE; + int snd_format32 = AFMT_S32_LE; + int snd_format16 = AFMT_S16_LE; +#endif #endif - if (ioctl(handle, SNDCTL_DSP_SETFMT, &snd_format32) == 0) { - is32bit = true; - } else if (ioctl(handle, SNDCTL_DSP_SETFMT, &snd_format16) == 0) { - is32bit = false; - } else { - cerr << "ERROR - Cannot set DSP format for " - << device << '.' << endl; - goto error; - } - for (x = NUM_MIDI_PARTS * 2; x >= 2; x -= 2) { - if (ioctl(handle, SNDCTL_DSP_CHANNELS, &x) == 0) - break; - } - if (x == 0) { - cerr << "ERROR - Cannot set DSP channels for " - << device << '.' << endl; - goto error; - } - channels = x; - - snd_samplerate = synth->samplerate; - - ioctl(handle, SNDCTL_DSP_SPEED, &snd_samplerate); - - if (snd_samplerate != (int)synth->samplerate) { - cerr << "ERROR - Cannot set samplerate for " - << device << ". " << snd_samplerate - << " != " << synth->samplerate << endl; - goto error; - } - - /* compute buffer size for 16-bit samples */ - buffersize = 2 * synth->buffersize * channels; - if (is32bit) - buffersize *= 2; - - for (x = 4; x < 20; x++) { - if ((1 << x) >= buffersize) - break; - } - - snd_fragment = 0x20000 | x; /* 2x buffer */ - - ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_create(&audioThread, &attr, _audioThreadCb, this); - - return (true); +#ifdef __linux__ +#define SND_32_INIT -1 +#else +#define SND_32_INIT ioctl(audio.handle, SNDCTL_DSP_SETFMT, &snd_format32) +#endif + + if (SND_32_INIT == 0) { + is32bit = true; + } else if (ioctl(handle, SNDCTL_DSP_SETFMT, &snd_format16) == 0) { + is32bit = false; + } else { + cerr << "ERROR - Cannot set DSP format for " + << device << '.' << endl; + goto error; + } + for (x = NUM_MIDI_PARTS * 2; x >= 2; x -= 2) { + if (ioctl(handle, SNDCTL_DSP_CHANNELS, &x) == 0) + break; + } + if (x == 0) { + cerr << "ERROR - Cannot set DSP channels for " + << device << '.' << endl; + goto error; + } + channels = x; + + snd_samplerate = synth->samplerate; + + ioctl(handle, SNDCTL_DSP_SPEED, &snd_samplerate); + + if (snd_samplerate != (int)synth->samplerate) { + cerr << "ERROR - Cannot set samplerate for " + << device << ". " << snd_samplerate + << " != " << synth->samplerate << endl; + goto error; + } + + /* compute buffer size for 16-bit samples */ + buffersize = 2 * synth->buffersize * channels; + if (is32bit) + buffersize *= 2; + + for (x = 4; x < 20; x++) { + if ((1 << x) >= buffersize) + break; + } + + snd_fragment = 0x20000 | x; /* 2x buffer */ + + ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_create(&audioThread, &attr, _audioThreadCb, this); + + return (true); error: - close(handle); - handle = -1; - return (false); + close(handle); + handle = -1; + return (false); } -void + void OssMultiEngine :: stopAudio() { - int fd = handle; + int fd = handle; - /* check if already closed */ - if (fd == -1) - return; - handle = -1; + /* check if already closed */ + if (fd == -1) + return; + handle = -1; - /* close handle first, so that write() exits */ - close(fd); + /* close handle first, so that write() exits */ + close(fd); - pthread_join(audioThread, 0); - audioThread = 0; + pthread_join(audioThread, 0); + audioThread = 0; } -bool + bool OssMultiEngine :: Start() { - return (openAudio()); + return (openAudio()); } -void + void OssMultiEngine :: Stop() { - stopAudio(); + stopAudio(); } -void + void OssMultiEngine :: setAudioEn(bool enable) { - if (enable) - openAudio(); - else - stopAudio(); + if (enable) + openAudio(); + else + stopAudio(); } bool OssMultiEngine :: getAudioEn() const { - return (handle != -1); + return (handle != -1); } -void * + void * OssMultiEngine :: _audioThreadCb(void *arg) { - return (static_cast<OssMultiEngine *>(arg))->audioThreadCb(); + return (static_cast<OssMultiEngine *>(arg))->audioThreadCb(); } -void * + void * OssMultiEngine :: audioThreadCb() { - /* - * In case the audio device is a PIPE/FIFO, we need to ignore - * any PIPE signals: - */ - signal(SIGPIPE, SIG_IGN); - - set_realtime(); - - while(getAudioEn()) { - int error; - float l; - float r; - int x; - int y; - - /* get next buffer */ - getNext(); - - /* extract audio from the "channels / 2" first parts */ - for (x = 0; x != channels; x += 2) { - Part *part = middleware->spawnMaster()->part[x / 2]; - - if (is32bit) { - for (y = 0; y != synth->buffersize; y++) { - l = part->partoutl[y]; - if (l < -1.0f) - l = -1.0f; - else if (l > 1.0f) - l = 1.0f; - smps.ps32[y * channels + x] = (int)(l * 2147483647.0f); - r = part->partoutr[y]; - if (r < -1.0f) - r = -1.0f; - else if (r > 1.0f) - r = 1.0f; - smps.ps32[y * channels + x + 1] = (int)(r * 2147483647.0f); - } - } else { - for (y = 0; y != synth->buffersize; y++) { - l = part->partoutl[y]; - if (l < -1.0f) - l = -1.0f; - else if (l > 1.0f) - l = 1.0f; - smps.ps16[y * channels + x] = (short int)(l * 32767.0f); - r = part->partoutr[y]; - if (r < -1.0f) - r = -1.0f; - else if (r > 1.0f) - r = 1.0f; - smps.ps16[y * channels + x + 1] = (short int)(r * 32767.0f); - } - } - } - - /* write audio buffer to DSP device */ - do { - /* make a copy of handle, in case of OSS audio disable */ - int fd = handle; - if (fd == -1) - goto done; - error = write(fd, smps.ps32, buffersize); - } while (error == -1 && errno == EINTR); - - if(error == -1) - goto done; - } + /* + * In case the audio device is a PIPE/FIFO, we need to ignore + * any PIPE signals: + */ + signal(SIGPIPE, SIG_IGN); + + set_realtime(); + + while(getAudioEn()) { + int error; + float l; + float r; + int x; + int y; + + /* get next buffer */ + getNext(); + + /* extract audio from the "channels / 2" first parts */ + for (x = 0; x != channels; x += 2) { + Part *part = middleware->spawnMaster()->part[x / 2]; + + if (is32bit) { + for (y = 0; y != synth->buffersize; y++) { + l = part->partoutl[y]; + if (l < -1.0f) + l = -1.0f; + else if (l > 1.0f) + l = 1.0f; + smps.ps32[y * channels + x] = (int)(l * 2147483647.0f); + r = part->partoutr[y]; + if (r < -1.0f) + r = -1.0f; + else if (r > 1.0f) + r = 1.0f; + smps.ps32[y * channels + x + 1] = (int)(r * 2147483647.0f); + } + } else { + for (y = 0; y != synth->buffersize; y++) { + l = part->partoutl[y]; + if (l < -1.0f) + l = -1.0f; + else if (l > 1.0f) + l = 1.0f; + smps.ps16[y * channels + x] = (short int)(l * 32767.0f); + r = part->partoutr[y]; + if (r < -1.0f) + r = -1.0f; + else if (r > 1.0f) + r = 1.0f; + smps.ps16[y * channels + x + 1] = (short int)(r * 32767.0f); + } + } + } + + /* write audio buffer to DSP device */ + do { + /* make a copy of handle, in case of OSS audio disable */ + int fd = handle; + if (fd == -1) + goto done; + error = write(fd, smps.ps32, buffersize); + } while (error == -1 && errno == EINTR); + + if(error == -1) + goto done; + } done: - pthread_exit(0); - return (0); + pthread_exit(0); + return (0); } diff --git a/src/Nio/OssMultiEngine.h b/src/Nio/OssMultiEngine.h @@ -1,21 +1,21 @@ /* - ZynAddSubFX - a software synthesizer + ZynAddSubFX - a software synthesizer - OssMultiEngine.h - Multi channel audio output for Open Sound System - Copyright (C) 2014 Hans Petter Selasky + OssMultiEngine.h - Multi channel audio output for Open Sound System + Copyright (C) 2014 Hans Petter Selasky - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -28,40 +28,40 @@ class OssMultiEngine : public AudioOut { -public: - OssMultiEngine(); - ~OssMultiEngine(); + public: + OssMultiEngine(); + ~OssMultiEngine(); - bool Start(); - void Stop(); + bool Start(); + void Stop(); - void setAudioEn(bool nval); - bool getAudioEn() const; + void setAudioEn(bool nval); + bool getAudioEn() const; -protected: - void *audioThreadCb(); - static void *_audioThreadCb(void *arg); + protected: + void *audioThreadCb(); + static void *_audioThreadCb(void *arg); -private: - pthread_t audioThread; + private: + pthread_t audioThread; - /* Audio */ - bool openAudio(); - void stopAudio(); + /* Audio */ + bool openAudio(); + void stopAudio(); - int handle; - int maxbuffersize; - int buffersize; - int channels; + int handle; + int maxbuffersize; + int buffersize; + int channels; - union { - /* Samples to be sent to soundcard */ - short int *ps16; - int *ps32; - } smps; + union { + /* Samples to be sent to soundcard */ + short int *ps16; + int *ps32; + } smps; - bool en; - bool is32bit; + bool en; + bool is32bit; }; #endif