summaryrefslogtreecommitdiff
path: root/muse2/synti/simpledrums/simpledrums.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/synti/simpledrums/simpledrums.cpp')
-rw-r--r--muse2/synti/simpledrums/simpledrums.cpp1766
1 files changed, 0 insertions, 1766 deletions
diff --git a/muse2/synti/simpledrums/simpledrums.cpp b/muse2/synti/simpledrums/simpledrums.cpp
deleted file mode 100644
index 22f83bd4..00000000
--- a/muse2/synti/simpledrums/simpledrums.cpp
+++ /dev/null
@@ -1,1766 +0,0 @@
-//
-// C++ Implementation: simplesynth
-//
-// Description:
-//
-//
-// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include "muse/midictrl.h"
-#include "muse/midi.h"
-//#include "libsynti/mpevent.h"
-#include "muse/mpevent.h"
-#include "simpledrums.h"
-#include <qstring.h>
-#include <samplerate.h>
-
-const char* SimpleSynth::synth_state_descr[] =
- {
- "SS_INITIALIZING",
- "SS_LOADING_SAMPLE",
- "SS_CLEARING_SAMPLE",
- "SS_RUNNING"
- };
-
-const char* SimpleSynth::channel_state_descr[] =
- {
- "SS_CHANNEL_INACTIVE",
- "SS_SAMPLE_PLAYING"
- };
-
-#define SWITCH_SYNTH_STATE(state)\
-synth_state = state; \
-if (SS_DEBUG_STATE) \
- fprintf (stderr, "SS STATE: %s\n", SimpleSynth::synth_state_descr[state]);
-
-#define SWITCH_CHAN_STATE(ch, s)\
-channels[ch].state = s; \
-if (SS_DEBUG_STATE) \
- fprintf (stderr, "SS CHAN %d STATE: %s\n", ch, SimpleSynth::channel_state_descr[s]);
-
-#define SS_CHANNEL_VOLUME_QUOT 100.0
-#define SS_MASTER_VOLUME_QUOT 100.0
-int SS_samplerate;
-
-#define SS_LOG_MAX 0
-#define SS_LOG_MIN -10
-#define SS_LOG_OFFSET SS_LOG_MIN
-
-
-//
-// Map plugin parameter on domain [SS_PLUGIN_PARAM_MIN, SS_PLUGIN_PARAM_MAX] to domain [SS_LOG_MIN, SS_LOG_MAX] (log domain)
-//
-float SS_map_pluginparam2logdomain(int pluginparam_val)
- {
- float scale = (float) (SS_LOG_MAX - SS_LOG_MIN)/ (float) SS_PLUGIN_PARAM_MAX;
- float scaled = (float) pluginparam_val * scale;
- float mapped = scaled + SS_LOG_OFFSET;
- return mapped;
- }
-//
-// Map plugin parameter on domain to domain [SS_LOG_MIN, SS_LOG_MAX] to [SS_PLUGIN_PARAM_MIN, SS_PLUGIN_PARAM_MAX] (from log-> [0,127])
-// (inverse func to the above)
-int SS_map_logdomain2pluginparam(float pluginparam_log)
- {
- float mapped = pluginparam_log - SS_LOG_OFFSET;
- float scale = (float) SS_PLUGIN_PARAM_MAX / (float) (SS_LOG_MAX - SS_LOG_MIN);
- int scaled = (int) round(mapped * scale);
- return scaled;
- }
-
-//---------------------------------------------------------
-// SimpleSynth
-//---------------------------------------------------------
-SimpleSynth::SimpleSynth(int sr)
- : Mess(SS_AUDIO_CHANNELS)
- {
- SS_TRACE_IN
- SS_samplerate = sr;
- SS_initPlugins();
-
- simplesynth_ptr = this;
- master_vol = 100.0 / SS_MASTER_VOLUME_QUOT;
- master_vol_ctrlval = 100;
-
- //initialize
- for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
- channels[i].sample = 0;
- channels[i].playoffset = 0;
- channels[i].noteoff_ignore = false;
- channels[i].volume = (double) (100.0/SS_CHANNEL_VOLUME_QUOT );
- channels[i].volume_ctrlval = 100;
- channels[i].pan = 64;
- channels[i].balanceFactorL = 1.0;
- channels[i].balanceFactorR = 1.0;
- SWITCH_CHAN_STATE(i, SS_CHANNEL_INACTIVE);
- channels[i].channel_on = false;
- for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
- channels[i].sendfxlevel[j] = 0.0;
- }
- }
-
- //Process buffer:
- processBuffer[0] = new double[SS_PROCESS_BUFFER_SIZE]; //left
- processBuffer[1] = new double[SS_PROCESS_BUFFER_SIZE]; //right
-
- //Send effects
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- sendFxLineOut[i][0] = new float[SS_SENDFX_BUFFER_SIZE]; //left out
- sendFxLineOut[i][1] = new float[SS_SENDFX_BUFFER_SIZE]; //right out
- sendFxReturn[i][0] = new float[SS_SENDFX_BUFFER_SIZE]; //left in
- sendFxReturn[i][1] = new float[SS_SENDFX_BUFFER_SIZE]; //right in
- }
-
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- sendEffects[i].state = SS_SENDFX_OFF;
- sendEffects[i].plugin = 0;
- sendEffects[i].retgain = 1.0;
- sendEffects[i].retgain_ctrlval = 100;
- sendEffects[i].nrofparameters = 0;
- }
-
- //Build controller list:
- controllers[0].name = "Master volume";
- controllers[0].num = CTRL_NRPN14_OFFSET;
- controllers[0].min = 0;
- controllers[0].max = 127;
-
- int i=1;
- for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
- QString c1 = "Channel " + QString::number(ch + 1) + " volume";
- QString c2 = "Channel " + QString::number(ch + 1) + " pan";
- QString c3 = "Channel " + QString::number(ch + 1) + " noteoff ignore";
- QString c4 = "Channel " + QString::number(ch + 1) + " on/off";
- QString c5 = "Channel " + QString::number(ch + 1) + " fx send 1";
- QString c6 = "Channel " + QString::number(ch + 1) + " fx send 2";
- QString c7 = "Channel " + QString::number(ch + 1) + " fx send 3";
- QString c8 = "Channel " + QString::number(ch + 1) + " fx send 4";
- controllers[i].name = c1.toLatin1();
- controllers[i].num = CTRL_NRPN14_OFFSET+i;
- controllers[i].min = 0;
- controllers[i].max = 127;
-
- controllers[i+1].name = c2.toLatin1();
- controllers[i+1].num = CTRL_NRPN14_OFFSET+i+1;
- controllers[i+1].min = 0;
- controllers[i+1].max = 127;
-
- controllers[i+2].name = c3.toLatin1();
- controllers[i+2].num = CTRL_NRPN14_OFFSET+i+2;
- controllers[i+2].min = 0;
- controllers[i+2].max = 1;
-
- controllers[i+3].name = c4.toLatin1();
- controllers[i+3].num = CTRL_NRPN14_OFFSET+i+3;
- controllers[i+3].min = 0;
- controllers[i+3].max = 1;
-
- controllers[i+4].name = c5.toLatin1();
- controllers[i+4].num = CTRL_NRPN14_OFFSET+i+4;
-
- controllers[i+5].name = c6.toLatin1();
- controllers[i+5].num = CTRL_NRPN14_OFFSET+i+5;
-
- controllers[i+6].name = c7.toLatin1();
- controllers[i+6].num = CTRL_NRPN14_OFFSET+i+6;
-
- controllers[i+7].name = c8.toLatin1();
- controllers[i+7].num = CTRL_NRPN14_OFFSET+i+7;
-
- controllers[i+4].min = controllers[i+5].min = controllers[i+6].min = controllers[i+7].min = 0;
- controllers[i+4].max = controllers[i+5].max = controllers[i+6].max = controllers[i+7].max = 127;
-
- i+=8;
- }
-
- for (int sfx=0; sfx<SS_NR_OF_SENDEFFECTS; sfx++) {
- QString c1 = "Sendfx " + QString::number(sfx) + " ret gain";
- QString c2 = "Sendfx " + QString::number(sfx) + " on/off";
- controllers[i].name = c1.toLatin1();
- controllers[i].num = CTRL_NRPN14_OFFSET+i;
- controllers[i].min = 0;
- controllers[i].max = 127;
-
- controllers[i+1].name = c2.toLatin1();
- controllers[i+1].num = CTRL_NRPN14_OFFSET+i+1;
- controllers[i+1].min = 0;
- controllers[i+1].max = 1;
- i+=2;
- }
-
- pthread_mutex_init(&SS_LoaderMutex, NULL);
- SS_TRACE_OUT
- }
-
-//---------------------------------------------------------
-// ~SimpleSynth
-//---------------------------------------------------------
-SimpleSynth::~SimpleSynth()
- {
- SS_TRACE_IN
-
- // Cleanup channels and samples:
- SS_DBG("Cleaning up sample data");
- for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
- if (channels[i].sample) {
- delete[] channels[i].sample->data;
- delete channels[i].sample;
- }
- }
- simplesynth_ptr = NULL;
-
- SS_DBG("Deleting pluginlist");
- //Cleanup plugins:
- for (iPlugin i = plugins.begin(); i != plugins.end(); ++i) {
- delete (*i);
- }
- plugins.clear();
-
- SS_DBG("Deleting sendfx buffers");
- //Delete sendfx buffers:
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- delete[] sendFxLineOut[i][0];
- delete[] sendFxLineOut[i][1];
- delete[] sendFxReturn[i][0];
- delete[] sendFxReturn[i][1];
- }
-
- //processBuffer:
- SS_DBG("Deleting process buffer");
- delete[] processBuffer[0];
- delete[] processBuffer[1];
- SS_TRACE_OUT
- }
-
-//---------------------------------------------------------
-// nativeGuiVisible
-/*!
- \fn SimpleSynth::nativeGuiVisible
- \brief Tells if the gui is hidden or shown
- \return true/false if gui is shown/hidden
- */
-//---------------------------------------------------------
-bool SimpleSynth::nativeGuiVisible() const
- {
- SS_TRACE_IN
- bool v = gui->isVisible();
- SS_TRACE_OUT
- return v;
- }
-
-//---------------------------------------------------------
-// hasNativeGui
-/*!
- \fn SimpleSynth::hasNativeGui
- \brief Tells if the synth has a gui or not
- \return true if synth has gui, false it synth has no gui
- */
-//---------------------------------------------------------
-bool SimpleSynth::hasNativeGui() const
- {
- SS_TRACE_IN
- SS_TRACE_OUT
- return true;
- }
-
-//---------------------------------------------------------
-// playNote
-/*!
- \fn SimpleSynth::playNote
- \brief Triggers a note on (noteoffs are noteons with velo=0)
- \param channel midi channel
- \param pitch note pitch
- \param velo note velocity
- \return false for ok, true for not ok (not sure these are handled differently, but...)
- */
-//---------------------------------------------------------
-bool SimpleSynth::playNote(int /*channel*/, int pitch, int velo)
- {
- SS_TRACE_IN
- //Don't bother about channel, we're processing every playnote!
- if ((pitch >= SS_LOWEST_NOTE) && (pitch <= SS_HIGHEST_NOTE)) {
- bool noteOff = (velo == 0 ? 1 : 0);
- int ch = pitch - SS_LOWEST_NOTE;
- if(!noteOff) {
- if (channels[ch].sample) {
- //Turn on the white stuff:
- channels[ch].playoffset = 0;
- SWITCH_CHAN_STATE(ch , SS_SAMPLE_PLAYING);
- channels[ch].cur_velo = (double) velo / 127.0;
- channels[ch].gain_factor = channels[ch].cur_velo * channels[ch].volume;
- if (SS_DEBUG_MIDI) {
- printf("Playing note %d on channel %d\n", pitch, ch);
- }
- }
- }
- else {
- //Note off:
- if (channels[ch].noteoff_ignore) {
- if (SS_DEBUG_MIDI) {
- printf("Note off on channel %d\n", ch);
- }
- SWITCH_CHAN_STATE(ch , SS_CHANNEL_INACTIVE);
- channels[ch].playoffset = 0;
- channels[ch].cur_velo = 0;
- }
- }
- }
- SS_TRACE_OUT
- return false;
- }
-
-//---------------------------------------------------------
-// processEvent
-/*!
- \fn SimpleSynth::processEvent
- \brief All events from sequencer first shows up here and are forwarded to their correct functions
- \param event The event sent from sequencer
- \return false for ok, true for not ok
- */
-//---------------------------------------------------------
-bool SimpleSynth::processEvent(const MidiPlayEvent& ev)
- {
- SS_TRACE_IN
- switch(ev.type()) {
- case ME_CONTROLLER:
- if (SS_DEBUG_MIDI) {
- printf("SimpleSynth::processEvent - Controller. Chan: %x dataA: %x dataB: %x\n", ev.channel(), ev.dataA(), ev.dataB());
- for (int i=0; i< ev.len(); i++)
- printf("%x ", ev.data()[i]);
- }
- setController(ev.channel(), ev.dataA(), ev.dataB(), false);
- return true;
- case ME_NOTEON:
- return playNote(ev.channel(), ev.dataA(), ev.dataB());
- case ME_NOTEOFF:
- return playNote(ev.channel(), ev.dataA(), 0);
- case ME_SYSEX:
- //Debug print
- if (SS_DEBUG_MIDI) {
- printf("SimpleSynth::processEvent - Sysex received\n");
- for (int i=0; i< ev.len(); i++)
- printf("%x ", ev.data()[i]);
- printf("\n");
- }
- return sysex(ev.len(), ev.data());
- }
- return false;
- SS_TRACE_OUT
- }
-
-//---------------------------------------------------------
-// setController
-/*!
- \fn SimpleSynth::setController
- \brief Called from sequencer indirectly via SimpleSynth::processEvent
- \brief when the synth is supposed to set a controller value
- \param channel channel nr
- \param id controller id
- \param val value of controller
- \return false for ok, true for not ok
- */
-//---------------------------------------------------------
-bool SimpleSynth::setController(int channel, int id, int val)
- {
- SS_TRACE_IN
- if (SS_DEBUG_MIDI) {
- printf("SimpleSynth::setController - received controller on channel %d, id %d value %d\n", channel, id, val);
- }
-
- // Channel controllers:
- if (id >= SS_FIRST_CHANNEL_CONTROLLER && id <= SS_LAST_CHANNEL_CONTROLLER ) {
- // Find out which channel we're dealing with:
- id-= SS_FIRST_CHANNEL_CONTROLLER;
- int ch = (id / SS_NR_OF_CHANNEL_CONTROLLERS);
- id = (id % SS_NR_OF_CHANNEL_CONTROLLERS);
-
- switch (id) {
- case SS_CHANNEL_CTRL_VOLUME:
- if (SS_DEBUG_MIDI)
- printf("Received channel ctrl volume %d for channel %d\n", val, ch);
- channels[ch].volume_ctrlval = val;
- updateVolume(ch, val);
- break;
- case SS_CHANNEL_CTRL_NOFF:
- if (SS_DEBUG_MIDI)
- printf("Received ctrl noff %d for channel %d\n", val, ch);
- channels[ch].noteoff_ignore = val;
- break;
- case SS_CHANNEL_CTRL_PAN:
- {
- if (SS_DEBUG_MIDI)
- printf("Received ctrl pan %d for channel %d\n", val, ch);
- channels[ch].pan = val;
- updateBalance(ch, val);
- break;
- }
- case SS_CHANNEL_CTRL_ONOFF:
- {
- if (SS_DEBUG_MIDI)
- printf("Received ctrl onoff %d for channel %d\n", val, ch);
-
- if (val == false && channels[ch].channel_on == true) {
- SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
- channels[ch].channel_on = val;
- }
- else if (val == true && channels[ch].channel_on == false) { // if it actually _was_ off:
- SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
- channels[ch].playoffset = 0;
- channels[ch].channel_on = val;
- }
- break;
- }
- case SS_CHANNEL_SENDFX1:
- case SS_CHANNEL_SENDFX2:
- case SS_CHANNEL_SENDFX3:
- case SS_CHANNEL_SENDFX4:
- {
- int fxid = id - SS_CHANNEL_SENDFX1;
- channels[ch].sendfxlevel[fxid] = (double)val/127.0;
- break;
- }
-
- default:
- if (SS_DEBUG_MIDI)
- printf("Unknown controller received for channel %d. id=%d\n", ch, id);
- break;
- }
- }
- // Master controllers:
- else if (id >= SS_FIRST_MASTER_CONTROLLER && id <= SS_LAST_MASTER_CONTROLLER) {
- if (SS_DEBUG_MIDI)
- printf("Mastervol controller received: %d\n", id);
- master_vol_ctrlval = val;
- master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
- }
- // Emmm, this one should've been there in the beginning
- else if (id == CTRL_VOLUME) {
- if (SS_DEBUG_MIDI) {
- printf("Ctrl volume received: vol: %d\n", val);
- }
- master_vol_ctrlval = val;
- master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
- //This one can't be from the gui, update gui:
- guiUpdateMasterVol(val);
- }
- // Plugin controllers:
- else if (id >= SS_FIRST_PLUGIN_CONTROLLER && id <= SS_LAST_PLUGIN_CONTROLLER) {
-
- int fxid = (id - SS_FIRST_PLUGIN_CONTROLLER) / SS_NR_OF_PLUGIN_CONTROLLERS;
- int cmd = (id - SS_FIRST_PLUGIN_CONTROLLER) % SS_NR_OF_PLUGIN_CONTROLLERS;
-
- // Plugin return-gain:
- if (cmd == SS_PLUGIN_RETURN) {
- if (SS_DEBUG_MIDI)
- printf("Ctrl fx retgain received: fxid: %d val: %d\n", fxid, val);
- sendEffects[fxid].retgain_ctrlval = val;
- sendEffects[fxid].retgain = (double) val / 75.0;
- }
- // Plugin on/off:
- else if (cmd == SS_PLUGIN_ONOFF) {
- if (SS_DEBUG_MIDI)
- printf("Ctrl fx onoff received: fxid: %d val: %d\n", fxid, val);
- sendEffects[fxid].state = (SS_SendFXState) val;
- }
- }
- else {
- if (SS_DEBUG_MIDI)
- printf("Unknown controller received: %d\n", id);
- }
- SS_TRACE_OUT
- return false;
- }
-
-//---------------------------------------------------------
-/*!
- \fn SimpleSynth::setController
- */
-//---------------------------------------------------------
-bool SimpleSynth::setController(int channel, int id, int val, bool /*fromGui*/)
- {
- SS_TRACE_IN
- bool ret = setController(channel, id, val); //Perhaps TODO... Separate events from the gui
- SS_TRACE_OUT
- return ret;
- }
-//---------------------------------------------------------
-// sysex
-/*!
- \fn SimpleSynth::sysex
- \brief Called from sequencer indirectly via SimpleSynth::processEvent
- \param len length of the sysex data
- \param data the sysex data
- \return false for ok, true for not ok
-*/
-//---------------------------------------------------------
-bool SimpleSynth::sysex(int /*len*/, const unsigned char* data)
- {
- SS_TRACE_IN
- int cmd = data[0];
- switch (cmd) {
- case SS_SYSEX_LOAD_SAMPLE:
- {
- int channel = data[1];
- //int l = data[2];
- const char* filename = (const char*)(data+3);
- if (SS_DEBUG_MIDI) {
- printf("Sysex cmd: load sample, filename %s, on channel: %d\n", filename, channel);
- }
- loadSample(channel, filename);
- break;
- }
- case SS_SYSEX_CLEAR_SAMPLE:
- {
- int ch = data[1];
- clearSample(ch);
- break;
- }
-
- case SS_SYSEX_INIT_DATA:
- {
- parseInitData(data);
- break;
- }
-
- case SS_SYSEX_LOAD_SENDEFFECT:
- {
- int fxid = data[1];
- QString lib = (const char*) (data + 2);
- QString label = (const char*) (data + lib.length() + 3);
- if (SS_DEBUG_MIDI) {
- printf("Sysex cmd load effect: %d %s %s\n", fxid, lib.toLatin1(), label.toLatin1());
- }
- initSendEffect(fxid, lib, label);
- break;
- }
-
- case SS_SYSEX_CLEAR_SENDEFFECT:
- {
- int fxid = data[1];
- if (SS_DEBUG_MIDI) {
- printf("Sysex cmd clear effect: %d\n", fxid);
- }
- sendEffects[fxid].state = SS_SENDFX_OFF;
- cleanupPlugin(fxid);
- sendEffects[fxid].plugin = 0;
- break;
- }
-
- case SS_SYSEX_SET_PLUGIN_PARAMETER:
- {
- int fxid = data[1];
- int parameter = data[2];
- int val = data[3];
- // Write it to the plugin:
- float floatval = sendEffects[fxid].plugin->convertGuiControlValue(parameter, val);
- setFxParameter(fxid, parameter, floatval);
- break;
- }
-
- case SS_SYSEX_GET_INIT_DATA:
- {
- int initdata_len = 0;
- const byte* tmp_initdata = NULL;
- byte* event_data = NULL;
-
- getInitData(&initdata_len, &tmp_initdata);
- int totlen = initdata_len + 1;
-
- event_data = new byte[initdata_len + 1];
- event_data[0] = SS_SYSEX_SEND_INIT_DATA;
- memcpy(event_data + 1, tmp_initdata, initdata_len);
- delete[] tmp_initdata;
- tmp_initdata = NULL;
-
- MidiPlayEvent ev(0, 0, ME_SYSEX, event_data, totlen);
- gui->writeEvent(ev);
- delete[] event_data;
-
- break;
- }
-
- default:
- if (SS_DEBUG_MIDI)
- printf("Unknown sysex cmd received: %d\n", cmd);
- break;
- }
- SS_TRACE_OUT
- return false;
- }
-
-//---------------------------------------------------------
-// getPatchName
-/*!
- \fn SimpleSynth::getPatchName
- \brief Called from host to get names of patches
- \param index - which patchnr we're about to deliver
- \param drum - is it a drum track?
- \return const char* with patchname
- */
-//---------------------------------------------------------
-const char* SimpleSynth::getPatchName(int /*index*/, int, int, bool /*drum*/) const
- {
- SS_TRACE_IN
- SS_TRACE_OUT
- //return 0;
- //return "<unknown>";
- return "SimpleSynth";
- }
-
-//---------------------------------------------------------
-// getPatchInfo
-/*!
- \fn SimpleSynth::getPatchInfo
- \brief Called from host to get info about patches
- \param index - which patchnr we're about to deliver
- \param patch - if this one is 0, this is the first call, otherwise keep deliver the host patches... or something
- \return MidiPatch with patch info for host
- */
-//---------------------------------------------------------
-const MidiPatch* SimpleSynth::getPatchInfo(int index, const MidiPatch* patch) const
- {
- SS_TRACE_IN
- index = 0; patch = 0;
- SS_TRACE_OUT
- return 0;
- }
-
-//---------------------------------------------------------
-// getControllerInfo
-/*!
- \fn SimpleSynth::getControllerInfo
- \brief Called from host to collect info about which controllers the synth supports
- \param index current controller number
- \param name pointer where name is stored
- \param controller int pointer where muse controller number is stored
- \param min int pointer where controller min value is stored
- \param max int pointer where controller max value is stored
- \return 0 when done, otherwise return next desired controller index
- */
-//---------------------------------------------------------
-int SimpleSynth::getControllerInfo(int index, const char** name, int* controller, int* min, int* max, int* /*initval*/ ) const
- {
- SS_TRACE_IN
- if (index >= SS_NR_OF_CONTROLLERS) {
- SS_TRACE_OUT
- return 0;
- }
-
- *name = controllers[index].name.c_str();
- *controller = controllers[index].num;
- *min = controllers[index].min;
- *max = controllers[index].max;
-
- if (SS_DEBUG_MIDI) {
- printf("setting controller info: index %d name %s controller %d min %d max %d\n", index, *name, *controller, *min, *max);
- }
- SS_TRACE_OUT
- return (index +1);
- }
-
-//---------------------------------------------------------
-// processMessages
-/*!
- \fn SimpleSynth::processMessages
- \brief Called from host always, even if output path is unconnected
- */
-//---------------------------------------------------------
-void SimpleSynth::processMessages()
-{
- //Process messages from the gui
- while (gui->fifoSize())
- {
- MidiPlayEvent ev = gui->readEvent();
- if (ev.type() == ME_SYSEX)
- {
- sysex(ev.len(), ev.data());
- sendEvent(ev);
- }
- else if (ev.type() == ME_CONTROLLER)
- {
- setController(ev.channel(), ev.dataA(), ev.dataB(), true);
- sendEvent(ev);
- }
- else
- {
- if(SS_DEBUG)
- printf("SimpleSynth::process(): unknown event, type: %d\n", ev.type());
- }
- }
-}
-
-//---------------------------------------------------------
-// process
-/*!
- \fn SimpleSynth::process
- \brief Realtime function where the processing actually occurs. Called from host, ONLY if output path is connected.
- \param channels - audio data
- \param offset - sample offset
- \param len - nr of samples to process
- */
-//---------------------------------------------------------
-void SimpleSynth::process(float** out, int offset, int len)
- {
- /*
- //Process messages from the gui
- while (gui->fifoSize()) {
- MidiPlayEvent ev = gui->readEvent();
- if (ev.type() == ME_SYSEX) {
- sysex(ev.len(), ev.data());
- sendEvent(ev);
- }
- else if (ev.type() == ME_CONTROLLER) {
- setController(ev.channel(), ev.dataA(), ev.dataB(), true);
- sendEvent(ev);
- }
- else {
- if (SS_DEBUG)
- printf("SimpleSynth::process(): unknown event, type: %d\n", ev.type());
- }
- }
- */
-
- if (synth_state == SS_RUNNING) {
-
- //Temporary mix-doubles
- double out1, out2;
- //double ltemp, rtemp;
- float* data;
- // Velocity factor:
- double gain_factor;
-
-
- // Clear send-channels. Skips if fx not turned on
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- if (sendEffects[i].state == SS_SENDFX_ON) {
- memset(sendFxLineOut[i][0], 0, SS_SENDFX_BUFFER_SIZE * sizeof(float));
- memset(sendFxLineOut[i][1], 0, SS_SENDFX_BUFFER_SIZE * sizeof(float));
- }
- }
-
-
- memset(out[0] + offset, 0, len * sizeof(float));
- memset(out[1] + offset, 0, len * sizeof(float));
-
- //Process 1 channel at a time
- for (int ch=0; ch < SS_NR_OF_CHANNELS; ch++) {
- // If channels is turned off, skip:
- if (channels[ch].channel_on == false)
- continue;
-
- //If sample isn't playing, skip:
- if (channels[ch].state == SS_SAMPLE_PLAYING) {
- memset(processBuffer[0], 0, SS_PROCESS_BUFFER_SIZE * sizeof(double));
- memset(processBuffer[1], 0, SS_PROCESS_BUFFER_SIZE * sizeof(double));
-
- for (int i=0; i<len; i++) {
- // Current channel sample data:
- data = channels[ch].sample->data;
- gain_factor = channels[ch].gain_factor;
- // Current velocity factor:
-
- if (channels[ch].sample->channels == 2) {
- //
- // Stereo sample:
- //
- // Add from sample:
- out1 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorL);
- out2 = (double) (data[channels[ch].playoffset + 1] * gain_factor * channels[ch].balanceFactorR);
- channels[ch].playoffset += 2;
- }
- else {
- //
- // Mono sample:
- //
- out1 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorL);
- out2 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorR);
- channels[ch].playoffset++;
- }
-
- processBuffer[0][i] = out1;
- processBuffer[1][i] = out2;
-
- // If send-effects tap is on, tap signal to respective lineout channel
- for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
- if (channels[ch].sendfxlevel[j] != 0.0) {
- //If the effect has 2 inputs (stereo in):
- if (sendEffects[j].inputs == 2) {
- sendFxLineOut[j][0][i]+= (out1 * channels[ch].sendfxlevel[j]);
- sendFxLineOut[j][1][i]+= (out2 * channels[ch].sendfxlevel[j]);
- }
- //If the effect is mono (1 input), only use first fxLineOut
- else if (sendEffects[j].inputs == 1) {
- sendFxLineOut[j][0][i]+= ((out1 + out2) * channels[ch].sendfxlevel[j] / 2.0);
- }
- //Effects with 0 or >2 inputs are ignored
- }
- }
-
- //
- // If we've reached the last sample, set state to inactive
- //
- if (channels[ch].playoffset >= channels[ch].sample->samples) {
- SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
- channels[ch].playoffset = 0;
- break;
- }
- }
- // Add contribution for this channel, for this frame, to final result:
- for (int i=0; i<len; i++) {
- out[0][i+offset]+=processBuffer[0][i];
- out[1][i+offset]+=processBuffer[1][i];
- }
- }
- }
- // Do something funny with the sendies:
- for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
- if (sendEffects[j].state == SS_SENDFX_ON) {
- sendEffects[j].plugin->process(len);
- for (int i=0; i<len; i++) {
- //Effect has mono output:
- if (sendEffects[j].outputs == 1) {
- //Add the result to both channels:
- out[0][i+offset]+=((sendEffects[j].retgain * sendFxReturn[j][0][i]) / 2.0);
- out[1][i+offset]+=((sendEffects[j].retgain * sendFxReturn[j][0][i]) / 2.0);
- }
- else if (sendEffects[j].outputs == 2) {
- // Effect has stereo output
- out[0][i+offset]+=(sendEffects[j].retgain * sendFxReturn[j][0][i]);
- out[1][i+offset]+=(sendEffects[j].retgain * sendFxReturn[j][1][i]);
- }
- }
- }
- }
- // Finally master gain:
- for (int i=0; i<len; i++) {
- out[0][i+offset] = (out[0][i+offset] * master_vol);
- out[1][i+offset] = (out[1][i+offset] * master_vol);
- }
- }
- }
-
-//---------------------------------------------------------
-// showNativeGui
-/*!
- \fn SimpleSynth::showNativeGui
- \brief Displays or hides the gui window
- \param val true or false = gui shown or hidden
- */
-//---------------------------------------------------------
-void SimpleSynth::showNativeGui(bool val)
- {
- SS_TRACE_IN
- gui->setVisible(val);
- SS_TRACE_OUT
- }
-
-//---------------------------------------------------------
-/*!
- \fn SimpleSynth::init
- \brief Initializes the SimpleSynth
- \param name string set to caption in the gui dialog
- \return true if successful, false if unsuccessful
- */
-//---------------------------------------------------------
-bool SimpleSynth::init(const char* name)
- {
- SS_TRACE_IN
- SWITCH_SYNTH_STATE(SS_INITIALIZING);
- gui = new SimpleSynthGui();
- gui->show();
- gui->setCaption(name);
- SWITCH_SYNTH_STATE(SS_RUNNING);
- SS_TRACE_OUT
- return true;
- }
-
-//---------------------------------------------------------
-/*!
- \fn SimpleSynth::getInitData
- \brief Data for reinitialization of SimpleSynth when loading project
- \param n - number of chars used in the data
- \param data - data that is sent as a sysex to the synth on reload of project
- */
-//---------------------------------------------------------
-void SimpleSynth::getInitData(int* n, const unsigned char** data) const
- {
- SS_TRACE_IN
- // Calculate length of data
- // For each channel, we need to store volume, pan, noff, onoff
- int len = SS_NR_OF_CHANNEL_CONTROLLERS * SS_NR_OF_CHANNELS;
- // Sampledata: filenames len
- for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
- if (channels[i].sample) {
- int filenamelen = strlen(channels[i].sample->filename.c_str()) + 2;
- len+=filenamelen;
- }
- else
- len++; //Add place for SS_NO_SAMPLE
- }
- len+=3; // 1 place for SS_SYSEX_INIT_DATA, 1 byte for master vol, 1 byte for version data
-
- // Effect data length
- len++; //Add place for SS_SYSEX_INIT_DATA_VERSION, as control
-
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- Plugin* plugin = sendEffects[i].plugin;
- if (plugin) {
- int namelen = strlen(plugin->lib()) + 2;
- int labelnamelen = strlen(plugin->label()) + 2;
- len+=(namelen + labelnamelen);
-
- len+=3; //1 byte for nr of parameters, 1 byte for return gain, 1 byte for effect on/off
- len+=sendEffects[i].nrofparameters; // 1 byte for each parameter value
- }
- else {
- len++; //place for SS_NO_PLUGIN
- }
- }
-
- // First, SS_SYSEX_INIT_DATA
- byte* buffer = new byte[len];
- memset(buffer, 0, len);
- buffer[0] = SS_SYSEX_INIT_DATA;
- buffer[1] = SS_SYSEX_INIT_DATA_VERSION;
- if (SS_DEBUG_INIT) {
- printf("Length of init data: %d\n", len);
- printf("buffer[0] - SS_SYSEX_INIT_DATA: %d\n", SS_SYSEX_INIT_DATA);
- printf("buffer[1] - SS_SYSEX_INIT_DATA_VERSION: %d\n", SS_SYSEX_INIT_DATA_VERSION);
- }
- int i = 2;
- // All channels:
- // 0 - volume ctrlval (0-127)
- // 1 - pan (0-127)
- // 2 - noff ignore (0-1)
- // 3 - channel on/off (0-1)
- // 4 - 7 - sendfx 1-4 (0-127)
- // 8 - len of filename, n
- // 9 - 9+n - filename
- for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
- buffer[i] = (byte) channels[ch].volume_ctrlval;
- buffer[i+1] = (byte) channels[ch].pan;
- buffer[i+2] = (byte) channels[ch].noteoff_ignore;
- buffer[i+3] = (byte) channels[ch].channel_on;
- buffer[i+4] = (byte) round(channels[ch].sendfxlevel[0] * 127.0);
- buffer[i+5] = (byte) round(channels[ch].sendfxlevel[1] * 127.0);
- buffer[i+6] = (byte) round(channels[ch].sendfxlevel[2] * 127.0);
- buffer[i+7] = (byte) round(channels[ch].sendfxlevel[3] * 127.0);
-
- if (SS_DEBUG_INIT) {
- printf("Channel %d:\n", ch);
- printf("buffer[%d] - channels[ch].volume_ctrlval = \t%d\n", i, channels[ch].volume_ctrlval);
- printf("buffer[%d] - channels[ch].pan = \t\t%d\n", i+1, channels[ch].pan);
- printf("buffer[%d] - channels[ch].noteoff_ignore = \t%d\n", i+2, channels[ch].noteoff_ignore );
- printf("buffer[%d] - channels[ch].channel_on = \t%d\n", i+3, channels[ch].channel_on);
- for (int j= i+4; j < i+8; j++) {
- printf("buffer[%d] - channels[ch].sendfxlevel[%d]= \t%d\n", j, j-i-4, (int)round(channels[ch].sendfxlevel[j-i-4] * 127.0));
- }
- }
- if (channels[ch].sample) {
- int filenamelen = strlen(channels[ch].sample->filename.c_str()) + 1;
- buffer[i+8] = (byte) filenamelen;
- memcpy((buffer+(i+9)), channels[ch].sample->filename.c_str(), filenamelen);
- if (SS_DEBUG_INIT) {
- printf("buffer[%d] - filenamelen: %d\n", i+8, filenamelen);
- printf("buffer[%d] - buffer[%d] - filename: ", (i+9), (i+9) + filenamelen - 1);
- for (int j = i+9; j< i+9+filenamelen; j++) {
- printf("%c",buffer[j]);
- }
- printf("\n");
- }
- i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1 + filenamelen);
- }
- else {
- buffer[i+8] = SS_NO_SAMPLE;
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: SS_NO_SAMPLE: - %d\n", i+8, SS_NO_SAMPLE);
- }
- i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1);
- }
- }
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: Master vol: - %d\n", i, master_vol_ctrlval);
- }
- buffer[i] = master_vol_ctrlval;
- *(data) = buffer; *n = len;
- i++;
-
- //Send effects:
- buffer[i] = SS_SYSEX_INIT_DATA_VERSION; //Just for check
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: Control value, SS_SYSEX_INIT_DATA_VERSION\n", i);
- }
- i++;
-
- for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
- if (sendEffects[j].plugin) {
- int labelnamelen = strlen(sendEffects[j].plugin->label()) + 1;
- buffer[i] = labelnamelen;
- memcpy((buffer+i+1), sendEffects[j].plugin->label(), labelnamelen);
- if (SS_DEBUG_INIT) {
- printf("buffer[%d] - labelnamelen: %d\n", i, labelnamelen);
- printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + labelnamelen - 1);
- for (int k = i+1; k < i+1+labelnamelen; k++) {
- printf("%c",buffer[k]);
- }
- printf("\n");
- }
-
- i+=(labelnamelen + 1);
-
- int namelen = strlen(sendEffects[j].plugin->lib()) + 1;
- buffer[i] = namelen;
- memcpy((buffer+i+1), sendEffects[j].plugin->lib(), namelen);
- if (SS_DEBUG_INIT) {
- printf("buffer[%d] - libnamelen : %d\n", i, namelen);
- printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + namelen - 1);
- for (int k = i+1; k < i+1+namelen; k++) {
- printf("%c",buffer[k]);
- }
- printf("\n");
- }
-
- i+=(namelen + 1);
-
- buffer[i]=sendEffects[j].nrofparameters;
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: sendEffects[%d].nrofparameters=%d\n", i, j, buffer[i]);
- }
- i++;
-
- buffer[i]=sendEffects[j].retgain_ctrlval;
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: sendEffects[%d].retgain_ctrlval=%d\n", i, j, buffer[i]);
- }
- i++;
-
- for (int k=0; k<sendEffects[j].nrofparameters; k++) {
- //TODO: Convert to 127-scale
- buffer[i] = sendEffects[j].plugin->getGuiControlValue(k);
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: sendEffects[%d].parameterval[%d]=%d\n", i, j, k, buffer[i]);
- }
- i++;
- }
- }
- // No plugin loaded:
- else {
- buffer[i] = SS_NO_PLUGIN;
- if (SS_DEBUG_INIT) {
- printf("buffer[%d]: SS_NO_PLUGIN\n", i);
- }
- i++;
- }
- }
-
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::parseInitData()
- */
-void SimpleSynth::parseInitData(const unsigned char* data)
- {
- SS_TRACE_IN
- //int len = strlen((const char*)data);
- if (SS_DEBUG_INIT) {
- printf("buffer[1], SS_SYSEX_INIT_DATA_VERSION=%d\n", *(data+1));
- }
- const byte* ptr = data+2;
- for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
- channels[ch].volume_ctrlval = (byte) *(ptr);
-
- if (SS_DEBUG_INIT) {
- printf("Channel %d:\n", ch);
- printf("buffer[%zd] - channels[ch].volume_ctrlval = \t%d\n", ptr-data, *ptr);
- printf("buffer[%zd] - channels[ch].pan = \t\t%d\n", ptr-data+1, *(ptr+1));
- printf("buffer[%zd] - channels[ch].noteoff_ignore = \t%d\n", ptr-data+2, *(ptr+2));
- printf("buffer[%zd] - channels[ch].channel_on = \t%d\n", ptr-data+3, *(ptr+3));
- }
- updateVolume(ch, *(ptr));
- guiUpdateVolume(ch, *(ptr));
-
- channels[ch].pan = *(ptr+1);
- updateBalance(ch, *(ptr+1));
- guiUpdateBalance(ch, *(ptr+1));
-
- channels[ch].noteoff_ignore = *(ptr+2);
- guiUpdateNoff(ch, *(ptr+2));
-
- channels[ch].channel_on = *(ptr+3);
- guiUpdateChoff(ch, *(ptr+3));
-
- ptr+=4;
-
- for (int i=0; i<4; i++) {
- channels[ch].sendfxlevel[i] = (float) (*(ptr)/127.0);
- guiUpdateSendFxLevel(ch, i, *(ptr));
- ptr++;
- }
-
- bool hasSample = *(ptr);
- ptr++;
-
- channels[ch].sample = 0;
- channels[ch].playoffset = 0;
- SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
- if (SS_DEBUG_INIT) {
- printf("parseInitData: channel %d, volume: %f pan: %d bfL %f bfR %f chON %d s1: %f s2: %f s3: %f s4: %f\n",
- ch,
- channels[ch].volume,
- channels[ch].pan,
- channels[ch].balanceFactorL,
- channels[ch].balanceFactorR,
- channels[ch].channel_on,
- channels[ch].sendfxlevel[0],
- channels[ch].sendfxlevel[1],
- channels[ch].sendfxlevel[2],
- channels[ch].sendfxlevel[3]
- );
- }
- if (hasSample) {
- std::string filenametmp = (const char*) ptr;
- ptr+= strlen(filenametmp.c_str()) + 1;
- //printf("We should load %s\n", filenametmp.c_str());
- loadSample(ch, filenametmp.c_str());
- }
- else {
- //Clear sample
- clearSample(ch);
- guiNotifySampleCleared(ch);
- }
- }
- //Master vol:
- master_vol_ctrlval = *(ptr);
- master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
- guiUpdateMasterVol(master_vol_ctrlval);
- if (SS_DEBUG_INIT) {
- printf("Master vol: %d\n", master_vol_ctrlval);
- }
- ptr++;
-
- // Effects:
- if (*(ptr) != SS_SYSEX_INIT_DATA_VERSION) {
- fprintf(stderr, "Error loading init data - control byte not found. Skipping...\n");
- SS_TRACE_OUT
- return;
- }
- ptr++;
-
- for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
- if (SS_DEBUG_INIT)
- printf("buffer[%zd] - sendeffect[%d], labelnamelen=%d\n", ptr-data, i, *ptr);
- int labelnamelen = *(ptr);
-
- if (labelnamelen != SS_NO_PLUGIN) {
- ptr++;
- std::string labelnametmp = (const char*) ptr;
- ptr+= labelnamelen;
-
- //int libnamelen = *(ptr);
- ptr++;
- std::string libnametmp = (const char*) ptr;
- ptr+= strlen(libnametmp.c_str()) + 1;
-
-
- initSendEffect(i, libnametmp.c_str(), labelnametmp.c_str());
- //initSendEffect(0, "cmt", "freeverb3");
-
- byte params = *(ptr);
- byte retgain = *(ptr+1);
- ptr+=2;
-
- sendEffects[i].nrofparameters = params;
-
- sendEffects[i].retgain_ctrlval = retgain;
- sendEffects[i].retgain = retgain;
- sendEffects[i].retgain = (double) retgain/ 75.0;
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_PLUGIN_RETURNLEVEL_CONTROLLER(i), retgain);
- gui->writeEvent(ev);
-
- for (int j=0; j<params; j++) {
- if (SS_DEBUG_INIT)
- printf("buffer[%zd] - sendeffect[%d], parameter[%d]=%d\n", ptr-data, i, j, *ptr);
- setFxParameter(i, j, sendEffects[i].plugin->convertGuiControlValue(j, *(ptr)));
- ptr++;
- }
- }
- else {
- if (sendEffects[i].plugin)
- cleanupPlugin(i);
- ptr++;
- }
- }
-
- SS_TRACE_OUT
- }
-
-/*!
- \fn SimpleSynth::loadSample(int chno, const char* filename)
- */
-bool SimpleSynth::loadSample(int chno, const char* filename)
- {
- SS_TRACE_IN
- SS_Channel* ch = &channels[chno];
-
- // Thread stuff:
- SS_SampleLoader* loader = new SS_SampleLoader;
- loader->channel = ch;
- loader->filename = std::string(filename);
- loader->ch_no = chno;
- if (SS_DEBUG) {
- printf("Loader filename is: %s\n", filename);
- }
- pthread_t sampleThread;
- pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
- pthread_attr_init(attributes);
- pthread_attr_setdetachstate(attributes, PTHREAD_CREATE_DETACHED);
- if (pthread_create(&sampleThread, attributes, ::loadSampleThread, (void*) loader)) {
- perror("creating thread failed:");
- pthread_attr_destroy(attributes);
- delete loader;
- return false;
- }
-
- pthread_attr_destroy(attributes);
- SS_TRACE_OUT
- return true;
- }
-
-/*!
- \fn loadSampleThread(void* p)
- \brief Since process needs to respond withing a certain time, loading of samples need to be done in a separate thread
- */
-static void* loadSampleThread(void* p)
- {
- SS_TRACE_IN
- pthread_mutex_lock(&SS_LoaderMutex);
-
- // Crit section:
- SS_State prevState = synth_state;
- SWITCH_SYNTH_STATE(SS_LOADING_SAMPLE);
- SS_SampleLoader* loader = (SS_SampleLoader*) p;
- SS_Channel* ch = loader->channel;
- int ch_no = loader->ch_no;
-
- if (ch->sample) {
- delete[] ch->sample->data;
- delete ch->sample;
- }
- ch->sample = new SS_Sample;
- SS_Sample* smp = ch->sample;
-
- SNDFILE* sf;
- const char* filename = loader->filename.c_str();
- SF_INFO sfi;
-
- if (SS_DEBUG)
- printf("loadSampleThread: filename = %s\n", filename);
-
- sf = sf_open(filename, SFM_READ, &sfi);
- if (sf == 0) {
- fprintf(stderr,"Error opening file: %s\n", filename);
- SWITCH_SYNTH_STATE(prevState);
- simplesynth_ptr->guiSendSampleLoaded(false, loader->ch_no, filename);
- delete ch->sample; ch->sample = 0;
- delete loader;
- pthread_mutex_unlock(&SS_LoaderMutex);
- SS_TRACE_OUT
- pthread_exit(0);
- }
-
- //Print some info:
- if (SS_DEBUG) {
- printf("Sample info:\n");
- printf("Frames: \t%ld\n", (long) sfi.frames);
- printf("Channels: \t%d\n", sfi.channels);
- printf("Samplerate: \t%d\n", sfi.samplerate);
- }
-
- //
- // Allocate and read the thingie
- //
-
- // If current samplerate is the same as MusE's:
- if (SS_samplerate == sfi.samplerate) {
- smp->data = new float[sfi.channels * sfi.frames];
- sf_count_t n = sf_readf_float(sf, smp->data, sfi.frames);
- smp->frames = sfi.frames;
- smp->samples = (n * sfi.channels);
- smp->channels = sfi.channels;
- if (SS_DEBUG) {
- printf("%ld frames read\n", (long) n);
- }
- }
- else // otherwise, resample:
- {
- smp->channels = sfi.channels;
- // Get new nr of frames:
- double srcratio = (double) SS_samplerate/ (double) sfi.samplerate;
- smp->frames = (long) floor(((double) sfi.frames * srcratio));
- smp->frames = (sfi.channels == 1 ? smp->frames * 2 : smp->frames ); // Double nr of new frames if mono->stereo
- smp->samples = smp->frames * smp->channels;
-
- if (SS_DEBUG) {
- printf("Resampling from %ld frames to %ld frames - srcration: %lf\n", (long) sfi.frames, smp->frames, srcratio);
- printf("Nr of new samples: %ld\n", smp->samples);
- }
-
- // Read to temporary:
- float temp[sfi.frames * sfi.channels];
- int frames_read = sf_readf_float(sf, temp, sfi.frames);
- if (frames_read != sfi.frames) {
- fprintf(stderr,"Error reading sample %s\n", filename);
- simplesynth_ptr->guiSendSampleLoaded(false, loader->ch_no, filename);
- sf_close(sf);
- SWITCH_SYNTH_STATE(prevState);
- delete ch->sample; ch->sample = 0;
- delete loader;
- pthread_mutex_unlock(&SS_LoaderMutex);
- pthread_exit(0);
- SS_TRACE_OUT
- }
-
- // Allocate mem for the new one
- smp->data = new float[smp->frames * smp->channels];
- memset(smp->data, 0, sizeof(float)* smp->frames * smp->channels);
-
- // libsamplerate & co (secret rabbits in the code!)
- SRC_DATA srcdata;
- srcdata.data_in = temp;
- srcdata.data_out = smp->data;
- srcdata.input_frames = sfi.frames;
- srcdata.output_frames = smp->frames;
- srcdata.src_ratio = (double) SS_samplerate / (double) sfi.samplerate;
-
- if (SS_DEBUG) {
- printf("Converting sample....\n");
- }
-
- if (src_simple(&srcdata, SRC_SINC_BEST_QUALITY, sfi.channels)) {
- SS_ERROR("Error when resampling, ignoring current sample");
- //TODO: deallocate and stuff
- }
- else if (SS_DEBUG) {
- printf("Sample converted. %ld input frames used, %ld output frames generated\n",
- srcdata.input_frames_used,
- srcdata.output_frames_gen);
- }
- }
- //Just close the dam thing
- sf_close(sf);
- SWITCH_SYNTH_STATE(prevState);
- ch->sample->filename = loader->filename;
- simplesynth_ptr->guiSendSampleLoaded(true, ch_no, filename);
- delete loader;
- pthread_mutex_unlock(&SS_LoaderMutex);
- SS_TRACE_OUT
- pthread_exit(0);
- }
-
-QString *projPathPtr;
-
-static Mess* instantiate(int sr, QWidget*, QString* projectPathPtr, const char* name)
- {
- projPathPtr = projectPathPtr;
- printf("SimpleSynth sampleRate %d\n", sr);
- SimpleSynth* synth = new SimpleSynth(sr);
- if (!synth->init(name)) {
- delete synth;
- synth = 0;
- }
- return synth;
- }
-
-
-/*!
- \fn SimpleSynth::updateBalance(int pan)
- */
-void SimpleSynth::updateBalance(int ch, int val)
- {
- SS_TRACE_IN
- channels[ch].pan = val;
-
- // Balance:
- channels[ch].balanceFactorL = 1.0;
- channels[ch].balanceFactorR = 1.0;
- double offset = 0;
- int dev = val - 64;
- offset = (double) dev / 64.0;
- if (offset < 0) {
- channels[ch].balanceFactorR = 1.0 + offset;
- }
- else {
- channels[ch].balanceFactorL = 1.0 - offset;
- }
-
- if (SS_DEBUG_MIDI)
- printf("balanceFactorL %f balanceFactorR %f\n", channels[ch].balanceFactorL, channels[ch].balanceFactorR);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::updateVolume(int invol_ctrlval)
- */
-void SimpleSynth::updateVolume(int ch, int invol_ctrlval)
- {
- SS_TRACE_IN
- channels[ch].volume = (double)invol_ctrlval/ (double) SS_CHANNEL_VOLUME_QUOT;
- channels[ch].volume_ctrlval = invol_ctrlval;
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiUpdateBalance(int ch, int bal)
- */
-void SimpleSynth::guiUpdateBalance(int ch, int bal)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, ch, ME_CONTROLLER, SS_CHANNEL_PAN_CONTROLLER(ch), bal);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiUpdateVolume(int ch, int val)
- */
-void SimpleSynth::guiUpdateVolume(int ch, int val)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_VOLUME_CONTROLLER(ch), val);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiUpdateNoff(bool b)
- */
-void SimpleSynth::guiUpdateNoff(int ch, bool b)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_NOFF_CONTROLLER(ch), b);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiUpdateChoff(int ch, bool b)
- */
-void SimpleSynth::guiUpdateChoff(int ch, bool b)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_ONOFF_CONTROLLER(ch), b);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiUpdateMasterVol(int val)
- */
-void SimpleSynth::guiUpdateMasterVol(int val)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_MASTER_CTRL_VOLUME, val);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-/*!
- \fn SimpleSynth::guiUpdateSendFxLevel(int fxid, int level)
- */
-void SimpleSynth::guiUpdateSendFxLevel(int channel, int fxid, int level)
- {
- SS_TRACE_IN
- MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_SENDFX_CONTROLLER(channel, fxid), level);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiSendSampleLoaded(int ch, const char* filename)
- */
-void SimpleSynth::guiSendSampleLoaded(bool success, int ch, const char* filename)
- {
- SS_TRACE_IN
- int len = strlen(filename) + 3; //2 + filenamelen + 1;
- byte out[len];
-
- if (success) {
- out[0] = SS_SYSEX_LOAD_SAMPLE_OK;
- }
- else {
- out[0] = SS_SYSEX_LOAD_SAMPLE_ERROR;
- }
- out[1] = ch;
- memcpy(out+2, filename, strlen(filename)+1);
- MidiPlayEvent ev(0, 0, ME_SYSEX, out, len);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiSendError(const char* errorstring)
- */
-void SimpleSynth::guiSendError(const char* errorstring)
- {
- SS_TRACE_IN
- byte out[strlen(errorstring)+2];
- out[0] = SS_SYSEX_ERRORMSG;
- memcpy(out+1, errorstring, strlen(errorstring) +1);
- SS_TRACE_OUT
- }
-
-extern "C"
- {
- static MESS descriptor = {
- "SimpleSynth",
- "SimpleSynth drums by Mathias Lundgren", // (lunar_shuttle@users.sf.net)
- "0.1", //Version string
- MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
- instantiate,
- };
- // We must compile with -fvisibility=hidden to avoid namespace
- // conflicts with global variables.
- // Only visible symbol is "mess_descriptor".
- // (TODO: all plugins should be compiled this way)
-
- __attribute__ ((visibility("default")))
- const MESS* mess_descriptor() { return &descriptor; }
- }
-
-
-/*!
- \fn SimpleSynth::initSendEffect(int sendeffectid, QString lib, QString name)
- */
-bool SimpleSynth::initSendEffect(int id, QString lib, QString name)
- {
- SS_TRACE_IN
- bool success = false;
- if (sendEffects[id].plugin) {
- //Cleanup if one was already there:
- cleanupPlugin(id);
- }
- sendEffects[id].plugin = (LadspaPlugin*) plugins.find(lib, name);
- LadspaPlugin* plugin = sendEffects[id].plugin;
- if (plugin) { //We found one
-
- sendEffects[id].inputs = plugin->inports();
- sendEffects[id].outputs = plugin->outports();
-
- if (plugin->instantiate()) {
- SS_DBG2("Plugin instantiated", name.toLatin1());
- SS_DBG_I("Parameters", plugin->parameter());
- SS_DBG_I("No of inputs", plugin->inports());
- SS_DBG_I("No of outputs",plugin->outports());
- SS_DBG_I("Inplace-capable", plugin->inPlaceCapable());
-
- // Connect inputs/outputs:
- // If single output/input, only use first channel in sendFxLineOut/sendFxReturn
- SS_DBG("Connecting ports...");
- plugin->connectInport(0, sendFxLineOut[id][0]);
- if (plugin->inports() == 2)
- plugin->connectInport(1, sendFxLineOut[id][1]);
- else if (plugin->inports() > 2) {
- fprintf(stderr, "Plugin has more than 2 inputs, not supported\n");
- }
-
- plugin->connectOutport(0, sendFxReturn[id][0]);
- if (plugin->outports() == 2)
- plugin->connectOutport(1, sendFxReturn[id][1]);
- else if (plugin->outports() > 2) {
- fprintf(stderr, "Plugin has more than 2 outputs, not supported\n");
- }
- SS_DBG("Ports connected");
- if (plugin->start()) {
- sendEffects[id].state = SS_SENDFX_ON;
- success = true;
-
- int n = plugin->parameter();
- sendEffects[id].nrofparameters = n;
-
- // This is not nice, but freeverb doesn't want to play until some values are set:
- if (name == "freeverb3") {
- setFxParameter(id, 2, 0.5);
- setFxParameter(id, 3, 0.5);
- setFxParameter(id, 4, 0.5);
- guiUpdateFxParameter(id, 2, 0.5);
- guiUpdateFxParameter(id, 3, 0.5);
- guiUpdateFxParameter(id, 4, 0.5);
- }
- }
- //TODO: cleanup if failed
- }
- }
- //Notify gui
- int len = 3;
- byte out[len];
- out[0] = SS_SYSEX_LOAD_SENDEFFECT_OK;
- out[1] = id;
- int j=0;
- for (iPlugin i = plugins.begin(); i!=plugins.end(); i++, j++) {
- if ((*i)->lib() == plugin->lib() && (*i)->label() == plugin->label()) {
- out[2] = j;
- MidiPlayEvent ev(0, 0, ME_SYSEX, out, len);
- gui->writeEvent(ev);
- }
- }
-
- if (!success) {
- QString errorString = "Error loading plugin \"" + plugin->label() + "\"";
- guiSendError(errorString);
- }
- return success;
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::setSendFxLevel(int channel, int effectid, double val)
- */
-void SimpleSynth::setSendFxLevel(int channel, int effectid, double val)
- {
- SS_TRACE_IN
- channels[channel].sendfxlevel[effectid] = val;
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::cleanupPlugin(int id)
- */
-void SimpleSynth::cleanupPlugin(int id)
- {
- SS_TRACE_IN
- LadspaPlugin* plugin = sendEffects[id].plugin;
- plugin->stop();
- SS_DBG2("Stopped fx", plugin->label().toLatin1());
- sendEffects[id].nrofparameters = 0;
- sendEffects[id].state = SS_SENDFX_OFF;
- sendEffects[id].plugin = 0;
-
- byte d[2];
- d[0] = SS_SYSEX_CLEAR_SENDEFFECT_OK;
- d[1] = id;
- MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::setFxParameter(int fxid, int param, float val)
- \brief Set fx-parameter on plugin and notify gui
- */
-void SimpleSynth::setFxParameter(int fxid, int param, float val)
- {
- SS_TRACE_IN
- LadspaPlugin* plugin = sendEffects[fxid].plugin;
- if (SS_DEBUG_LADSPA) {
- printf("Setting fx parameter: %f\n", val);
- }
- plugin->setParam(param, val);
- //sendEffects[fxid].parameter[param] = val;
- //guiUpdateFxParameter(fxid, param, val);
- SS_TRACE_OUT
- }
-
-
-
-/*!
- \fn SimpleSynth::guiUpdateFxParameter(int fxid, int param, float val)
- \brief Notify gui of changed fx-parameter
- */
-void SimpleSynth::guiUpdateFxParameter(int fxid, int param, float val)
- {
- SS_TRACE_IN
- LadspaPlugin* plugin = sendEffects[fxid].plugin;
- float min, max;
- plugin->range(param, &min, &max);
- //offset:
- val-= min;
-
- int intval = plugin->getGuiControlValue(param);
- /*if (plugin->isLog(param)) {
- intval = SS_map_logdomain2pluginparam(logf(val/(max - min) + min));
- }
- else if (plugin->isBool(param)) {
- intval = (int) val;
- }
- else {
- float scale = SS_PLUGIN_PARAM_MAX / (max - min);
- intval = (int) ((val - min) * scale);
- }*/
- if (SS_DEBUG_MIDI) {
- printf("Updating gui, fx parameter. fxid=%d, param=%d val=%d\n", fxid, param, intval);
- }
-
- byte d[4];
- d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER_OK;
- d[1] = fxid;
- d[2] = param;
- d[3] = intval;
- MidiPlayEvent ev(0, 0, ME_SYSEX, d, 4);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }
-
-
-
-
-/*!
- \fn SimpleSynth::clearSample(int ch)
- \brief Clears a sample (actually clears a channel)
- */
-void SimpleSynth::clearSample(int ch)
- {
- SS_TRACE_IN
- if (channels[ch].sample) {
- if (SS_DEBUG)
- printf("Clearing sample on channel %d\n", ch);
- SS_State prevstate = synth_state;
- SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
- SWITCH_SYNTH_STATE(SS_CLEARING_SAMPLE);
- if (channels[ch].sample->data) {
- delete[] channels[ch].sample->data;
- channels[ch].sample->data = 0;
- }
- if (channels[ch].sample) {
- delete channels[ch].sample;
- channels[ch].sample = 0;
- }
- SWITCH_SYNTH_STATE(prevstate);
- guiNotifySampleCleared(ch);
- if (SS_DEBUG) {
- printf("Clear sample - sample cleared on channel %d\n", ch);
- }
- }
- SS_TRACE_OUT
- }
-
-
-/*!
- \fn SimpleSynth::guiNotifySampleCleared(int ch)
- */
-void SimpleSynth::guiNotifySampleCleared(int ch)
- {
- SS_TRACE_IN
- byte d[2];
- d[0] = SS_SYSEX_CLEAR_SAMPLE_OK;
- d[1] = (byte) ch;
- MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2);
- gui->writeEvent(ev);
- SS_TRACE_OUT
- }