From 7e2777670f20dec0dce37f70351a3d16fbc1ed24 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Tue, 17 Oct 2006 14:49:42 +0000 Subject: added "mus" wrapper program for standalone MESS synthesizer --- muse/ChangeLog | 4 + muse/muse/audio.cpp | 12 -- muse/muse/ladspaplugin.cpp | 2 +- muse/muse/wave.cpp | 2 +- muse/synti/CMakeLists.txt | 2 +- muse/synti/README | 14 +++ muse/synti/mus/CMakeLists.txt | 27 +++++ muse/synti/mus/mus.cpp | 252 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 300 insertions(+), 15 deletions(-) create mode 100644 muse/synti/README create mode 100644 muse/synti/mus/CMakeLists.txt create mode 100644 muse/synti/mus/mus.cpp diff --git a/muse/ChangeLog b/muse/ChangeLog index 12f39d09..ca965719 100644 --- a/muse/ChangeLog +++ b/muse/ChangeLog @@ -1,3 +1,7 @@ +17.10 (ws) + - added new program "mus". Mus is a wrapper to operate MusE MESS + synthesizer standalone with JACK audio/midi interface. The + plan is to use them to test the upcoming jack midi implementation. 15.10 (ng) - DeicsOnze 0.5, add FX send - fix installation path for freeverb diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index ec8c6463..4e637278 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -218,14 +218,6 @@ bool Audio::start() } } audioDriver->stopTransport(); - - // - // do connections - // -// done in seqStart -// for (iTrack i = tl->begin(); i != tl->end(); ++i) { -// (*i)->activate2(); -// } return true; } @@ -702,10 +694,6 @@ void Audio::stopRolling() unsigned int Audio::curFrame() const { -// return lrint((curTime() - syncTime) * AL::sampleRate) + syncFrame; - // - // this should be the same: - // return audioDriver->framePos(); } diff --git a/muse/muse/ladspaplugin.cpp b/muse/muse/ladspaplugin.cpp index ee8b0e14..85398d74 100644 --- a/muse/muse/ladspaplugin.cpp +++ b/muse/muse/ladspaplugin.cpp @@ -125,7 +125,7 @@ void LadspaPlugin::range(int i, double* min, double* max) const LADSPA_PortRangeHint range = plugin->PortRangeHints[i]; LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor; if (desc & LADSPA_HINT_TOGGLED) { - *min = 0.0; + *min = -1.0; *max = 1.0; return; } diff --git a/muse/muse/wave.cpp b/muse/muse/wave.cpp index 9b40c967..280b291e 100644 --- a/muse/muse/wave.cpp +++ b/muse/muse/wave.cpp @@ -1,4 +1,4 @@ -//============================================================================= + //============================================================================= // MusE // Linux Music Editor // $Id:$ diff --git a/muse/synti/CMakeLists.txt b/muse/synti/CMakeLists.txt index 02babaf9..09d2f1b3 100644 --- a/muse/synti/CMakeLists.txt +++ b/muse/synti/CMakeLists.txt @@ -27,7 +27,7 @@ include_directories( ${PROJECT_SOURCE_DIR}/synti ) -set (SubDirs libsynti s1 organ deicsonze simpledrums vam ) +set (SubDirs libsynti s1 organ deicsonze simpledrums vam mus) if (ENABLE_FLUID) set (SubDirs ${SubDirs} fluid fluidsynth ) diff --git a/muse/synti/README b/muse/synti/README new file mode 100644 index 00000000..cbda0fd4 --- /dev/null +++ b/muse/synti/README @@ -0,0 +1,14 @@ +s1 is a simple demo of the MusE software synthesizer interface. + It has no gui and no parameters to set. + +organ is a demo synthesizer which shows how to implement + polyphony and a gui + +fluid is demo synthesizer utilizing the fluid sythesizer library + +mus is a program which can load any of the MusE synthsizer plugins + turning them into standalone synthesizer with a JACK audio and + midi interface + + + diff --git a/muse/synti/mus/CMakeLists.txt b/muse/synti/mus/CMakeLists.txt new file mode 100644 index 00000000..98a0c74c --- /dev/null +++ b/muse/synti/mus/CMakeLists.txt @@ -0,0 +1,27 @@ +#============================================================================= +# MusE +# Linux Music Editor +# $Id:$ +# +# Copyright (C) 2002-2006 by Werner Schweer and others +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2. +# +# 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 for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#============================================================================= + +add_executable ( mus mus.cpp ) +install_targets ( /bin mus ) +target_link_libraries(mus + ${QT_LIBRARIES} + ${JACK_LIB} + ) + diff --git a/muse/synti/mus/mus.cpp b/muse/synti/mus/mus.cpp new file mode 100644 index 00000000..5534dfab --- /dev/null +++ b/muse/synti/mus/mus.cpp @@ -0,0 +1,252 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "all.h" +#include +#include +#include + +#include "config.h" +#include "libsynti/mess.h" +#include "driver/jackaudio.h" +#include + +static const char* versionString = "1.0"; +static bool debug = false; + +static int sampleRate; +static int segmentSize; + +static Mess* mess; +static const int MAX_OUTPORTS = 8; +jack_port_t* inPort; +jack_port_t* outPorts[MAX_OUTPORTS]; +float* outBuffer[MAX_OUTPORTS]; + +//--------------------------------------------------------- +// processAudio +// JACK callback +//--------------------------------------------------------- + +static int processAudio(jack_nframes_t nFrames, void*) + { + int nch = mess->channels(); + for (int i = 0; i < nch; ++i) + outBuffer[i] = (float*)jack_port_get_buffer(outPorts[i], nFrames); + void* midi = jack_port_get_buffer(inPort, nFrames); + int n = jack_midi_port_get_info(midi, nFrames)->event_count; + unsigned offset = 0; + for (int i = 0; i < n; ++i) { + jack_midi_event_t event; + jack_midi_event_get(&event, midi, i, nFrames); + mess->process(outBuffer, offset, event.time - offset); + offset = event.time; + MidiEvent e; + e.setType(event.buffer[0] & 0xf0); + e.setChannel(event.buffer[0] & 0xf); + e.setA(event.buffer[1]); + e.setB(event.buffer[2]); + mess->processEvent(e); + } + if (offset < nFrames) + mess->process(outBuffer, offset, nFrames - offset); + return 0; + } + +//--------------------------------------------------------- +// jackError +//--------------------------------------------------------- + +static void jackError(const char* s) + { + fprintf(stderr, "JACK ERROR: %s\n", s); + } + +//--------------------------------------------------------- +// noJackError +//--------------------------------------------------------- + +static void noJackError(const char* /* s */) + { + } + +//--------------------------------------------------------- +// printVersion +//--------------------------------------------------------- + +static void printVersion(const char* programName) + { + printf("%s: Version %s\n", programName, versionString); + } + +//--------------------------------------------------------- +// usage +//--------------------------------------------------------- + +static void usage(const char* programName) + { + fprintf(stderr, "%s: usage MusE-synthesizer-plugin-name\n" + " options: -v print version\n" + " -d debug mode on\n", + programName + ); + } + +//--------------------------------------------------------- +// main +//--------------------------------------------------------- + +int main(int argc, char* argv[]) + { + new QApplication(argc, argv); + int c; + while ((c = getopt(argc, argv, "vd")) != EOF) { + switch (c) { + case 'v': + printVersion(argv[0]); + return 0; + case 'd': + debug = true; + break; + default: + usage(argv[0]); + return -1; + } + } + argc -= optind; + if (argc != 1) { + usage(argv[0]); + return -1; + } + // + // load synthesizer plugin + // + QDir pluginDir(INSTPREFIX "/lib/" INSTALL_NAME "/synthi"); + if (!pluginDir.exists()) { + fprintf(stderr, "plugin directory <%s> not found\n", + pluginDir.path().toLocal8Bit().data()); + return -2; + } + QString pluginName(argv[1]); + if (!pluginName.endsWith(".so", Qt::CaseInsensitive)) + pluginName += ".so"; + if (!pluginDir.exists(pluginName)) { + fprintf(stderr, "plugin <%s> in directory <%s> not found\n", + pluginName.toLocal8Bit().data(), + pluginDir.path().toLocal8Bit().data()); + return -3; + } + QString path = pluginDir.filePath(pluginName); + void* handle = dlopen(path.toLocal8Bit().data(), RTLD_LAZY); + if (handle == 0) { + fprintf(stderr, "%s: dlopen(%s) failed: %s\n", + argv[0], path.toLocal8Bit().data(), dlerror()); + return -4; + } + typedef const MESS* (*MESS_Function)(); + MESS_Function msynth = (MESS_Function)dlsym(handle, "mess_descriptor"); + if (!msynth) { + fprintf(stderr, + "%s: Unable to find msynth_descriptor() function in plugin\n" + "Are you sure this is a MESS plugin file?\n%s", + argv[0], dlerror()); + return -5; + } + const MESS* descr = msynth(); + if (descr == 0) { + fprintf(stderr, "%s: instantiate: no MESS descr found\n", + argv[0]); + return 6; + } + // + // initialize JACK + // + if (debug) { + fprintf(stderr, "init JACK audio\n"); + jack_set_error_function(jackError); + } + else + jack_set_error_function(noJackError); + + jack_client_t* client = 0; + int i = 0; + QString instanceName; + QString s(pluginName.left(pluginName.size()-3)); + s += "-%1"; + static const int MAX_INSTANCES = 500; + for (i = 0; i < MAX_INSTANCES; ++i) { + instanceName = s.arg(i); + const char* jackIdString = instanceName.toLocal8Bit().data(); + client = jack_client_new(jackIdString); + if (client) + break; + } + if (i == MAX_INSTANCES) { + fprintf(stderr, "%s: too many instances of the synth! (>%d)\n", + argv[0], MAX_INSTANCES); + return -7; + } + jack_set_error_function(jackError); + if (debug) + fprintf(stderr, "init Jack Audio: register device\n"); + // jackAudio = new JackAudio(client, jackIdString); + if (debug) + fprintf(stderr, "init Jack Audio: register client\n"); + + jack_set_process_callback(client, processAudio, 0); +// jack_set_sync_callback(_client, processSync, 0); +// jack_on_shutdown(_client, processShutdown, 0); +// jack_set_buffer_size_callback(_client, bufsize_callback, 0); +// jack_set_sample_rate_callback(_client, srate_callback, 0); +// jack_set_port_registration_callback(_client, registration_callback, 0); +// jack_set_graph_order_callback(_client, graph_callback, 0); +// jack_set_freewheel_callback (_client, freewheel_callback, 0); +// jack_set_timebase_callback(_client, 0, timebase_callback, 0); + + sampleRate = jack_get_sample_rate(client); + segmentSize = jack_get_buffer_size(client); + // + // instantiate Synthesizer + // + mess = descr->instantiate(sampleRate, 0, instanceName.toLocal8Bit().data()); + if (mess == 0) { + fprintf(stderr, "%s: instantiate failed\n", + argv[0]); + } + + int channels = mess->channels(); + if (channels > MAX_OUTPORTS) { + channels = MAX_OUTPORTS; + fprintf(stderr, "%s: too many outports %d > %d\n", + argv[0], channels, MAX_OUTPORTS); + } + for (int i = 0; i < channels; ++i) { + char portName[64]; + snprintf(portName, 64, "audioOut-%d", i); + outPorts[i] = jack_port_register(client, portName, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + inPort = jack_port_register(client, "midiIn", + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + if (mess->hasGui()) + mess->showGui(true); + qApp->exec(); + } + -- cgit v1.2.3