zynaddsubfx

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

commit 2b2742af9f16eb68982b1becdcea5fa0f88b623a
parent 2c0e4b5634b171af1d0d45646833af187ecb1cc7
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Fri, 30 Oct 2009 09:15:01 -0400

NewIO: First stage of WIP

Integration of yoshimi code under way.
This is a base establishment of the new output system.
Will compile, but will not behave as expected.

Diffstat:
MAUTHORS.txt | 1+
MChangeLog | 3+++
Msrc/CMakeLists.txt | 17++++++++++++++---
Msrc/Misc/Config.cpp | 4++++
Msrc/Misc/Config.h | 3+++
Msrc/Misc/Master.cpp | 19+++++++++++++++++++
Msrc/Misc/Master.h | 8+++++++-
Msrc/Misc/Stereo.h | 1+
Msrc/Misc/Util.cpp | 13+++++++++++++
Msrc/Misc/Util.h | 6++++++
Asrc/Nio/AlsaEngine.cpp | 587+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/AlsaEngine.h | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/AudioOut.cpp | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/AudioOut.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/CMakeLists.txt | 11+++++++++++
Asrc/Nio/MidiIn.cpp | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/MidiIn.h | 37+++++++++++++++++++++++++++++++++++++
Asrc/Nio/OutMgr.cpp | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Nio/OutMgr.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Samples/Sample.cpp | 6++++++
Msrc/Samples/Sample.h | 3++-
Msrc/UI/VirKeyboard.fl | 12++++--------
Msrc/main.cpp | 127+++++++++++++++++++++++++++++++++++++++----------------------------------------
23 files changed, 1342 insertions(+), 78 deletions(-)

diff --git a/AUTHORS.txt b/AUTHORS.txt @@ -15,4 +15,5 @@ Contributors: Alexis Ballier (const char* <-> string mismatch, NULLMidi prototype fix) Tobias Doerffel (static vs instance variables alteration) James Morris (Memory leaks in FLTK GUI) + Alan Calvert (Portions of New IO) diff --git a/ChangeLog b/ChangeLog @@ -957,3 +957,6 @@ 09 Oct 2009 (Mark McCurry) - Restylized codebase with uncrustify + +30 Oct 2009 (Mark McCurry) + - Commited first stage of Nio (New IO) WIP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(FLTK) # file, but either in in CMakeCache.txt before compile, or by passing # parameters directly into cmake using the -D flag. SET (FFTW_VERSION 3 CACHE STRING "Version number of FFTW") -SET (OutputModule alsa CACHE STRING "Output module, either alsa, jack or portaudio") +SET (OutputModule alsa CACHE STRING "Output module, either alsa, nio, jack or portaudio") SET (GuiModule fltk CACHE STRING "GUI module, either fltk, qt or off") SET (CompileTests OFF CACHE BOOL "whether tests should be compiled in or not") @@ -38,8 +38,10 @@ elseif(OutputModule STREQUAL jack AND JACK_FOUND) set(JackOutput TRUE) elseif(OutputModule STREQUAL portaudio AND PortAudio_FOUND) set(PortAudioOutput TRUE) +elseif(OutputModule STREQUAL nio AND ALSA_FOUND) + set(NewIO TRUE) else () - message(FATAL_ERROR "OutputModule must be either alsa, jack or portaudio") + message(FATAL_ERROR "OutputModule must be either alsa, nio, jack or portaudio") endif() ########### Settings dependant code ########### @@ -51,6 +53,11 @@ if(AlsaMidiOutput) set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${ASOUND_LIBRARY}) endif() +if(NewIO) + add_definitions(-DNEW_IO) + set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${ASOUND_LIBRARY}) +endif() + if (CompileTests) ENABLE_TESTING() endif() @@ -71,6 +78,7 @@ add_definitions(-DFFTW_VERSION_${FFTW_VERSION} -DOS_LINUX -DALSAMIDIIN -DASM_F2I_YES + -g #TODO #todo put in a better location ) @@ -149,8 +157,8 @@ endmacro(unit_test) set(NONGUI_LIBRARIES zynaddsubfx_input - zynaddsubfx_output zynaddsubfx_misc + zynaddsubfx_nio zynaddsubfx_synth zynaddsubfx_seq zynaddsubfx_effect @@ -158,6 +166,7 @@ set(NONGUI_LIBRARIES zynaddsubfx_dsp zynaddsubfx_samples zynaddsubfx_controls + zynaddsubfx_output ) set(CXXTEST_LINK_LIBS ${NONGUI_LIBRARIES}) @@ -174,6 +183,7 @@ add_subdirectory(Params) add_subdirectory(DSP) add_subdirectory(Samples) add_subdirectory(Tests) +add_subdirectory(Nio) set(zynaddsubfx_SRCS main.cpp @@ -191,5 +201,6 @@ target_link_libraries(zynaddsubfx ${MXML_LIBRARIES} ${AUDIO_LIBRARIES} ${MIDIINPUT_LIBRARIES} + ${NIO_LIBRARIES} ) diff --git a/src/Misc/Config.cpp b/src/Misc/Config.cpp @@ -32,6 +32,8 @@ #include "Config.h" #include "XMLwrapper.h" +using namespace std; + Config::Config() {} void Config::init() @@ -178,6 +180,8 @@ void Config::init() sprintf(cfg.presetsDirList[2], "presets"); #endif } + cfg.LinuxALSAaudioDev = "default"; + cfg.nameTag = ""; } Config::~Config() diff --git a/src/Misc/Config.h b/src/Misc/Config.h @@ -23,6 +23,7 @@ #ifndef CONFIG_H #define CONFIG_H #include "../globals.h" +#include <string> #define MAX_STRING_SIZE 4000 #define MAX_BANK_ROOT_DIRS 100 @@ -48,6 +49,8 @@ class Config int CheckPADsynth; int UserInterfaceMode; int VirKeybLayout; + std::string LinuxALSAaudioDev; + std::string nameTag; } cfg; int winwavemax, winmidimax; //number of wave/midi devices on Windows int maxstringsize; diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp @@ -109,6 +109,21 @@ void Master::defaults() ShutUp(); } +bool Master::mutexLock(lockset request) +{ + switch (request) + { + case MUTEX_TRYLOCK: + return !pthread_mutex_trylock(&mutex); + case MUTEX_LOCK: + return !pthread_mutex_lock(&mutex); + case MUTEX_UNLOCK: + return !pthread_mutex_unlock(&mutex); + } + return false; +} + + /* * Note On Messages (velocity=0 for NoteOff) */ @@ -116,9 +131,11 @@ void Master::NoteOn(unsigned char chan, unsigned char note, unsigned char velocity) { + pthread_mutex_lock(&mutex); dump.dumpnote(chan, note, velocity); noteon(chan, note, velocity); + pthread_mutex_unlock(&mutex); } /* @@ -149,9 +166,11 @@ void Master::noteon(unsigned char chan, */ void Master::NoteOff(unsigned char chan, unsigned char note) { + pthread_mutex_lock(&mutex); dump.dumpnote(chan, note, 0); noteoff(chan, note); + pthread_mutex_unlock(&mutex); } /* diff --git a/src/Misc/Master.h b/src/Misc/Master.h @@ -35,6 +35,8 @@ #include "../Seq/Sequencer.h" #include "XMLwrapper.h" +typedef enum { MUTEX_TRYLOCK, MUTEX_LOCK, MUTEX_UNLOCK } lockset; + extern Dump dump; /** It sends Midi Messages to Parts, receives samples from parts, * process them with system/insertion effects and mix them */ @@ -69,7 +71,11 @@ class Master /**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ void putalldata(char *data, int size); - + //Mutex control + /**Control the Master's mutex state. + * @param lockset either trylock, lock, or unlock. + * @return true when successful false otherwise.*/ + bool mutexLock(lockset request); //Midi IN void NoteOn(unsigned char chan, diff --git a/src/Misc/Stereo.h b/src/Misc/Stereo.h @@ -30,6 +30,7 @@ class Stereo /**Initializes Stereo with left and right set to val * @param val the value for both channels*/ Stereo(const T &val); + Stereo() {}; ~Stereo() {} void operator=(const Stereo<T> &smp); diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp @@ -30,6 +30,8 @@ #include <unistd.h> #include <errno.h> #include <string.h> +#include <sched.h> + int SAMPLE_RATE = 44100; int SOUND_BUFFER_SIZE = 256; @@ -113,3 +115,14 @@ bool fileexists(const char *filename) return false; } +void set_realtime() +{ +#ifdef OS_LINUX + sched_param sc; + sc.sched_priority = 60; + //if you want get "sched_setscheduler undeclared" from compilation, + //you can safely remove the folowing line: + sched_setscheduler(0, SCHED_FIFO, &sc); + //if (err==0) printf("Real-time"); +#endif +} diff --git a/src/Misc/Util.h b/src/Misc/Util.h @@ -38,6 +38,12 @@ extern REALTYPE getdetune(unsigned char type, unsigned short int coarsedetune, unsigned short int finedetune); +/**Try to set current thread to realtime priority program priority + * \todo see if the right pid is being sent + * \todo see if this is having desired effect, if not then look at + * pthread_attr_t*/ +void set_realtime(); + extern REALTYPE *denormalkillbuf; /**<the buffer to add noise in order to avoid denormalisation*/ extern Config config; diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp @@ -0,0 +1,587 @@ +/* + AlsaEngine.cpp + + Copyright 2009, Alan Calvert + + This file is part of ZynAddSubFX, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + ZynAddSubFX 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 for more details. + + You should have received a copy of the GNU General Public License + along with ZynAddSubFX. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <iostream> + +using namespace std; + +#include "../Misc/Util.h" +#include "../Misc/Config.h" +#include "../Misc/Master.h" +#include "AlsaEngine.h" + +AlsaEngine::AlsaEngine() +{ + audio.handle = NULL; + audio.period_time = 0; + audio.samplerate = 0; + audio.buffer_size = 0; + audio.period_size = 0; + audio.buffer_size = 0; + audio.alsaId = -1; + audio.pThread = 0; + +// midi.handle = NULL; +// midi.alsaId = -1; +// midi.pThread = 0; + + threadStop = true; + pthread_mutex_init(&outBuf_mutex, NULL); + pthread_cond_init (&outBuf_cv, NULL); + manager = sysOut; + +} + + +bool AlsaEngine::openAudio() +{ + audio.device = "default";//config.cfg.audioDevice; + audio.samplerate = config.cfg.SampleRate; + audio.period_size = config.cfg.SoundBufferSize; + audio.period_time = audio.period_size * 1000000.0f / audio.samplerate; + alsaBad(snd_config_update_free_global(), "failed to update snd config"); + if (alsaBad(snd_pcm_open(&audio.handle, audio.device.c_str(), + SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_CHANNELS), + "failed to open alsa audio device:" + audio.device)) + goto bail_out; + if (alsaBad(snd_pcm_nonblock(audio.handle, 0), "set blocking failed")) + goto bail_out; + if (!prepHwparams()) + goto bail_out; + if (!prepSwparams()) + goto bail_out; + //config.cfg.Samplerate = getSamplerate(); + //config.cfg.Buffersize = getBuffersize(); + return true; +bail_out: + Close(); + return false; +} + + +//bool AlsaEngine::openMidi() +//{ +// midi.device = config.cfg.midiDevice; +// if (!midi.device.size()) +// midi.device = "default"; +// string port_name = "input"; +// if (snd_seq_open(&midi.handle, midi.device.c_str(), SND_SEQ_OPEN_INPUT, 0)) +// { +// cerr << "Error, failed to open alsa midi device: " << midi.device << endl; +// goto bail_out; +// } +// snd_seq_client_info_t *seq_info; +// snd_seq_client_info_alloca(&seq_info); +// snd_seq_get_client_info(midi.handle, seq_info); +// midi.alsaId = snd_seq_client_info_get_client(seq_info); +// snd_seq_set_client_name(midi.handle, midiClientName().c_str()); +// if (0 > snd_seq_create_simple_port(midi.handle, port_name.c_str(), +// SND_SEQ_PORT_CAP_WRITE +// | SND_SEQ_PORT_CAP_SUBS_WRITE, +// SND_SEQ_PORT_TYPE_SYNTH)) +// { +// cerr << "Error, failed to acquire alsa midi port" << endl; +// goto bail_out; +// } +// return true; +// +//bail_out: +// Close(); +// return false; +//} + + +void AlsaEngine::Close() +{ + Stop(); + if (audio.handle != NULL) + alsaBad(snd_pcm_close(audio.handle), "close pcm failed"); + audio.handle = NULL; +// if (NULL != midi.handle) +// if (snd_seq_close(midi.handle) < 0) +// cerr << "Error closing Alsa midi connection" << endl; +// midi.handle = NULL; +} + +void AlsaEngine::out(const Stereo<Sample> smps) +{ + pthread_mutex_lock(&outBuf_mutex); + outBuf.push(smps); + pthread_cond_signal(&outBuf_cv); + pthread_mutex_unlock(&outBuf_mutex); +} + + +string AlsaEngine::audioClientName() +{ + string name = "zynaddsubfx"; + if (!config.cfg.nameTag.empty()) + name += ("-" + config.cfg.nameTag); + return name; +} + +//string AlsaEngine::midiClientName() +//{ +// string name = "zynaddsubfx"; +// if (!config.cfg.nameTag.empty()) +// name += ("-" + config.cfg.nameTag); +// return name; +//} + + +bool AlsaEngine::prepHwparams() +{ + unsigned int buffer_time = audio.period_time * 4; + unsigned int desired_samplerate = audio.samplerate; + snd_pcm_format_t format = SND_PCM_FORMAT_S16; // Alsa appends _LE/_BE? hmmm + snd_pcm_access_t axs = SND_PCM_ACCESS_MMAP_INTERLEAVED; + snd_pcm_hw_params_t *hwparams = NULL; + snd_pcm_hw_params_alloca(&hwparams); + if (alsaBad(snd_pcm_hw_params_any(audio.handle, hwparams), + "alsa audio no playback configurations available")) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_set_periods_integer(audio.handle, hwparams), + "alsa audio cannot restrict period size to integral value")) + goto bail_out; + if (!alsaBad(snd_pcm_hw_params_set_access(audio.handle, hwparams, axs), + "alsa audio mmap not possible")) + pcmWrite = &snd_pcm_mmap_writei; + else + { + axs = SND_PCM_ACCESS_RW_INTERLEAVED; + if (alsaBad(snd_pcm_hw_params_set_access(audio.handle, hwparams, axs), + "alsa audio failed to set access, both mmap and rw failed")) + goto bail_out; + pcmWrite = &snd_pcm_writei; + } + if (alsaBad(snd_pcm_hw_params_set_format(audio.handle, hwparams, format), + "alsa audio failed to set sample format")) + goto bail_out; + alsaBad(snd_pcm_hw_params_set_rate_resample(audio.handle, hwparams, 1), + "alsa audio failed to set allow resample"); + if (alsaBad(snd_pcm_hw_params_set_rate_near(audio.handle, hwparams, + &audio.samplerate, NULL), + "alsa audio failed to set sample rate to " + + stringFrom<int>(desired_samplerate))) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_set_channels(audio.handle, hwparams, 2), + "alsa audio failed to set channels to 2")) + goto bail_out; + if (!alsaBad(snd_pcm_hw_params_set_buffer_time_near(audio.handle, hwparams, + &buffer_time, NULL), "initial buffer time setting failed")) + { + if (alsaBad(snd_pcm_hw_params_get_buffer_size(hwparams, &audio.buffer_size), + "alsa audio failed to get buffer size")) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_set_period_time_near(audio.handle, hwparams, + &audio.period_time, NULL), "failed to set period time")) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_get_period_size(hwparams, &audio.period_size, + NULL), "alsa audio failed to get period size")) + goto bail_out; + } + else + { + if (alsaBad(snd_pcm_hw_params_set_period_time_near(audio.handle, hwparams, + &audio.period_time, NULL), "failed to set period time")) + goto bail_out; + audio.buffer_size = audio.period_size * 4; + if (alsaBad(snd_pcm_hw_params_set_buffer_size_near(audio.handle, hwparams, + &audio.buffer_size), "failed to set buffer size")) + goto bail_out; + } + if (alsaBad(snd_pcm_hw_params(audio.handle, hwparams), + "alsa audio failed to set hardware parameters")) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_get_buffer_size(hwparams, &audio.buffer_size), + "alsa audio failed to get buffer size")) + goto bail_out; + if (alsaBad(snd_pcm_hw_params_get_period_size(hwparams, &audio.period_size, + NULL), "failed to get period size")) + goto bail_out; + return true; + +bail_out: + if (audio.handle != NULL) + Close(); + return false; +} + + +bool AlsaEngine::prepSwparams() +{ + snd_pcm_sw_params_t *swparams; + snd_pcm_sw_params_alloca(&swparams); + snd_pcm_uframes_t boundary; + if (alsaBad(snd_pcm_sw_params_current(audio.handle, swparams), + "alsa audio failed to get swparams")) + goto bail_out; + if (alsaBad(snd_pcm_sw_params_get_boundary(swparams, &boundary), + "alsa audio failed to get boundary")) + goto bail_out; + if (alsaBad(snd_pcm_sw_params_set_start_threshold(audio.handle, swparams, + boundary + 1), + "failed to set start threshold")) // explicit start, not auto start + goto bail_out; + if (alsaBad(snd_pcm_sw_params_set_stop_threshold(audio.handle, swparams, + boundary), + "alsa audio failed to set stop threshold")) + goto bail_out; + if (alsaBad(snd_pcm_sw_params(audio.handle, swparams), + "alsa audio failed to set software parameters")) + goto bail_out; + return true; + +bail_out: + return false; +} + + +bool AlsaEngine::alsaBad(int op_result, string err_msg) +{ + bool isbad = (op_result < 0); // (op_result < 0) -> is bad -> return true + if (isbad) + cerr << "Error, alsa audio: " << err_msg << ": " + << string(snd_strerror(op_result)) << endl; + return isbad; +} + + +void *AlsaEngine::_AudioThread(void *arg) +{ + return (static_cast<AlsaEngine*>(arg))->AudioThread(); +} + + +void *AlsaEngine::AudioThread() +{ + if (NULL == audio.handle) + { + cerr << "Error, null pcm handle into AlsaEngine::AudioThread" << endl; + return NULL; + } + set_realtime(); + alsaBad(snd_pcm_start(audio.handle), "alsa audio pcm start failed"); + while (!threadStop) + { + cout << "AlsaEngine THREAD" << endl; + const Stereo<Sample> smps = getNext(); + + audio.pcm_state = snd_pcm_state(audio.handle); + if (audio.pcm_state != SND_PCM_STATE_RUNNING) + { + switch (audio.pcm_state) + { + case SND_PCM_STATE_XRUN: + case SND_PCM_STATE_SUSPENDED: + if (!xrunRecover()) + break; + // else fall through to ... + case SND_PCM_STATE_SETUP: + if (alsaBad(snd_pcm_prepare(audio.handle), + "alsa audio pcm prepare failed")) + break; + case SND_PCM_STATE_PREPARED: + alsaBad(snd_pcm_start(audio.handle), "pcm start failed"); + break; + default: + cout << "AlsaEngine::AudioThread, weird SND_PCM_STATE: " + << audio.pcm_state << endl; + break; + } + audio.pcm_state = snd_pcm_state(audio.handle); + } + if (audio.pcm_state == SND_PCM_STATE_RUNNING) + { + const short *tmp = interleave(smps); + Write(tmp); + delete [] tmp; + } + else + ;//config.cfg.verbose + // && cerr << "Error, audio pcm still not RUNNING" << endl; + cerr << "Error, audio pcm still not running"; + } + return NULL; +} + + +void AlsaEngine::Write(const short *InterleavedSmps) +{ + snd_pcm_uframes_t towrite = getBuffersize(); + snd_pcm_sframes_t wrote = 0; + const short int *data = InterleavedSmps; + while (towrite > 0) + { + //wrote = pcmWrite(audio.handle, &data, towrite); + wrote = snd_pcm_writei(audio.handle, data, towrite); + if (wrote >= 0) + { + if ((snd_pcm_uframes_t)wrote < towrite || wrote == -EAGAIN) + snd_pcm_wait(audio.handle, 707); + if (wrote > 0) + { + towrite -= wrote; + data += wrote * 2; + } + } + else // (wrote < 0) + { + switch (wrote) + { + case -EBADFD: + alsaBad(-EBADFD, "alsa audio unfit for writing"); + break; + case -EPIPE: + xrunRecover(); + break; + case -ESTRPIPE: + Recover(wrote); + break; + default: + alsaBad(wrote, "alsa audio, snd_pcm_writei ==> weird state"); + break; + } + wrote = 0; + } + } +} + + +bool AlsaEngine::Recover(int err) +{ + if (err > 0) + err = -err; + bool isgood = false; + switch (err) + { + case -EINTR: + isgood = true; // nuthin to see here + break; + case -ESTRPIPE: + if (!alsaBad(snd_pcm_prepare(audio.handle), + "Error, AlsaEngine failed to recover from suspend")) + isgood = true; + break; + case -EPIPE: + if (!alsaBad(snd_pcm_prepare(audio.handle), + "Error, AlsaEngine failed to recover from underrun")) + isgood = true; + break; + default: + break; + } + return isgood; +} + + +bool AlsaEngine::xrunRecover() +{ + bool isgood = false; + if (audio.handle != NULL) + { + if (!alsaBad(snd_pcm_drop(audio.handle), "pcm drop failed")) + if (!alsaBad(snd_pcm_prepare(audio.handle), "pcm prepare failed")) + isgood = true; + ;//config.cfg.verbose + // && cout << "Info, xrun recovery " << ((isgood) ? "good" : "not good") + // << endl; + } + return isgood; +} + + +bool AlsaEngine::Start(void) +{ + int chk; + pthread_attr_t attr; + threadStop = false; + if (NULL != audio.handle) + { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&audio.pThread, &attr, _AudioThread, this); + } + +// if (NULL != midi.handle) +// { +// chk = pthread_attr_init(&attr); +// chk = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); +// chk = pthread_create(&midi.pThread, &attr, _MidiThread, this); +// } + return true; + +bail_out: + cerr << "Error - bail out of AlsaEngine::Start()" << endl; + Close(); + threadStop = true; + return false; +} + + +void AlsaEngine::Stop(void) +{ + threadStop = true; + + if (NULL != audio.handle && audio.pThread) + if (pthread_cancel(audio.pThread)) + cerr << "Error, failed to cancel Alsa audio thread" << endl; + //if (NULL != midi.handle && midi.pThread) + // if (pthread_cancel(midi.pThread)) + // cerr << "Error, failed to cancel Alsa midi thread" << endl; +} + + +//void *AlsaEngine::_MidiThread(void *arg) +//{ +// return static_cast<AlsaEngine*>(arg)->MidiThread(); +//} + + +//void *AlsaEngine::MidiThread(void) +//{ +// snd_seq_event_t *event; +// unsigned char channel; +// unsigned char note; +// unsigned char velocity; +// int ctrltype; +// int par; +// int chk; +// set_realtime(); +// while (!threadStop) +// { +// while ((chk = snd_seq_event_input(midi.handle, &event)) > 0) +// { +// if (!event) +// continue; +// par = event->data.control.param; +// switch (event->type) +// { +// case SND_SEQ_EVENT_NOTEON: +// if (event->data.note.note) +// { +// channel = event->data.note.channel; +// note = event->data.note.note; +// velocity = event->data.note.velocity; +// setMidiNote(channel, note, velocity); +// } +// break; +// +// case SND_SEQ_EVENT_NOTEOFF: +// channel = event->data.note.channel; +// note = event->data.note.note; +// setMidiNote(channel, note); +// break; +// +// case SND_SEQ_EVENT_PITCHBEND: +// channel = event->data.control.channel; +// ctrltype = C_pitchwheel; +// par = event->data.control.value; +// setMidiController(channel, ctrltype, par); +// break; +// +// case SND_SEQ_EVENT_CONTROLLER: +// channel = event->data.control.channel; +// ctrltype = event->data.control.param; +// par = event->data.control.value; +// setMidiController(channel, ctrltype, par); +// break; +// +// case SND_SEQ_EVENT_RESET: // reset to power-on state +// channel = event->data.control.channel; +// ctrltype = C_resetallcontrollers; +// setMidiController(channel, ctrltype, 0); +// break; +// +// case SND_SEQ_EVENT_PORT_SUBSCRIBED: // ports connected +// if (config.cfg.verbose) +// cout << "Info, alsa midi port connected" << endl; +// break; +// +// case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: // ports disconnected +// if (config.cfg.verbose) +// cout << "Info, alsa midi port disconnected" << endl; +// break; +// +// case SND_SEQ_EVENT_SYSEX: // system exclusive +// case SND_SEQ_EVENT_SENSING: // midi device still there +// break; +// +// default: +// if (config.cfg.verbose) +// cout << "Info, other non-handled midi event, type: " +// << (int)event->type << endl; +// break; +// } +// snd_seq_free_event(event); +// } +// if (chk < 0) +// { +// if (config.cfg.verbose) +// cerr << "Error, ALSA midi input read failed: " << chk << endl; +// return NULL; +// } +// } +// return NULL; +//} + +const Stereo<Sample> AlsaEngine::getNext() +{ + Stereo<Sample> ans; + if(outBuf.empty())//fetch samples if possible + { + if(true)//FIXME care about locking state later on + //mgr.requestSamples()!=-1)//samples are being prepared + { + manager->requestSamples(); + pthread_mutex_lock(&outBuf_mutex); + pthread_cond_wait(&outBuf_cv, &outBuf_mutex); + ans = outBuf.front(); + outBuf.pop(); + pthread_mutex_unlock(&outBuf_mutex); + } + } + else + { + pthread_mutex_lock(&outBuf_mutex); + ans = outBuf.front(); + outBuf.pop(); + pthread_mutex_unlock(&outBuf_mutex); + } + return ans; +} + + +const short *AlsaEngine::interleave(const Stereo<Sample> smps)const +{ + //hm, this seems less than optimum + //TODO remove this excessive allocation/deallocation once things are + //integrated + short *shortInterleaved = new short[smps.l().size()*2+1002];//over allocation + /**\todo TODO fix overallocation*/ + int idx = 0;//possible off by one error here + double scaled; + for (int frame = 0; frame < smps.l().size(); ++frame) + { // with a nod to libsamplerate ... + scaled = smps.l()[frame] * (8.0 * 0x10000000); + shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16); + scaled = smps.r()[frame] * (8.0 * 0x10000000); + shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16); + } +} diff --git a/src/Nio/AlsaEngine.h b/src/Nio/AlsaEngine.h @@ -0,0 +1,110 @@ +/* + AlsaEngine.h + + Copyright 2009, Alan Calvert + + This file is part of ZynAddSubFX, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + ZynAddSubFX 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 for more details. + + You should have received a copy of the GNU General Public License + along with ZynAddSubFX. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef ALSA_ENGINE_H +#define ALSA_ENGINE_H + +#include <pthread.h> +#include <string> +#include <alsa/asoundlib.h> +#include <queue> + +#include "AudioOut.h" +//include "MidiIn.h" +#include "OutMgr.h" +#include "../Misc/Stereo.h" +#include "../Samples/Sample.h" + +class AlsaEngine : public AudioOut//, MidiIn +{ + public: + AlsaEngine(); + ~AlsaEngine() { }; + + bool openAudio(); + //bool openMidi(); + bool Start(); + void Stop(); + void Close(); + void out(const Stereo<Sample> smps); + + unsigned int getSamplerate() { return audio.samplerate; }; + unsigned int getBuffersize() { return audio.period_size; }; + + std::string audioClientName(); + //std::string midiClientName(); + int audioClientId() { return audio.alsaId; }; + //int midiClientId() { return midi.alsaId; }; + + protected: + void *AudioThread(); + static void *_AudioThread(void *arg); + //void *MidiThread(oid); + //static void *_MidiThread(); + + private: + bool prepHwparams(); + bool prepSwparams(); + void Write(const short *InterleavedSmps); + bool Recover(int err); + bool xrunRecover(); + bool alsaBad(int op_result, std::string err_msg); + void closeAudio(); + //void closeMidi(); + + snd_pcm_sframes_t (*pcmWrite)(snd_pcm_t *handle, const void *data, + snd_pcm_uframes_t nframes); + + /**Get the next sample for output.*/ + const Stereo<Sample> getNext(); + /**Interleave Samples. \todo move this to util*/ + const short *interleave(const Stereo<Sample> smps) const; + + struct { + std::string device; + snd_pcm_t *handle; + unsigned int period_time; + unsigned int samplerate; + snd_pcm_uframes_t period_size; + snd_pcm_uframes_t buffer_size; + int alsaId; + snd_pcm_state_t pcm_state; + pthread_t pThread; + } audio; + + //struct { + // std::string device; + // snd_seq_t *handle; + // int alsaId; + // pthread_t pThread; + //} midi; + + bool threadStop; + + //outside audio interface + queue<Stereo<Sample> > outBuf; + const Sample * curSmp; + pthread_mutex_t outBuf_mutex; + pthread_cond_t outBuf_cv; + + OutMgr *manager; + +}; + +#endif diff --git a/src/Nio/AudioOut.cpp b/src/Nio/AudioOut.cpp @@ -0,0 +1,114 @@ +/* + AudioOut.cpp + + Copyright 2009, Alan Calvert + + This file is part of yoshimi, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + yoshimi 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 for more details. + + You should have received a copy of the GNU General Public License + along with yoshimi. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <iostream> +#include <cstring> + +using namespace std; + +#include "../Misc/Master.h" +#include "AudioOut.h" + +AudioOut::AudioOut(){} + +//bool AudioOut::prepAudiobuffers(unsigned int nframes, bool with_interleaved) +//{ +// if (nframes > 0) +// { +// buffersize = nframes; +// outl = new float[buffersize]; +// outr = new float[buffersize]; +// if (outl == NULL || outr == NULL) +// goto bail_out; +// memset(outl, 0, buffersize * sizeof(float)); +// memset(outr, 0, buffersize * sizeof(float)); +// if (with_interleaved) +// { +// shortInterleaved = new short int[buffersize * 2]; +// if (shortInterleaved == NULL) +// goto bail_out; +// memset(shortInterleaved, 0, buffersize * 2 * sizeof(short int)); +// } +// return true; +// } +// +//bail_out: +// cerr << "Error, failed to allocate audio buffers, size " << buffersize << endl; +// if (outl != NULL) +// delete [] outl; +// outl = NULL; +// if (outr != NULL) +// delete [] outr; +// outr = NULL; +// if (with_interleaved) +// { +// if (shortInterleaved != NULL) +// delete [] shortInterleaved; +// shortInterleaved = NULL; +// } +// return false; +//} +// +// +//bool AudioOut::getAudio(bool lockrequired) +//{ +// if (NULL != master && outr != NULL && outl != NULL) +// return master->MasterAudio(outl, outr, lockrequired); +// return false; +//} +// +// +//bool AudioOut::getAudioInterleaved(bool lockrequired) +//{ +// if (shortInterleaved != NULL) +// { +// if (getAudio(lockrequired)) +// { +// int idx = 0; +// double scaled; +// for (int frame = 0; frame < buffersize; ++frame) +// { // with a nod to libsamplerate ... +// scaled = outl[frame] * (8.0 * 0x10000000); +// shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16); +// scaled = outr[frame] * (8.0 * 0x10000000); +// shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16); +// } +// return true; +// } +// } +// return false; +//} +// +// +//void AudioOut::silenceBuffers() +//{ +// memset(outl, 0, buffersize * sizeof(float)); +// memset(outr, 0, buffersize * sizeof(float)); +//} +// +// +//void AudioOut::dimBuffers() +//{ +// for (int i = 0; i < buffersize; ++i) +// { +// outl[i] *= 0.84033613; // -1.5dB +// outr[i] *= 0.84033613; +// } +//} + diff --git a/src/Nio/AudioOut.h b/src/Nio/AudioOut.h @@ -0,0 +1,49 @@ +/* + MusicIO.h + + Copyright 2009, Alan Calvert + Copyright 2009, James Morris + + This file is part of yoshimi, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + yoshimi 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 for more details. + + You should have received a copy of the GNU General Public License + along with yoshimi. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef AUDIO_OUT_H +#define AUDIO_OUT_H + +class AudioOut +{ + public: + AudioOut(); + virtual ~AudioOut() { }; + + virtual bool openAudio()=0; + virtual bool Start()=0; + virtual void Stop()=0; + virtual void Close()=0; + virtual void out(const Stereo<Sample> smps)=0; + //bool prepAudiobuffers(unsigned int buffersize, bool with_interleaved); + //void silenceBuffers(); + //void dimBuffers(); + /**Determines if new operator should/can be used*/ + //virtual bool isSingleton() const {return true;}; + + protected: + //float *outl; + //float *outr; + //short int *shortInterleaved; + //int buffersize; +}; + +#endif + diff --git a/src/Nio/CMakeLists.txt b/src/Nio/CMakeLists.txt @@ -0,0 +1,11 @@ +set(zynaddsubfx_nio_SRCS + AlsaEngine.cpp + AudioOut.cpp + OutMgr.cpp +) + +add_library(zynaddsubfx_nio STATIC + ${zynaddsubfx_nio_SRCS} + ) + +target_link_libraries(zynaddsubfx_nio) diff --git a/src/Nio/MidiIn.cpp b/src/Nio/MidiIn.cpp @@ -0,0 +1,126 @@ +/* + MusicIO.cpp + + Copyright 2009, Alan Calvert + + This file is part of yoshimi, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + yoshimi 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 for more details. + + You should have received a copy of the GNU General Public License + along with yoshimi. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <iostream> +#include <cstring> + +using namespace std; + +#include "../Misc/Master.h" +#include "MidiIn.h" + +MidiIn::MidiIn() +{} + +int MidiIn::getMidiController(unsigned char b) +{ + int ctl = C_NULL; + switch (b) + { + case 1: + ctl = C_modwheel; // Modulation Wheel + break; + case 7: + ctl=C_volume; // Volume + break; + case 10: + ctl = C_panning; // Panning + break; + case 11: + ctl = C_expression; // Expression + break; + case 64: + ctl = C_sustain; // Sustain pedal + break; + case 65: + ctl = C_portamento; // Portamento + break; + case 71: + ctl = C_filterq; // Filter Q (Sound Timbre) + break; + case 74: + ctl = C_filtercutoff; // Filter Cutoff (Brightness) + break; + case 75: + ctl = C_bandwidth; // BandWidth + break; + case 76: + ctl = C_fmamp; // FM amplitude + break; + case 77: + ctl = C_resonance_center; // Resonance Center Frequency + break; + case 78: + ctl = C_resonance_bandwidth; // Resonance Bandwith + break; + case 120: + ctl = C_allsoundsoff; // All Sounds OFF + break; + case 121: + ctl = C_resetallcontrollers; // Reset All Controllers + break; + case 123: + ctl = C_allnotesoff; // All Notes OFF + break; + // RPN and NRPN + case 0x06: + ctl = C_dataentryhi; // Data Entry (Coarse) + break; + case 0x26: + ctl = C_dataentrylo; // Data Entry (Fine) + break; + case 99: + ctl = C_nrpnhi; // NRPN (Coarse) + break; + case 98: + ctl = C_nrpnlo; // NRPN (Fine) + break; + default: + ctl = C_NULL; // an unrecognised controller! + break; + } + return ctl; +} + + +void MidiIn::setMidiController(unsigned char ch, unsigned int ctrl, + int param) +{ + master->mutexLock(MUTEX_LOCK); + master->SetController(ch, ctrl, param); + master->mutexLock(MUTEX_UNLOCK); +} + + +void MidiIn::setMidiNote(unsigned char channel, unsigned char note, + unsigned char velocity) +{ + master->mutexLock(MUTEX_LOCK); + master->NoteOn(channel, note, velocity); + master->mutexLock(MUTEX_UNLOCK); +} + + +void MidiIn::setMidiNote(unsigned char channel, unsigned char note) +{ + master->mutexLock(MUTEX_LOCK); + master->NoteOff(channel, note); + master->mutexLock(MUTEX_UNLOCK); +} + diff --git a/src/Nio/MidiIn.h b/src/Nio/MidiIn.h @@ -0,0 +1,37 @@ +/* + MusicIO.h + + Copyright 2009, Alan Calvert + Copyright 2009, James Morris + + This file is part of yoshimi, which is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + yoshimi 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 for more details. + + You should have received a copy of the GNU General Public License + along with yoshimi. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MIDI_IN_H +#define MIDI_IN_H + +class MidiIn +{ + public: + MidiIn(); + virtual ~MusicIO() {}; + + int getMidiController(unsigned char b); + void setMidiController(unsigned char ch, unsigned int ctrl, int param); + void setMidiNote(unsigned char chan, unsigned char note); + void setMidiNote(unsigned char chan, unsigned char note, + unsigned char velocity); +}; + +#endif diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp @@ -0,0 +1,102 @@ +#include "OutMgr.h" +#include <algorithm> +#include <iostream> +using namespace std; + +OutMgr *sysOut; +//typedef enum +//{ +// JACK_OUTPUT; +// ALSA_OUTPUT; +// OSS_OUTPUT; +// WINDOWS_OUTPUT; +// WAV_OUTPUT; +//} outputDriver; + +OutMgr::OutMgr(Master *nmaster) +{ + master = nmaster; + //initialize mutex + pthread_mutex_init(&mutex, NULL); + pthread_mutex_init(&processing, NULL); + pthread_cond_init(&needsProcess, NULL); + //init samples + outr = new REALTYPE[SOUND_BUFFER_SIZE]; + outl = new REALTYPE[SOUND_BUFFER_SIZE]; +}; + +void *_outputThread(void *arg) +{ + return (static_cast<OutMgr*>(arg))->outputThread(); +} + +void *OutMgr::outputThread() +{ + pthread_mutex_lock(&mutex); + cout << "run start" << endl; + for(int i = 0; i < outs.size(); ++i) + outs[i]->Start(); + cout << "running" << endl; + pthread_mutex_unlock(&mutex); + running=true; + init=true; + while(running){ + cout << "OutMgr THREAD" << endl; + pthread_mutex_lock(&processing); + cout << "OutMgr wait" << endl; + if(init||pthread_cond_wait(&needsProcess, &processing)); + //init=false;FIXME + //make master use samples + cout << "have some food" << endl; + master->AudioOut(outl,outr); + smps = Stereo<Sample>(Sample(SOUND_BUFFER_SIZE, outl), + Sample(SOUND_BUFFER_SIZE, outr)); + pthread_mutex_unlock(&processing); + + pthread_mutex_lock(&mutex); + for(int i = 0; i < outs.size(); ++i) + outs[i]->out(smps); + pthread_mutex_unlock(&mutex); + + } + return NULL; +} + +void OutMgr::run() +{ + int chk; + pthread_attr_t attr; + //threadStop = false; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&outThread, &attr, _outputThread, this); +} + + +int OutMgr::add(AudioOut *driver) +{ + pthread_mutex_lock(&mutex); + outs.push_back(driver); + pthread_mutex_unlock(&mutex); +} + +int OutMgr::remove(AudioOut *out) +{ + pthread_mutex_lock(&mutex); + //vector<AudioOut>::iterator it; + //outs.remove(out); + pthread_mutex_unlock(&mutex); +} + +int OutMgr::requestSamples() +{ + cout << "me hungry" << endl; + pthread_mutex_lock(&processing); + pthread_cond_signal(&needsProcess); + cout << "me start fire" << endl; + pthread_mutex_unlock(&processing); +} + +//int OutMgr::enable(outputDriver out); +//int OutMgr::disable(outputDriver out); + diff --git a/src/Nio/OutMgr.h b/src/Nio/OutMgr.h @@ -0,0 +1,61 @@ +#ifndef OUTMGR_H +#define OUTMGR_H + +#include "../globals.h" +#include "../Misc/Stereo.h" +#include "../Samples/Sample.h" +#include "../Misc/Master.h" +#include "AudioOut.h" +#include <vector> +#include <pthread.h> + +//typedef enum +//{ +// JACK_OUTPUT; +// ALSA_OUTPUT +// OSS_OUTPUT; +// WINDOWS_OUTPUT; +// WAV_OUTPUT; +//} outputDriver; + +class OutMgr +{ + public: + OutMgr(Master *nmaster); + /**Adds audio output out. + * @return -1 for error 0 otherwise*/ + int add(AudioOut *out); + /**Removes given audio output engine + * @return -1 for error 0 otherwise*/ + int remove(AudioOut *out); + /**Request a new set of samples + * @return -1 for locking issues 0 for valid request*/ + int requestSamples(); + /**Enables one instance of given driver*/ + //int enable(outputDriver out); + /**Disables all instances of given driver*/ + //int disable(outputDriver out); + void run(); + + void *outputThread(); + private: + bool running; + bool init; + + std::vector<AudioOut *> outs; + mutable pthread_mutex_t mutex; + + pthread_mutex_t processing; + + pthread_t outThread; + pthread_cond_t needsProcess; + /**Buffer*/ + Stereo<Sample> smps; + REALTYPE *outl; + REALTYPE *outr; + Master *master; +}; + +extern OutMgr *sysOut; +#endif + diff --git a/src/Samples/Sample.cpp b/src/Samples/Sample.cpp @@ -23,6 +23,12 @@ /**\TODO start using pointer math here as these will be Frequency called * functions throughout the code*/ +Sample::Sample() + :bufferSize(1),buffer(new REALTYPE[1]) +{ + buffer[0] = 0.0; +} + Sample::Sample(const Sample &smp) :bufferSize(smp.bufferSize) { diff --git a/src/Samples/Sample.h b/src/Samples/Sample.h @@ -22,11 +22,12 @@ #define SAMPLE_H #include "../globals.h" /** - * Base Class for Samples + * Audio Samples Representation */ class Sample { public: + Sample(); Sample(const Sample &smp); Sample(int length, REALTYPE fill = 0); Sample(int length, const REALTYPE *fill); diff --git a/src/UI/VirKeyboard.fl b/src/UI/VirKeyboard.fl @@ -204,9 +204,7 @@ if (rndvelocity!=0){ vel=midivel*(127.0-rndvelocity)/127.0+RND*rndvelocity; }; -pthread_mutex_lock(&master->mutex); - master->NoteOn(midich,nk+midioct*12,(int)vel); -pthread_mutex_unlock(&master->mutex);} {} +master->NoteOn(midich,nk+midioct*12,(int)vel);} {} } Function {relasekey(int nk,int type)} {} { code {if ((nk<0)||(nk>=N_OCT*12)) return; @@ -218,9 +216,8 @@ pressed[nk]=0; damage(1); -pthread_mutex_lock(&master->mutex); - master->NoteOff(midich,nk+12*midioct); -pthread_mutex_unlock(&master->mutex);} {} +master->NoteOff(midich,nk+12*midioct);} {selected + } } Function {relaseallkeys(int type)} {} { code {for (int i=0;i<N_OCT*12;i++) relasekey(i,type);} {} @@ -410,8 +407,7 @@ midictl=75; make_window();} {} } Function {~VirKeyboard()} {} { - code {delete virkeyboardwindow;} {selected - } + code {delete virkeyboardwindow;} {} } Function {show()} {} { code {virkeyboardwindow->show();} {} diff --git a/src/main.cpp b/src/main.cpp @@ -1,7 +1,7 @@ /* ZynAddSubFX - a software synthesizer - main.c - Main file of the synthesizer + main.cpp - Main file of the synthesizer Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul @@ -38,6 +38,10 @@ #include "Misc/Dump.h" extern Dump dump; +//#ifdef NEW_IO +#include "Nio/OutMgr.h" +//#endif + #ifdef ALSAMIDIIN #include "Input/ALSAMidiIn.h" #endif @@ -72,11 +76,16 @@ MasterUI *ui; using namespace std; -pthread_t thr1, thr2, thr3, thr4; +pthread_t thr1, thr2, thr3, thr4;/**@deprecated*/ Master *master; int swaplr = 0; //1 for left-right swapping bool usejackit = false; +#ifdef NEW_IO +#include "Nio/AlsaEngine.h"//temporary include +#include "Nio/OutMgr.h" +#endif + #ifdef JACKAUDIOOUT #include "Output/JACKaudiooutput.h" #endif @@ -103,22 +112,6 @@ MidiIn *Midi; int Pexitprogram = 0; //if the UI set this to 1, the program will exit /* - * Try to get the realtime priority - */ -void set_realtime() -{ -#ifdef OS_LINUX - sched_param sc; - - sc.sched_priority = 50; - - //if you want get "sched_setscheduler undeclared" from compilation, you can safely remove the folowing line - sched_setscheduler(0, SCHED_FIFO, &sc); -// if (err==0) printf("Real-time"); -#endif -} - -/* * Midi input thread */ #if !(defined(WINMIDIIN) || defined(VSTMIDIIN)) @@ -315,32 +308,32 @@ void initprogram() master = new Master(); master->swaplr = swaplr; -#if defined(JACKAUDIOOUT) - if(usejackit) { - bool tmp = JACKaudiooutputinit(master); -#if defined(OSSAUDIOOUT) - if(!tmp) - cout << "\nUsing OSS instead." << endl; -#else - if(!tmp) - exit(1); -#endif - usejackit = tmp; - } -#endif -#if defined(OSSAUDIOOUT) - if(!usejackit) - audioout = new OSSaudiooutput(); - else - audioout = NULL; -#endif - -#ifdef JACK_RTAUDIOOUT - JACKaudiooutputinit(master); -#endif -#ifdef PAAUDIOOUT - PAaudiooutputinit(master); -#endif +//#if defined(JACKAUDIOOUT) +// if(usejackit) { +// bool tmp = JACKaudiooutputinit(master); +//#if defined(OSSAUDIOOUT) +// if(!tmp) +// cout << "\nUsing OSS instead." << endl; +//#else +// if(!tmp) +// exit(1); +//#endif +// usejackit = tmp; +// } +//#endif +//#if defined(OSSAUDIOOUT) +// if(!usejackit) +// audioout = new OSSaudiooutput(); +// else +// audioout = NULL; +//#endif + +//#ifdef JACK_RTAUDIOOUT +// JACKaudiooutputinit(master); +//#endif +//#ifdef PAAUDIOOUT +// PAaudiooutputinit(master); +//#endif #ifdef ALSAMIDIIN Midi = new ALSAMidiIn(); @@ -362,19 +355,19 @@ void initprogram() void exitprogram() { pthread_mutex_lock(&master->mutex); -#ifdef OSSAUDIOOUT - delete (audioout); -#endif -#ifdef JACKAUDIOOUT - if(usejackit) - JACKfinish(); -#endif -#ifdef JACK_RTAUDIOOUT - JACKfinish(); -#endif -#ifdef PAAUDIOOUT - PAfinish(); -#endif +//#ifdef OSSAUDIOOUT +// delete (audioout); +//#endif +//#ifdef JACKAUDIOOUT +// if(usejackit) +// JACKfinish(); +//#endif +//#ifdef JACK_RTAUDIOOUT +// JACKfinish(); +//#endif +//#ifdef PAAUDIOOUT +// PAfinish(); +//#endif #ifndef DISABLE_GUI delete (ui); @@ -452,15 +445,10 @@ int main(int argc, char *argv[]) /* Parse command-line options */ #ifdef OS_LINUX struct option opts[] = { - { - "load", 2, NULL, 'l' - }, - { - "load-instrument", 2, NULL, 'L' - }, - { - "sample-rate", 2, NULL, 'r' + {"load", 2, NULL, 'l'}, + {"load-instrument", 2, NULL, 'L' }, + {"sample-rate", 2, NULL, 'r'}, { "buffer-size", 2, NULL, 'b' }, @@ -692,6 +680,15 @@ int main(int argc, char *argv[]) pthread_create(&thr2, NULL, thread2, NULL); #endif +#ifdef NEW_IO + sysOut = new OutMgr(master); + AlsaEngine *tmp = new AlsaEngine(); + tmp->openAudio(); + sysOut->add(tmp); + sysOut->run(); + +#endif + /*It is not working and I don't know why //drop the suid-root permisions #if !(defined(JACKAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT)|| (defined (WINMIDIIN)) )