Merge remote-tracking branch 'origin/stable-0.4' into sfxr
@@ -1744,8 +1744,7 @@ p->putValue( jt->pos, value, false );
|
||||
{
|
||||
continue;
|
||||
}
|
||||
trackContentObject * tco =
|
||||
bb_tracks[it->pattern]->createTCO( midiTime() );
|
||||
trackContentObject * tco = bb_tracks[it->pattern]->createTCO( MidiTime() );
|
||||
tco->movePosition( it->position );
|
||||
if( it->length != DefaultTicksPerTact )
|
||||
{
|
||||
|
||||
@@ -108,18 +108,26 @@ public:
|
||||
finalise_modules();
|
||||
}
|
||||
|
||||
} g_oStartupShutdownHandler;
|
||||
} ;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
const LADSPA_Descriptor *
|
||||
ladspa_descriptor(unsigned long Index) {
|
||||
|
||||
static StartupShutdownHandler handler;
|
||||
|
||||
if (Index < g_lPluginCount)
|
||||
return g_ppsRegisteredDescriptors[Index];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -29,8 +29,14 @@ FOREACH(_item ${PLUGIN_SOURCES})
|
||||
ENDFOREACH(_item ${PLUGIN_SOURCES})
|
||||
|
||||
|
||||
IF(LMMS_BUILD_WIN32)
|
||||
SET(PIC_FLAGS "")
|
||||
ELSE(LMMS_BUILD_WIN32)
|
||||
SET(PIC_FLAGS "-fPIC")
|
||||
ENDIF(LMMS_BUILD_WIN32)
|
||||
|
||||
ADD_LIBRARY(iir STATIC util/iir.c)
|
||||
SET_TARGET_PROPERTIES(iir PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(iir PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(bandpass_a_iir_1893 iir)
|
||||
TARGET_LINK_LIBRARIES(bandpass_iir_1892 iir)
|
||||
TARGET_LINK_LIBRARIES(butterworth_1902 iir)
|
||||
@@ -40,21 +46,21 @@ TARGET_LINK_LIBRARIES(notch_iir_1894 iir)
|
||||
|
||||
FILE(GLOB GSM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gsm/*.c)
|
||||
ADD_LIBRARY(gsm STATIC ${GSM_SOURCES})
|
||||
SET_TARGET_PROPERTIES(gsm PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(gsm PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(gsm_1215 gsm)
|
||||
|
||||
ADD_LIBRARY(gverb STATIC gverb/gverb.c gverb/gverbdsp.c)
|
||||
SET_TARGET_PROPERTIES(gverb PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(gverb PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(gverb_1216 gverb)
|
||||
|
||||
ADD_LIBRARY(blo STATIC util/blo.c)
|
||||
SET_TARGET_PROPERTIES(blo PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(blo PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(hermes_filter_1200 blo)
|
||||
|
||||
ADD_LIBRARY(rms STATIC util/rms.c)
|
||||
ADD_LIBRARY(db STATIC util/db.c)
|
||||
SET_TARGET_PROPERTIES(rms PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(db PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(rms PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
SET_TARGET_PROPERTIES(db PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(sc1_1425 rms db)
|
||||
TARGET_LINK_LIBRARIES(sc2_1426 rms db)
|
||||
TARGET_LINK_LIBRARIES(sc3_1427 rms db)
|
||||
@@ -63,6 +69,6 @@ TARGET_LINK_LIBRARIES(sc4m_1916 rms db)
|
||||
TARGET_LINK_LIBRARIES(se4_1883 rms db)
|
||||
|
||||
ADD_LIBRARY(pitchscale STATIC util/pitchscale.c)
|
||||
SET_TARGET_PROPERTIES(pitchscale PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
SET_TARGET_PROPERTIES(pitchscale PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(pitch_scale_1193 pitchscale)
|
||||
TARGET_LINK_LIBRARIES(pitch_scale_1194 pitchscale)
|
||||
|
||||
@@ -48,7 +48,9 @@ blo_h_tables *blo_h_tables_new(int table_size)
|
||||
unsigned int h;
|
||||
size_t all_tables_size = sizeof(float) * (table_size + BLO_TABLE_WR)
|
||||
* (BLO_N_HARMONICS - 1) * 2;
|
||||
#ifndef WIN32
|
||||
int shm_fd;
|
||||
#endif
|
||||
char shm_path[128];
|
||||
|
||||
this = malloc(sizeof(blo_h_tables));
|
||||
|
||||
456
plugins/ladspa_effect/swh/vocoder_1337.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* vocoder.c
|
||||
Version 0.3
|
||||
|
||||
LADSPA Unique ID: 1337
|
||||
|
||||
Version 0.31
|
||||
Added stereo output, renamed input/output ports, added,
|
||||
added a control for stereo balance
|
||||
|
||||
Version 0.3
|
||||
Added support for changing bands in real time 2003-12-09
|
||||
|
||||
Version 0.2
|
||||
Adapted to LADSPA by Josh Green <jgreen@users.sourceforge.net>
|
||||
15.6.2001 (for the LinuxTag 2001!)
|
||||
|
||||
Original program can be found at:
|
||||
http://www.sirlab.de/linux/
|
||||
Author: Achim Settelmeier <settel-linux@sirlab.de>
|
||||
|
||||
Adapted to LMMS by Hexasoft (hexasoft.corp@free.fr)
|
||||
|
||||
|
||||
Licence: GPL
|
||||
This program 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.
|
||||
|
||||
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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* not familiar with WINDOWS stuff. Saw this in other sources, it should be needed */
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WINDOWS_DLL_EXPORT_ __declspec(dllexport)
|
||||
int bIsFirstTime = 1;
|
||||
void _init(); // forward declaration
|
||||
#else
|
||||
#define _WINDOWS_DLL_EXPORT_
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* general includes */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LADSPA headers */
|
||||
#include <ladspa.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#define LADSPA_UNIQUE_ID 1337
|
||||
|
||||
#define MAX_BANDS 16 /* max 16 bandsn should be increased */
|
||||
#define AMPLIFIER 16.0
|
||||
|
||||
struct bandpass
|
||||
{
|
||||
LADSPA_Data c, f, att;
|
||||
|
||||
LADSPA_Data freq;
|
||||
LADSPA_Data low1, low2;
|
||||
LADSPA_Data mid1, mid2;
|
||||
LADSPA_Data high1, high2;
|
||||
LADSPA_Data y;
|
||||
};
|
||||
|
||||
struct bands_out{
|
||||
LADSPA_Data decay;
|
||||
LADSPA_Data oldval;
|
||||
LADSPA_Data level; /* 0.0 - 1.0 level of this output band */
|
||||
};
|
||||
|
||||
const LADSPA_Data decay_table[] =
|
||||
{
|
||||
1/100.0,
|
||||
1/100.0, 1/100.0, 1/100.0,
|
||||
1/125.0, 1/125.0, 1/125.0,
|
||||
1/166.0, 1/166.0, 1/166.0,
|
||||
1/200.0, 1/200.0, 1/200.0,
|
||||
1/250.0, 1/250.0, 1/250.0
|
||||
};
|
||||
|
||||
/* The port numbers for the plugin: */
|
||||
|
||||
#define PORT_FORMANT 0 /* the track to "vocodify */
|
||||
#define PORT_CARRIER 1 /* the track to control 1st track */
|
||||
#define PORT_OUTPUT 2 /* left output */
|
||||
#define PORT_OUTPUT2 3 /* right output */
|
||||
#define CTRL_BANDCOUNT 4 /* selected # of bands to use */
|
||||
#define CTRL_PAN 5 /* stereo balance for outputs */
|
||||
#define CTRL_BAND1LVL 6 /* start of bands level */
|
||||
|
||||
#define PORT_COUNT 6 + MAX_BANDS /* bands level */
|
||||
|
||||
|
||||
/* useful macros */
|
||||
#undef CLAMP
|
||||
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
|
||||
|
||||
/* Instance data for the vocoder plugin */
|
||||
typedef struct {
|
||||
LADSPA_Data SampleRate;
|
||||
|
||||
int num_bands; /* current number of bands */
|
||||
float mainvol; /* main volume */
|
||||
|
||||
struct bandpass bands_formant[MAX_BANDS]; /* one structure per band */
|
||||
struct bandpass bands_carrier[MAX_BANDS]; /* one structure per band */
|
||||
struct bands_out bands_out[MAX_BANDS]; /* one structure per band */
|
||||
|
||||
/* Ports */
|
||||
|
||||
LADSPA_Data * portFormant; /* Formant signal port data location */
|
||||
LADSPA_Data * portCarrier; /* Carrier signal port data location */
|
||||
LADSPA_Data * portOutput; /* Output audio port data location */
|
||||
LADSPA_Data * portOutput2; /* Output audio port data location (copy of previous one) */
|
||||
LADSPA_Data * ctrlPan; /* PAN for output */
|
||||
LADSPA_Data * ctrlBandCount; /* Band count control */
|
||||
LADSPA_Data * ctrlBandLevels[MAX_BANDS]; /* level controls for each band */
|
||||
|
||||
} VocoderInstance;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Construct a new plugin instance. */
|
||||
LADSPA_Handle
|
||||
instantiateVocoder(const LADSPA_Descriptor * Descriptor,
|
||||
unsigned long SampleRate) {
|
||||
VocoderInstance * vocoder;
|
||||
|
||||
vocoder = (VocoderInstance *)malloc(sizeof(VocoderInstance));
|
||||
|
||||
if (vocoder == NULL)
|
||||
return NULL;
|
||||
|
||||
vocoder->SampleRate = (LADSPA_Data)SampleRate;
|
||||
vocoder->num_bands = -1;
|
||||
|
||||
return vocoder;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Initialise and activate a plugin instance. */
|
||||
void
|
||||
activateVocoder(LADSPA_Handle Instance) {
|
||||
VocoderInstance *vocoder = (VocoderInstance *)Instance;
|
||||
int i;
|
||||
|
||||
vocoder->mainvol = 1.0 * AMPLIFIER;
|
||||
|
||||
for (i = 0; i < MAX_BANDS; i++)
|
||||
vocoder->bands_out[i].oldval = 0.0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Connect a port to a data location. */
|
||||
void
|
||||
connectPortToVocoder(LADSPA_Handle Instance,
|
||||
unsigned long Port,
|
||||
LADSPA_Data * DataLocation) {
|
||||
|
||||
VocoderInstance * vocoder;
|
||||
|
||||
vocoder = (VocoderInstance *)Instance;
|
||||
switch (Port) {
|
||||
case PORT_FORMANT: /* formant port? */
|
||||
vocoder->portFormant = DataLocation;
|
||||
break;
|
||||
case PORT_CARRIER: /* carrier port? */
|
||||
vocoder->portCarrier = DataLocation;
|
||||
break;
|
||||
case PORT_OUTPUT: /* output port? */
|
||||
vocoder->portOutput = DataLocation;
|
||||
break;
|
||||
case PORT_OUTPUT2: /* output port? */
|
||||
vocoder->portOutput2 = DataLocation;
|
||||
break;
|
||||
case CTRL_BANDCOUNT: /* band count control? */
|
||||
vocoder->ctrlBandCount = DataLocation;
|
||||
break;
|
||||
case CTRL_PAN: /* Pan control? */
|
||||
vocoder->ctrlPan = DataLocation;
|
||||
break;
|
||||
default: /* a band level control? */
|
||||
if (Port >= CTRL_BAND1LVL && Port < CTRL_BAND1LVL + MAX_BANDS)
|
||||
vocoder->ctrlBandLevels[Port - CTRL_BAND1LVL] = DataLocation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// vocoder_do_bandpasses /*fold00*/
|
||||
void vocoder_do_bandpasses(struct bandpass *bands, LADSPA_Data sample,
|
||||
VocoderInstance *vocoder)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < vocoder->num_bands; i++)
|
||||
{
|
||||
bands[i].high1 = sample - bands[i].f * bands[i].mid1 - bands[i].low1;
|
||||
bands[i].mid1 += bands[i].high1 * bands[i].c;
|
||||
bands[i].low1 += bands[i].mid1;
|
||||
|
||||
bands[i].high2 = bands[i].low1 - bands[i].f * bands[i].mid2
|
||||
- bands[i].low2;
|
||||
bands[i].mid2 += bands[i].high2 * bands[i].c;
|
||||
bands[i].low2 += bands[i].mid2;
|
||||
bands[i].y = bands[i].high2 * bands[i].att;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run a vocoder instance for a block of SampleCount samples. */
|
||||
void
|
||||
runVocoder(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount)
|
||||
{
|
||||
VocoderInstance *vocoder = (VocoderInstance *)Instance;
|
||||
int i, j, numbands, pan;
|
||||
float a;
|
||||
LADSPA_Data x, c;
|
||||
float fl, fr;
|
||||
|
||||
numbands = (int)(*vocoder->ctrlBandCount);
|
||||
if (numbands < 1 || numbands > MAX_BANDS) numbands = MAX_BANDS;
|
||||
|
||||
/* initialize bandpass information if num_bands control has changed,
|
||||
or on first run */
|
||||
if (vocoder->num_bands != numbands)
|
||||
{
|
||||
vocoder->num_bands = numbands;
|
||||
|
||||
for(i=0; i < numbands; i++)
|
||||
{
|
||||
memset(&vocoder->bands_formant[i], 0, sizeof(struct bandpass));
|
||||
|
||||
a = 16.0 * i/(double)numbands; // stretch existing bands
|
||||
|
||||
if (a < 4.0)
|
||||
vocoder->bands_formant[i].freq = 150 + 420 * a / 4.0;
|
||||
else
|
||||
vocoder->bands_formant[i].freq = 600 * pow (1.23, a - 4.0);
|
||||
|
||||
c = vocoder->bands_formant[i].freq * 2 * M_PI / vocoder->SampleRate;
|
||||
vocoder->bands_formant[i].c = c * c;
|
||||
|
||||
vocoder->bands_formant[i].f = 0.4/c;
|
||||
vocoder->bands_formant[i].att =
|
||||
1/(6.0 + ((exp (vocoder->bands_formant[i].freq
|
||||
/ vocoder->SampleRate) - 1) * 10));
|
||||
|
||||
memcpy(&vocoder->bands_carrier[i],
|
||||
&vocoder->bands_formant[i], sizeof(struct bandpass));
|
||||
|
||||
vocoder->bands_out[i].decay = decay_table[(int)a];
|
||||
vocoder->bands_out[i].level =
|
||||
CLAMP (*vocoder->ctrlBandLevels[i], 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
else /* get current values of band level controls */
|
||||
{
|
||||
for (i = 0; i < numbands; i++)
|
||||
vocoder->bands_out[i].level = CLAMP (*vocoder->ctrlBandLevels[i],
|
||||
0.0, 1.0);
|
||||
}
|
||||
|
||||
for (i=0; i < SampleCount; i++)
|
||||
{
|
||||
vocoder_do_bandpasses (vocoder->bands_carrier,
|
||||
vocoder->portCarrier[i], vocoder);
|
||||
vocoder_do_bandpasses (vocoder->bands_formant,
|
||||
vocoder->portFormant[i], vocoder);
|
||||
|
||||
vocoder->portOutput[i] = 0.0;
|
||||
vocoder->portOutput2[i] = 0.0;
|
||||
for (j=0; j < numbands; j++)
|
||||
{
|
||||
vocoder->bands_out[j].oldval = vocoder->bands_out[j].oldval
|
||||
+ (fabs (vocoder->bands_formant[j].y)
|
||||
- vocoder->bands_out[j].oldval)
|
||||
* vocoder->bands_out[j].decay;
|
||||
x = vocoder->bands_carrier[j].y * vocoder->bands_out[j].oldval;
|
||||
vocoder->portOutput[i] += x * vocoder->bands_out[j].level;
|
||||
vocoder->portOutput2[i] += x * vocoder->bands_out[j].level;
|
||||
}
|
||||
/* treat paning + main volume */
|
||||
pan = (int)(*vocoder->ctrlPan);
|
||||
fl = fr = 1.;
|
||||
if (pan != 0) { /* no paning, don't compute useless values */
|
||||
if (pan > 0) { /* reduce left */
|
||||
fl = (100.-pan)/100.;
|
||||
} else {
|
||||
fr = (100.+pan)/100.;
|
||||
}
|
||||
}
|
||||
/* apply volume and paning */
|
||||
vocoder->portOutput[i] *= vocoder->mainvol * fl;
|
||||
vocoder->portOutput2[i] *= vocoder->mainvol * fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Throw away a vocoder instance. */
|
||||
void
|
||||
cleanupVocoder(LADSPA_Handle Instance)
|
||||
{
|
||||
VocoderInstance * Vocoder;
|
||||
Vocoder = (VocoderInstance *)Instance;
|
||||
free(Vocoder);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
LADSPA_Descriptor * g_psDescriptor = NULL;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* _init() is called automatically when the plugin library is first
|
||||
loaded. */
|
||||
void
|
||||
_init() {
|
||||
char ** pcPortNames;
|
||||
LADSPA_PortDescriptor * piPortDescriptors;
|
||||
LADSPA_PortRangeHint * psPortRangeHints;
|
||||
int i;
|
||||
|
||||
g_psDescriptor = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
|
||||
|
||||
if (g_psDescriptor) {
|
||||
g_psDescriptor->UniqueID = LADSPA_UNIQUE_ID;
|
||||
g_psDescriptor->Label = strdup("vocoder-lmms");
|
||||
g_psDescriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
|
||||
g_psDescriptor->Name = strdup("Vocoder for LMMS");
|
||||
g_psDescriptor->Maker = strdup("Achim Settelmeier (adapted to LADSPA by Josh Green, adapted to LMMS by Hexasoft)");
|
||||
g_psDescriptor->Copyright = strdup("GPL");
|
||||
g_psDescriptor->PortCount = PORT_COUNT;
|
||||
piPortDescriptors = (LADSPA_PortDescriptor *)calloc(PORT_COUNT,
|
||||
sizeof(LADSPA_PortDescriptor));
|
||||
g_psDescriptor->PortDescriptors
|
||||
= (const LADSPA_PortDescriptor *)piPortDescriptors;
|
||||
piPortDescriptors[PORT_FORMANT]
|
||||
= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
|
||||
piPortDescriptors[PORT_CARRIER]
|
||||
= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
|
||||
piPortDescriptors[PORT_OUTPUT]
|
||||
= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
|
||||
piPortDescriptors[PORT_OUTPUT2]
|
||||
= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
|
||||
piPortDescriptors[CTRL_BANDCOUNT]
|
||||
= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
|
||||
piPortDescriptors[CTRL_PAN]
|
||||
= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
|
||||
|
||||
pcPortNames = (char **)calloc(PORT_COUNT, sizeof(char *));
|
||||
g_psDescriptor->PortNames = (const char **)pcPortNames;
|
||||
pcPortNames[PORT_FORMANT] = strdup("Formant-in");
|
||||
pcPortNames[PORT_CARRIER] = strdup("Carrier-in");
|
||||
pcPortNames[PORT_OUTPUT] = strdup("Output-out");
|
||||
pcPortNames[PORT_OUTPUT2] = strdup("Output2-out");
|
||||
pcPortNames[CTRL_BANDCOUNT] = strdup("Number of bands");
|
||||
pcPortNames[CTRL_PAN] = strdup("Left/Right");
|
||||
|
||||
psPortRangeHints = ((LADSPA_PortRangeHint *)
|
||||
calloc(PORT_COUNT, sizeof(LADSPA_PortRangeHint)));
|
||||
g_psDescriptor->PortRangeHints
|
||||
= (const LADSPA_PortRangeHint *)psPortRangeHints;
|
||||
psPortRangeHints[PORT_FORMANT].HintDescriptor = 0;
|
||||
psPortRangeHints[PORT_CARRIER].HintDescriptor = 0;
|
||||
psPortRangeHints[PORT_OUTPUT].HintDescriptor = 0;
|
||||
psPortRangeHints[PORT_OUTPUT2].HintDescriptor = 0;
|
||||
psPortRangeHints[CTRL_BANDCOUNT].HintDescriptor
|
||||
= LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE
|
||||
| LADSPA_HINT_INTEGER;
|
||||
psPortRangeHints[CTRL_BANDCOUNT].LowerBound = 1;
|
||||
psPortRangeHints[CTRL_BANDCOUNT].UpperBound = MAX_BANDS;
|
||||
psPortRangeHints[CTRL_PAN].HintDescriptor
|
||||
= LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE
|
||||
| LADSPA_HINT_INTEGER;
|
||||
psPortRangeHints[CTRL_PAN].LowerBound = -100;
|
||||
psPortRangeHints[CTRL_PAN].UpperBound = +100;
|
||||
|
||||
for (i=CTRL_BAND1LVL; i < CTRL_BAND1LVL + MAX_BANDS; i++)
|
||||
{
|
||||
piPortDescriptors[i] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
|
||||
pcPortNames[i] = malloc (sizeof ("Band 99 Level"));
|
||||
sprintf(pcPortNames[i], "Band %d Level", i - CTRL_BAND1LVL + 1);
|
||||
psPortRangeHints[i].HintDescriptor
|
||||
= LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
|
||||
psPortRangeHints[i].LowerBound = 0;
|
||||
psPortRangeHints[i].UpperBound = 1;
|
||||
}
|
||||
|
||||
g_psDescriptor->instantiate = instantiateVocoder;
|
||||
g_psDescriptor->connect_port = connectPortToVocoder;
|
||||
g_psDescriptor->activate = activateVocoder;
|
||||
g_psDescriptor->run = runVocoder;
|
||||
g_psDescriptor->run_adding = NULL;
|
||||
g_psDescriptor->set_run_adding_gain = NULL;
|
||||
g_psDescriptor->deactivate = NULL;
|
||||
g_psDescriptor->cleanup = cleanupVocoder;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* _fini() is called automatically when the library is unloaded. */
|
||||
void
|
||||
_fini() {
|
||||
long lIndex;
|
||||
if (g_psDescriptor) {
|
||||
free((char *)g_psDescriptor->Label);
|
||||
free((char *)g_psDescriptor->Name);
|
||||
free((char *)g_psDescriptor->Maker);
|
||||
free((char *)g_psDescriptor->Copyright);
|
||||
free((LADSPA_PortDescriptor *)g_psDescriptor->PortDescriptors);
|
||||
for (lIndex = 0; lIndex < g_psDescriptor->PortCount; lIndex++)
|
||||
free((char *)(g_psDescriptor->PortNames[lIndex]));
|
||||
free((char **)g_psDescriptor->PortNames);
|
||||
free((LADSPA_PortRangeHint *)g_psDescriptor->PortRangeHints);
|
||||
free(g_psDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Return a descriptor of the requested plugin type. Only one plugin
|
||||
type is available in this library. */
|
||||
const LADSPA_Descriptor *
|
||||
ladspa_descriptor(unsigned long Index) {
|
||||
if (Index == 0)
|
||||
return g_psDescriptor;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* EOF */
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "pattern.h"
|
||||
#include "Instrument.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MidiTime.h"
|
||||
#include "debug.h"
|
||||
#include "embed.h"
|
||||
#include "song.h"
|
||||
@@ -152,7 +153,7 @@ public:
|
||||
|
||||
AutomationTrack * at;
|
||||
AutomationPattern * ap;
|
||||
midiTime lastPos;
|
||||
MidiTime lastPos;
|
||||
|
||||
smfMidiCC & create( TrackContainer* tc )
|
||||
{
|
||||
@@ -172,11 +173,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
smfMidiCC & putValue( midiTime time, AutomatableModel * objModel, float value )
|
||||
smfMidiCC & putValue( MidiTime time, AutomatableModel * objModel, float value )
|
||||
{
|
||||
if( !ap || time > lastPos + DefaultTicksPerTact )
|
||||
{
|
||||
midiTime pPos = midiTime( time.getTact(), 0 );
|
||||
MidiTime pPos = MidiTime( time.getTact(), 0 );
|
||||
ap = dynamic_cast<AutomationPattern*>(
|
||||
at->createTCO(0) );
|
||||
ap->movePosition( pPos );
|
||||
@@ -186,7 +187,7 @@ public:
|
||||
lastPos = time;
|
||||
time = time - ap->startPosition();
|
||||
ap->putValue( time, value, false );
|
||||
ap->changeLength( midiTime( time.getTact() + 1, 0 ) );
|
||||
ap->changeLength( MidiTime( time.getTact() + 1, 0 ) );
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -212,7 +213,7 @@ public:
|
||||
Instrument * it_inst;
|
||||
bool isSF2;
|
||||
bool hasNotes;
|
||||
midiTime lastEnd;
|
||||
MidiTime lastEnd;
|
||||
|
||||
smfMidiChannel * create( TrackContainer* tc )
|
||||
{
|
||||
@@ -247,7 +248,7 @@ public:
|
||||
{
|
||||
if( !p || n.pos() > lastEnd + DefaultTicksPerTact )
|
||||
{
|
||||
midiTime pPos = midiTime(n.pos().getTact(), 0 );
|
||||
MidiTime pPos = MidiTime( n.pos().getTact(), 0 );
|
||||
p = dynamic_cast<pattern *>( it->createTCO( 0 ) );
|
||||
p->movePosition( pPos );
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "midi.h"
|
||||
#include "MidiEvent.h"
|
||||
#include "ImportFilter.h"
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ private:
|
||||
}
|
||||
|
||||
|
||||
typedef QVector<QPair<int, midiEvent> > eventVector;
|
||||
eventVector m_events;
|
||||
typedef QVector<QPair<int, MidiEvent> > EventVector;
|
||||
EventVector m_events;
|
||||
int m_timingDivision;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(OPL2 opl2instrument.cpp opl2instrument.h opl.h kemuopl.h adlibemu.c adlibemu.h fmopl.c fmopl.h temuopl.cpp temuopl.h MOCFILES opl2instrument.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png)
|
||||
BUILD_PLUGIN(OPL2 opl2instrument.cpp opl2instrument.h opl.h fmopl.c fmopl.h temuopl.cpp temuopl.h MOCFILES opl2instrument.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png)
|
||||
502
plugins/opl2/COPYING.LESSER
Normal file
@@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
@@ -1,608 +0,0 @@
|
||||
/*
|
||||
* ADLIBEMU.C
|
||||
* Copyright (C) 1998-2001 Ken Silverman
|
||||
* Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
This file is a digital Adlib emulator for OPL2 and possibly OPL3
|
||||
|
||||
Features that could be added in a future version:
|
||||
- Amplitude and Frequency Vibrato Bits (not hard, but a big speed hit)
|
||||
- Global Keyboard Split Number Bit (need to research this one some more)
|
||||
- 2nd Adlib chip for OPL3 (simply need to make my cell array bigger)
|
||||
- Advanced connection modes of OPL3 (Just need to add more "docell" cases)
|
||||
- L/R Stereo bits of OPL3 (Need adlibgetsample to return stereo)
|
||||
|
||||
Features that aren't worth supporting:
|
||||
- Anything related to adlib timers&interrupts (Sorry - I always used IRQ0)
|
||||
- Composite sine wave mode (CSM) (Supported only on ancient cards)
|
||||
|
||||
I'm not sure about a few things in my code:
|
||||
- Attack curve. What function is this anyway? I chose to use an order-3
|
||||
polynomial to approximate but this doesn't seem right.
|
||||
- Attack/Decay/Release constants - my constants may not be exact
|
||||
- What should ADJUSTSPEED be?
|
||||
- Haven't verified that Global Keyboard Split Number Bit works yet
|
||||
- Some of the drums don't always sound right. It's pretty hard to guess
|
||||
the exact waveform of drums when you look at random data which is
|
||||
slightly randomized due to digital ADC recording.
|
||||
- Adlib seems to have a lot more treble than my emulator does. I'm not
|
||||
sure if this is simply unfixable due to the sound blaster's different
|
||||
filtering on FM and digital playback or if it's a serious bug in my
|
||||
code.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(max) && !defined(__cplusplus)
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
#if !defined(min) && !defined(__cplusplus)
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define PI 3.141592653589793
|
||||
#define MAXCELLS 18
|
||||
#define WAVPREC 2048
|
||||
|
||||
static float AMPSCALE=(8192.0);
|
||||
#define FRQSCALE (49716/512.0)
|
||||
|
||||
//Constants for Ken's Awe32, on a PII-266 (Ken says: Use these for KSM's!)
|
||||
#define MODFACTOR 4.0 //How much of modulator cell goes into carrier
|
||||
#define MFBFACTOR 1.0 //How much feedback goes back into modulator
|
||||
#define ADJUSTSPEED 0.75 //0<=x<=1 Simulate finite rate of change of state
|
||||
|
||||
//Constants for Ken's Awe64G, on a P-133
|
||||
//#define MODFACTOR 4.25 //How much of modulator cell goes into carrier
|
||||
//#define MFBFACTOR 0.5 //How much feedback goes back into modulator
|
||||
//#define ADJUSTSPEED 0.85 //0<=x<=1 Simulate finite rate of change of state
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float val, t, tinc, vol, sustain, amp, mfb;
|
||||
float a0, a1, a2, a3, decaymul, releasemul;
|
||||
short *waveform;
|
||||
long wavemask;
|
||||
void (*cellfunc)(void *, float);
|
||||
unsigned char flags, dum0, dum1, dum2;
|
||||
} celltype;
|
||||
|
||||
static long numspeakers, bytespersample;
|
||||
static float recipsamp;
|
||||
static celltype cell[MAXCELLS];
|
||||
static signed short wavtable[WAVPREC*3];
|
||||
static float kslmul[4] = {0.0,0.5,0.25,1.0};
|
||||
static float frqmul[16] = {.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15}, nfrqmul[16];
|
||||
static unsigned char adlibreg[256], ksl[8][16];
|
||||
static unsigned char modulatorbase[9] = {0,1,2,8,9,10,16,17,18};
|
||||
static unsigned char odrumstat = 0;
|
||||
static unsigned char base2cell[22] = {0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8};
|
||||
|
||||
float lvol[9] = {1,1,1,1,1,1,1,1,1}; //Volume multiplier on left speaker
|
||||
float rvol[9] = {1,1,1,1,1,1,1,1,1}; //Volume multiplier on right speaker
|
||||
long lplc[9] = {0,0,0,0,0,0,0,0,0}; //Samples to delay on left speaker
|
||||
long rplc[9] = {0,0,0,0,0,0,0,0,0}; //Samples to delay on right speaker
|
||||
|
||||
long nlvol[9], nrvol[9];
|
||||
long nlplc[9], nrplc[9];
|
||||
long rend = 0;
|
||||
#define FIFOSIZ 256
|
||||
static float *rptr[9], *nrptr[9];
|
||||
static float rbuf[9][FIFOSIZ*2];
|
||||
static float snd[FIFOSIZ*2];
|
||||
|
||||
#ifndef USING_ASM
|
||||
#define _inline
|
||||
#endif
|
||||
|
||||
#ifdef USING_ASM
|
||||
static _inline void ftol (float f, long *a)
|
||||
{
|
||||
_asm
|
||||
{
|
||||
mov eax, a
|
||||
fld f
|
||||
fistp dword ptr [eax]
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void ftol(float f, long *a) {
|
||||
*a=f;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ctc ((celltype *)c) //A rare attempt to make code easier to read!
|
||||
void docell4 (void *c, float modulator) { }
|
||||
void docell3 (void *c, float modulator)
|
||||
{
|
||||
long i;
|
||||
|
||||
ftol(ctc->t+modulator,&i);
|
||||
ctc->t += ctc->tinc;
|
||||
ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
|
||||
}
|
||||
void docell2 (void *c, float modulator)
|
||||
{
|
||||
long i;
|
||||
|
||||
ftol(ctc->t+modulator,&i);
|
||||
|
||||
void *amp_void = &ctc->amp;
|
||||
long *amp_long = (long *)amp_void;
|
||||
if (*amp_long <= 0x37800000)
|
||||
{
|
||||
ctc->amp = 0;
|
||||
ctc->cellfunc = docell4;
|
||||
}
|
||||
ctc->amp *= ctc->releasemul;
|
||||
|
||||
ctc->t += ctc->tinc;
|
||||
ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
|
||||
}
|
||||
void docell1 (void *c, float modulator)
|
||||
{
|
||||
long i;
|
||||
|
||||
ftol(ctc->t+modulator,&i);
|
||||
|
||||
void *amp_void = &ctc->amp;
|
||||
long *amp_long = (long *)amp_void;
|
||||
void *sustain_void = &ctc->sustain;
|
||||
long *sustain_long = (long *)sustain_void;
|
||||
if (*amp_long <= *sustain_long)
|
||||
{
|
||||
if (ctc->flags&32)
|
||||
{
|
||||
ctc->amp = ctc->sustain;
|
||||
ctc->cellfunc = docell3;
|
||||
}
|
||||
else
|
||||
ctc->cellfunc = docell2;
|
||||
}
|
||||
else
|
||||
ctc->amp *= ctc->decaymul;
|
||||
|
||||
ctc->t += ctc->tinc;
|
||||
ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
|
||||
}
|
||||
void docell0 (void *c, float modulator)
|
||||
{
|
||||
long i;
|
||||
|
||||
ftol(ctc->t+modulator,&i);
|
||||
|
||||
ctc->amp = ((ctc->a3*ctc->amp + ctc->a2)*ctc->amp + ctc->a1)*ctc->amp + ctc->a0;
|
||||
void *amp_void = &ctc->amp;
|
||||
long *amp_long = (long *)amp_void;
|
||||
if (*amp_long > 0x3f800000)
|
||||
{
|
||||
ctc->amp = 1;
|
||||
ctc->cellfunc = docell1;
|
||||
}
|
||||
|
||||
ctc->t += ctc->tinc;
|
||||
ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
|
||||
}
|
||||
|
||||
|
||||
static long waveform[8] = {WAVPREC,WAVPREC>>1,WAVPREC,(WAVPREC*3)>>2,0,0,(WAVPREC*5)>>2,WAVPREC<<1};
|
||||
static long wavemask[8] = {WAVPREC-1,WAVPREC-1,(WAVPREC>>1)-1,(WAVPREC>>1)-1,WAVPREC-1,((WAVPREC*3)>>2)-1,WAVPREC>>1,WAVPREC-1};
|
||||
static long wavestart[8] = {0,WAVPREC>>1,0,WAVPREC>>2,0,0,0,WAVPREC>>3};
|
||||
static float attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744};
|
||||
static float decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608};
|
||||
void cellon (long i, long j, celltype *c, unsigned char iscarrier)
|
||||
{
|
||||
long frn, oct, toff;
|
||||
float f;
|
||||
|
||||
frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
|
||||
oct = ((((long)adlibreg[i+0xb0])>>2)&7);
|
||||
toff = (oct<<1) + ((frn>>9)&((frn>>8)|(((adlibreg[8]>>6)&1)^1)));
|
||||
if (!(adlibreg[j+0x20]&16)) toff >>= 2;
|
||||
|
||||
f = pow(2.0,(adlibreg[j+0x60]>>4)+(toff>>2)-1)*attackconst[toff&3]*recipsamp;
|
||||
c->a0 = .0377*f; c->a1 = 10.73*f+1; c->a2 = -17.57*f; c->a3 = 7.42*f;
|
||||
f = -7.4493*decrelconst[toff&3]*recipsamp;
|
||||
c->decaymul = pow(2.0,f*pow(2.0,(adlibreg[j+0x60]&15)+(toff>>2)));
|
||||
c->releasemul = pow(2.0,f*pow(2.0,(adlibreg[j+0x80]&15)+(toff>>2)));
|
||||
c->wavemask = wavemask[adlibreg[j+0xe0]&7];
|
||||
c->waveform = &wavtable[waveform[adlibreg[j+0xe0]&7]];
|
||||
if (!(adlibreg[1]&0x20)) c->waveform = &wavtable[WAVPREC];
|
||||
c->t = wavestart[adlibreg[j+0xe0]&7];
|
||||
c->flags = adlibreg[j+0x20];
|
||||
c->cellfunc = docell0;
|
||||
c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15];
|
||||
c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) +
|
||||
(float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14);
|
||||
c->sustain = pow(2.0,(float)(adlibreg[j+0x80]>>4) * -.5);
|
||||
if (!iscarrier) c->amp = 0;
|
||||
c->mfb = pow(2.0,((adlibreg[i+0xc0]>>1)&7)+5)*(WAVPREC/2048.0)*MFBFACTOR;
|
||||
if (!(adlibreg[i+0xc0]&14)) c->mfb = 0;
|
||||
c->val = 0;
|
||||
}
|
||||
|
||||
//This function (and bug fix) written by Chris Moeller
|
||||
void cellfreq (signed long i, signed long j, celltype *c)
|
||||
{
|
||||
long frn, oct;
|
||||
|
||||
frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
|
||||
oct = ((((long)adlibreg[i+0xb0])>>2)&7);
|
||||
|
||||
c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15];
|
||||
c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) +
|
||||
(float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14);
|
||||
}
|
||||
|
||||
static long initfirstime = 0;
|
||||
void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample)
|
||||
{
|
||||
long i, j, frn, oct;
|
||||
|
||||
memset((void *)adlibreg,0,sizeof(adlibreg));
|
||||
memset((void *)cell,0,sizeof(celltype)*MAXCELLS);
|
||||
memset((void *)rbuf,0,sizeof(rbuf));
|
||||
rend = 0; odrumstat = 0;
|
||||
|
||||
for(i=0;i<MAXCELLS;i++)
|
||||
{
|
||||
cell[i].cellfunc = docell4;
|
||||
cell[i].amp = 0;
|
||||
cell[i].vol = 0;
|
||||
cell[i].t = 0;
|
||||
cell[i].tinc = 0;
|
||||
cell[i].wavemask = 0;
|
||||
cell[i].waveform = &wavtable[WAVPREC];
|
||||
}
|
||||
|
||||
numspeakers = danumspeakers;
|
||||
bytespersample = dabytespersample;
|
||||
|
||||
recipsamp = 1.0 / (float)dasamplerate;
|
||||
for(i=15;i>=0;i--) nfrqmul[i] = frqmul[i]*recipsamp*FRQSCALE*(WAVPREC/2048.0);
|
||||
|
||||
if (!initfirstime)
|
||||
{
|
||||
initfirstime = 1;
|
||||
|
||||
for(i=0;i<(WAVPREC>>1);i++)
|
||||
{
|
||||
wavtable[i] =
|
||||
wavtable[(i<<1) +WAVPREC] = (signed short)(16384*sin((float)((i<<1) )*PI*2/WAVPREC));
|
||||
wavtable[(i<<1)+1+WAVPREC] = (signed short)(16384*sin((float)((i<<1)+1)*PI*2/WAVPREC));
|
||||
}
|
||||
for(i=0;i<(WAVPREC>>3);i++)
|
||||
{
|
||||
wavtable[i+(WAVPREC<<1)] = wavtable[i+(WAVPREC>>3)]-16384;
|
||||
wavtable[i+((WAVPREC*17)>>3)] = wavtable[i+(WAVPREC>>2)]+16384;
|
||||
}
|
||||
|
||||
//[table in book]*8/3
|
||||
ksl[7][0] = 0; ksl[7][1] = 24; ksl[7][2] = 32; ksl[7][3] = 37;
|
||||
ksl[7][4] = 40; ksl[7][5] = 43; ksl[7][6] = 45; ksl[7][7] = 47;
|
||||
ksl[7][8] = 48; for(i=9;i<16;i++) ksl[7][i] = i+41;
|
||||
for(j=6;j>=0;j--)
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
oct = (long)ksl[j+1][i]-8; if (oct < 0) oct = 0;
|
||||
ksl[j][i] = (unsigned char)oct;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<9;i++)
|
||||
{
|
||||
frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
|
||||
oct = ((((long)adlibreg[i+0xb0])>>2)&7);
|
||||
cell[i].tinc = (float)(frn<<oct)*nfrqmul[adlibreg[modulatorbase[i]+0x20]&15];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adlib0 (long i, long v)
|
||||
{
|
||||
unsigned char tmp = adlibreg[i];
|
||||
adlibreg[i] = v;
|
||||
|
||||
if (i == 0xbd)
|
||||
{
|
||||
if ((v&16) > (odrumstat&16)) //BassDrum
|
||||
{
|
||||
cellon(6,16,&cell[6],0);
|
||||
cellon(6,19,&cell[15],1);
|
||||
cell[15].vol *= 2;
|
||||
}
|
||||
if ((v&8) > (odrumstat&8)) //Snare
|
||||
{
|
||||
cellon(16,20,&cell[16],0);
|
||||
cell[16].tinc *= 2*(nfrqmul[adlibreg[17+0x20]&15] / nfrqmul[adlibreg[20+0x20]&15]);
|
||||
if (((adlibreg[20+0xe0]&7) >= 3) && ((adlibreg[20+0xe0]&7) <= 5)) cell[16].vol = 0;
|
||||
cell[16].vol *= 2;
|
||||
}
|
||||
if ((v&4) > (odrumstat&4)) //TomTom
|
||||
{
|
||||
cellon(8,18,&cell[8],0);
|
||||
cell[8].vol *= 2;
|
||||
}
|
||||
if ((v&2) > (odrumstat&2)) //Cymbal
|
||||
{
|
||||
cellon(17,21,&cell[17],0);
|
||||
|
||||
cell[17].wavemask = wavemask[5];
|
||||
cell[17].waveform = &wavtable[waveform[5]];
|
||||
cell[17].tinc *= 16; cell[17].vol *= 2;
|
||||
|
||||
//cell[17].waveform = &wavtable[WAVPREC]; cell[17].wavemask = 0;
|
||||
//if (((adlibreg[21+0xe0]&7) == 0) || ((adlibreg[21+0xe0]&7) == 6))
|
||||
// cell[17].waveform = &wavtable[(WAVPREC*7)>>2];
|
||||
//if (((adlibreg[21+0xe0]&7) == 2) || ((adlibreg[21+0xe0]&7) == 3))
|
||||
// cell[17].waveform = &wavtable[(WAVPREC*5)>>2];
|
||||
}
|
||||
if ((v&1) > (odrumstat&1)) //Hihat
|
||||
{
|
||||
cellon(7,17,&cell[7],0);
|
||||
if (((adlibreg[17+0xe0]&7) == 1) || ((adlibreg[17+0xe0]&7) == 4) ||
|
||||
((adlibreg[17+0xe0]&7) == 5) || ((adlibreg[17+0xe0]&7) == 7)) cell[7].vol = 0;
|
||||
if ((adlibreg[17+0xe0]&7) == 6) { cell[7].wavemask = 0; cell[7].waveform = &wavtable[(WAVPREC*7)>>2]; }
|
||||
}
|
||||
|
||||
odrumstat = v;
|
||||
}
|
||||
else if (((unsigned)(i-0x40) < (unsigned)22) && ((i&7) < 6))
|
||||
{
|
||||
if ((i&7) < 3) // Modulator
|
||||
cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]]);
|
||||
else // Carrier
|
||||
cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]+9]);
|
||||
}
|
||||
else if ((unsigned)(i-0xa0) < (unsigned)9)
|
||||
{
|
||||
cellfreq(i-0xa0,modulatorbase[i-0xa0],&cell[i-0xa0]);
|
||||
cellfreq(i-0xa0,modulatorbase[i-0xa0]+3,&cell[i-0xa0+9]);
|
||||
}
|
||||
else if ((unsigned)(i-0xb0) < (unsigned)9)
|
||||
{
|
||||
if ((v&32) > (tmp&32))
|
||||
{
|
||||
cellon(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0],0);
|
||||
cellon(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9],1);
|
||||
}
|
||||
else if ((v&32) < (tmp&32))
|
||||
cell[i-0xb0].cellfunc = cell[i-0xb0+9].cellfunc = docell2;
|
||||
cellfreq(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0]);
|
||||
cellfreq(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9]);
|
||||
}
|
||||
|
||||
//outdata(i,v);
|
||||
}
|
||||
|
||||
#ifdef USING_ASM
|
||||
static long fpuasm;
|
||||
static float fakeadd = 8388608.0+128.0;
|
||||
static _inline void clipit8 (float f, long a)
|
||||
{
|
||||
_asm
|
||||
{
|
||||
mov edi, a
|
||||
fld dword ptr f
|
||||
fadd dword ptr fakeadd
|
||||
fstp dword ptr fpuasm
|
||||
mov eax, fpuasm
|
||||
test eax, 0x007fff00
|
||||
jz short skipit
|
||||
shr eax, 16
|
||||
xor eax, -1
|
||||
skipit: mov byte ptr [edi], al
|
||||
}
|
||||
}
|
||||
|
||||
static _inline void clipit16 (float f, long a)
|
||||
{
|
||||
_asm
|
||||
{
|
||||
mov eax, a
|
||||
fld dword ptr f
|
||||
fist word ptr [eax]
|
||||
cmp word ptr [eax], 0x8000
|
||||
jne short skipit2
|
||||
fst dword ptr [fpuasm]
|
||||
cmp fpuasm, 0x80000000
|
||||
sbb word ptr [eax], 0
|
||||
skipit2: fstp st
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void clipit8(float f,unsigned char *a) {
|
||||
f/=256.0;
|
||||
f+=128.0;
|
||||
if (f>254.5) *a=255;
|
||||
else if (f<0.5) *a=0;
|
||||
else *a=f;
|
||||
}
|
||||
|
||||
static void clipit16(float f,short *a) {
|
||||
if (f>32766.5) *a=32767;
|
||||
else if (f<-32767.5) *a=-32768;
|
||||
else *a=f;
|
||||
}
|
||||
#endif
|
||||
|
||||
void adlibsetvolume(int i) {
|
||||
AMPSCALE=i;
|
||||
}
|
||||
|
||||
void adlibgetsample (unsigned char *sndptr, long numbytes)
|
||||
{
|
||||
long i, j, k=0, ns, endsamples, rptrs, numsamples;
|
||||
celltype *cptr;
|
||||
float f;
|
||||
short *sndptr2=(short *)sndptr;
|
||||
|
||||
numsamples = (numbytes>>(numspeakers+bytespersample-2));
|
||||
|
||||
if (bytespersample == 1) f = AMPSCALE/256.0; else f = AMPSCALE;
|
||||
if (numspeakers == 1)
|
||||
{
|
||||
nlvol[0] = lvol[0]*f;
|
||||
for(i=0;i<9;i++) rptr[i] = &rbuf[0][0];
|
||||
rptrs = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rptrs = 0;
|
||||
for(i=0;i<9;i++)
|
||||
{
|
||||
if ((!i) || (lvol[i] != lvol[i-1]) || (rvol[i] != rvol[i-1]) ||
|
||||
(lplc[i] != lplc[i-1]) || (rplc[i] != rplc[i-1]))
|
||||
{
|
||||
nlvol[rptrs] = lvol[i]*f;
|
||||
nrvol[rptrs] = rvol[i]*f;
|
||||
nlplc[rptrs] = rend-min(max(lplc[i],0),FIFOSIZ);
|
||||
nrplc[rptrs] = rend-min(max(rplc[i],0),FIFOSIZ);
|
||||
rptrs++;
|
||||
}
|
||||
rptr[i] = &rbuf[rptrs-1][0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//CPU time used to be somewhat less when emulator was only mono!
|
||||
// Because of no delay fifos!
|
||||
|
||||
for(ns=0;ns<numsamples;ns+=endsamples)
|
||||
{
|
||||
endsamples = min(FIFOSIZ*2-rend,FIFOSIZ);
|
||||
endsamples = min(endsamples,numsamples-ns);
|
||||
|
||||
for(i=0;i<9;i++)
|
||||
nrptr[i] = &rptr[i][rend];
|
||||
for(i=0;i<rptrs;i++)
|
||||
memset((void *)&rbuf[i][rend],0,endsamples*sizeof(float));
|
||||
|
||||
if (adlibreg[0xbd]&0x20)
|
||||
{
|
||||
//BassDrum (j=6)
|
||||
if (cell[15].cellfunc != docell4)
|
||||
{
|
||||
if (adlibreg[0xc6]&1)
|
||||
{
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
(cell[15].cellfunc)((void *)&cell[15],0.0);
|
||||
nrptr[6][i] += cell[15].val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
(cell[6].cellfunc)((void *)&cell[6],cell[6].val*cell[6].mfb);
|
||||
(cell[15].cellfunc)((void *)&cell[15],cell[6].val*WAVPREC*MODFACTOR);
|
||||
nrptr[6][i] += cell[15].val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Snare/Hihat (j=7), Cymbal/TomTom (j=8)
|
||||
if ((cell[7].cellfunc != docell4) || (cell[8].cellfunc != docell4) || (cell[16].cellfunc != docell4) || (cell[17].cellfunc != docell4))
|
||||
{
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
k = k*1664525+1013904223;
|
||||
(cell[16].cellfunc)((void *)&cell[16],k&((WAVPREC>>1)-1)); //Snare
|
||||
(cell[7].cellfunc)((void *)&cell[7],k&(WAVPREC-1)); //Hihat
|
||||
(cell[17].cellfunc)((void *)&cell[17],k&((WAVPREC>>3)-1)); //Cymbal
|
||||
(cell[8].cellfunc)((void *)&cell[8],0.0); //TomTom
|
||||
nrptr[7][i] += cell[7].val + cell[16].val;
|
||||
nrptr[8][i] += cell[8].val + cell[17].val;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=9-1;j>=0;j--)
|
||||
{
|
||||
if ((adlibreg[0xbd]&0x20) && (j >= 6) && (j < 9)) continue;
|
||||
|
||||
cptr = &cell[j]; k = j;
|
||||
if (adlibreg[0xc0+k]&1)
|
||||
{
|
||||
if ((cptr[9].cellfunc == docell4) && (cptr->cellfunc == docell4)) continue;
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
(cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb);
|
||||
(cptr->cellfunc)((void *)&cptr[9],0);
|
||||
nrptr[j][i] += cptr[9].val + cptr->val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cptr[9].cellfunc == docell4) continue;
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
(cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb);
|
||||
(cptr[9].cellfunc)((void *)&cptr[9],cptr->val*WAVPREC*MODFACTOR);
|
||||
nrptr[j][i] += cptr[9].val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numspeakers == 1)
|
||||
{
|
||||
if (bytespersample == 1)
|
||||
{
|
||||
for(i=endsamples-1;i>=0;i--)
|
||||
clipit8(nrptr[0][i]*nlvol[0],sndptr+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=endsamples-1;i>=0;i--)
|
||||
clipit16(nrptr[0][i]*nlvol[0],sndptr2+i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((void *)snd,0,endsamples*sizeof(float)*2);
|
||||
for(j=0;j<rptrs;j++)
|
||||
{
|
||||
for(i=0;i<endsamples;i++)
|
||||
{
|
||||
snd[(i<<1) ] += rbuf[j][(nlplc[j]+i)&(FIFOSIZ*2-1)]*nlvol[j];
|
||||
snd[(i<<1)+1] += rbuf[j][(nrplc[j]+i)&(FIFOSIZ*2-1)]*nrvol[j];
|
||||
}
|
||||
nlplc[j] += endsamples;
|
||||
nrplc[j] += endsamples;
|
||||
}
|
||||
|
||||
if (bytespersample == 1)
|
||||
{
|
||||
for(i=(endsamples<<1)-1;i>=0;i--)
|
||||
clipit8(snd[i],sndptr+i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=(endsamples<<1)-1;i>=0;i--)
|
||||
clipit16(snd[i],sndptr2+i);
|
||||
}
|
||||
}
|
||||
|
||||
sndptr = sndptr+(numspeakers*endsamples);
|
||||
sndptr2 = sndptr2+(numspeakers*endsamples);
|
||||
rend = ((rend+endsamples)&(FIFOSIZ*2-1));
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* ADLIBEMU.H
|
||||
* Copyright (C) 1998-2001 Ken Silverman
|
||||
* Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
void adlibinit(long dasamplerate,long danumspeakers,long dabytespersample);
|
||||
void adlib0(long i,long v);
|
||||
void adlibgetsample(void *sndptr,long numbytes);
|
||||
void adlibsetvolume(int i);
|
||||
void randoinsts();
|
||||
extern float lvol[9],rvol[9],lplc[9],rplc[9];
|
||||
@@ -596,7 +596,7 @@ static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
|
||||
OPL->AR_TABLE[i] = rate / ARRATE;
|
||||
OPL->DR_TABLE[i] = rate / DRRATE;
|
||||
}
|
||||
for (i = 60;i < 76;i++)
|
||||
for (i = 60;i < 75;i++)
|
||||
{
|
||||
OPL->AR_TABLE[i] = EG_AED-1;
|
||||
OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Adplug - Replayer for many OPL2/OPL3 audio file formats.
|
||||
* Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* kemuopl.h - Emulated OPL using Ken Silverman's emulator, by Simon Peter
|
||||
* <dn.tlp@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef H_ADPLUG_KEMUOPL
|
||||
#define H_ADPLUG_KEMUOPL
|
||||
|
||||
#include "opl.h"
|
||||
extern "C" {
|
||||
#include "adlibemu.h"
|
||||
}
|
||||
|
||||
class CKemuopl: public Copl
|
||||
{
|
||||
public:
|
||||
CKemuopl(int rate, bool bit16, bool usestereo)
|
||||
: use16bit(bit16), stereo(usestereo)
|
||||
{
|
||||
adlibinit(rate, usestereo ? 2 : 1, bit16 ? 2 : 1);
|
||||
currType = TYPE_OPL2;
|
||||
};
|
||||
|
||||
void update(short *buf, int samples)
|
||||
{
|
||||
if(use16bit) samples *= 2;
|
||||
if(stereo) samples *= 2;
|
||||
adlibgetsample(buf, samples);
|
||||
}
|
||||
|
||||
// template methods
|
||||
void write(int reg, int val)
|
||||
{
|
||||
if(currChip == 0)
|
||||
adlib0(reg, val);
|
||||
};
|
||||
|
||||
void init() {};
|
||||
|
||||
private:
|
||||
bool use16bit,stereo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* OPL2 FM synth
|
||||
*
|
||||
* Copyright (c) 2013 Raine M. Ekman <raine/at/iki/fi>
|
||||
* Copyright (c) 2014 Raine M. Ekman <raine/at/iki/fi>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -23,10 +23,10 @@
|
||||
*/
|
||||
|
||||
// TODO:
|
||||
// - Pitch bend
|
||||
// - Velocity (and aftertouch) sensitivity
|
||||
// - in FM mode: OP2 level, add mode: OP1 and OP2 levels
|
||||
// - Better voice allocation: long releases get cut short :(
|
||||
// - .sbi (or similar) file loading into models
|
||||
// - RT safety = get rid of mutex = make emulator code thread-safe
|
||||
|
||||
// - Extras:
|
||||
// - double release: first release is in effect until noteoff (heard if percussive sound),
|
||||
// second is switched in just before key bit cleared (is this useful???)
|
||||
@@ -53,7 +53,6 @@
|
||||
|
||||
#include "opl.h"
|
||||
#include "temuopl.h"
|
||||
#include "kemuopl.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
#include "math.h"
|
||||
@@ -92,6 +91,9 @@ Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
|
||||
// the emulator code isn't really ready for threads
|
||||
QMutex opl2instrument::emulatorMutex;
|
||||
|
||||
// Weird ordering of voice parameters
|
||||
const unsigned int adlib_opadd[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
|
||||
|
||||
opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) :
|
||||
Instrument( _instrument_track, &OPL2_plugin_descriptor ),
|
||||
m_patchModel( 0, 0, 127, this, tr( "Patch" ) ),
|
||||
@@ -139,28 +141,38 @@ opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) :
|
||||
InstrumentPlayHandle * iph = new InstrumentPlayHandle( this );
|
||||
engine::mixer()->addPlayHandle( iph );
|
||||
|
||||
// Voices are laid out in a funny way...
|
||||
// adlib_opadd = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
|
||||
|
||||
// Create an emulator - samplerate, 16 bit, mono
|
||||
// CTemuopl is the better one, CKemuopl kinda sucks (some sounds silent, pitch goes flat after a while)
|
||||
emulatorMutex.lock();
|
||||
// theEmulator = new CKemuopl(engine::mixer()->processingSampleRate(), true, false);
|
||||
theEmulator = new CTemuopl(engine::mixer()->processingSampleRate(), true, false);
|
||||
theEmulator->init();
|
||||
// Enable waveform selection
|
||||
theEmulator->write(0x01,0x20);
|
||||
emulatorMutex.unlock();
|
||||
|
||||
//Initialize voice values
|
||||
voiceNote[0] = 0;
|
||||
voiceLRU[0] = 0;
|
||||
for(int i=1; i<9; ++i) {
|
||||
voiceNote[i] = OPL2_VOICE_FREE;
|
||||
voiceLRU[i] = i;
|
||||
}
|
||||
|
||||
updatePatch();
|
||||
|
||||
// Can the buffer size change suddenly? I bet that would break lots of stuff
|
||||
frameCount = engine::mixer()->framesPerPeriod();
|
||||
renderbuffer = new short[frameCount];
|
||||
|
||||
// Some kind of sane default
|
||||
// Some kind of sane defaults
|
||||
pitchbend = 0;
|
||||
pitchBendRange = 100;
|
||||
RPNcoarse = RPNfine = 255;
|
||||
|
||||
tuneEqual(69, 440);
|
||||
|
||||
for(int i=1; i<9; ++i) {
|
||||
voiceNote[i] = OPL2_VOICE_FREE;
|
||||
}
|
||||
connect( engine::mixer(), SIGNAL( sampleRateChanged() ),
|
||||
this, SLOT( reloadEmulator() ) );
|
||||
// Connect knobs
|
||||
@@ -207,8 +219,15 @@ opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) :
|
||||
MOD_CON( trem_depth_mdl );
|
||||
}
|
||||
|
||||
opl2instrument::~opl2instrument() {
|
||||
delete theEmulator;
|
||||
engine::mixer()->removePlayHandles( instrumentTrack() );
|
||||
delete [] renderbuffer;
|
||||
}
|
||||
|
||||
// Samplerate changes when choosing oversampling, so this is more or less mandatory
|
||||
void opl2instrument::reloadEmulator() {
|
||||
delete theEmulator;
|
||||
emulatorMutex.lock();
|
||||
theEmulator = new CTemuopl(engine::mixer()->processingSampleRate(), true, false);
|
||||
theEmulator->init();
|
||||
@@ -216,50 +235,141 @@ void opl2instrument::reloadEmulator() {
|
||||
emulatorMutex.unlock();
|
||||
for(int i=1; i<9; ++i) {
|
||||
voiceNote[i] = OPL2_VOICE_FREE;
|
||||
voiceLRU[i] = i;
|
||||
}
|
||||
updatePatch();
|
||||
}
|
||||
|
||||
bool opl2instrument::handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time )
|
||||
// This shall only be called from code protected by the holy Mutex!
|
||||
void opl2instrument::setVoiceVelocity(int voice, int vel) {
|
||||
int vel_adjusted;
|
||||
// Velocity calculation, some kind of approximation
|
||||
// Only calculate for operator 1 if in adding mode, don't want to change timbre
|
||||
if( fm_mdl.value() == false ) {
|
||||
vel_adjusted = 63 - ( op1_lvl_mdl.value() * vel/127.0) ;
|
||||
} else {
|
||||
vel_adjusted = 63 - op1_lvl_mdl.value();
|
||||
}
|
||||
theEmulator->write(0x40+adlib_opadd[voice],
|
||||
( (int)op1_scale_mdl.value() & 0x03 << 6) +
|
||||
( vel_adjusted & 0x3f ) );
|
||||
|
||||
|
||||
vel_adjusted = 63 - ( op2_lvl_mdl.value() * vel/127.0 );
|
||||
// vel_adjusted = 63 - op2_lvl_mdl.value();
|
||||
theEmulator->write(0x43+adlib_opadd[voice],
|
||||
( (int)op2_scale_mdl.value() & 0x03 << 6) +
|
||||
( vel_adjusted & 0x3f ) );
|
||||
}
|
||||
|
||||
// Pop least recently used voice - why does it sometimes lose a voice (mostly 0)?
|
||||
int opl2instrument::popVoice() {
|
||||
int tmp = voiceLRU[0];
|
||||
for( int i=0; i<8; ++i) {
|
||||
voiceLRU[i] = voiceLRU[i+1];
|
||||
}
|
||||
voiceLRU[8] = OPL2_NO_VOICE;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int opl2instrument::pushVoice(int v) {
|
||||
int i;
|
||||
for(i=8; i>0; --i) {
|
||||
if( voiceLRU[i-1] != OPL2_NO_VOICE ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
voiceLRU[i] = v;
|
||||
return i;
|
||||
}
|
||||
|
||||
bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time )
|
||||
{
|
||||
emulatorMutex.lock();
|
||||
// Real dummy version... Should at least add:
|
||||
// - smarter voice allocation:
|
||||
// - reuse same note, now we have round robin-ish
|
||||
// - what to do when voices run out and so on...
|
||||
// - mono mode
|
||||
//
|
||||
int key;
|
||||
static int lastvoice=0;
|
||||
if( _me.m_type == MidiNoteOn ) {
|
||||
// to get us in line with MIDI
|
||||
key = _me.key() +12;
|
||||
for(int i=lastvoice+1; i!=lastvoice; ++i,i%=9) {
|
||||
if( voiceNote[i] == OPL2_VOICE_FREE ) {
|
||||
theEmulator->write(0xA0+i, fnums[key] & 0xff);
|
||||
theEmulator->write(0xB0+i, 32 + ((fnums[key] & 0x1f00) >> 8) );
|
||||
// printf("%d: %d %d\n", key, (fnums[key] & 0x1c00) >> 10, fnums[key] & 0x3ff);
|
||||
voiceNote[i] = key;
|
||||
// printf("Voice %d on\n",i);
|
||||
lastvoice=i;
|
||||
break;
|
||||
int key, vel, voice, tmp_pb;
|
||||
|
||||
switch(event.type()) {
|
||||
case MidiNoteOn:
|
||||
// to get us in line with MIDI(?)
|
||||
key = event.key() +12;
|
||||
vel = event.velocity();
|
||||
|
||||
voice = popVoice();
|
||||
if( voice != OPL2_NO_VOICE ) {
|
||||
// Turn voice on, NB! the frequencies are straight by voice number,
|
||||
// not by the adlib_opadd table!
|
||||
theEmulator->write(0xA0+voice, fnums[key] & 0xff);
|
||||
theEmulator->write(0xB0+voice, 32 + ((fnums[key] & 0x1f00) >> 8) );
|
||||
setVoiceVelocity(voice, vel);
|
||||
voiceNote[voice] = key;
|
||||
velocities[key] = vel;
|
||||
}
|
||||
break;
|
||||
case MidiNoteOff:
|
||||
key = event.key() +12;
|
||||
for(voice=0; voice<9; ++voice) {
|
||||
if( voiceNote[voice] == key ) {
|
||||
theEmulator->write(0xA0+voice, fnums[key] & 0xff);
|
||||
theEmulator->write(0xB0+voice, (fnums[key] & 0x1f00) >> 8 );
|
||||
voiceNote[voice] = OPL2_VOICE_FREE;
|
||||
pushVoice(voice);
|
||||
}
|
||||
}
|
||||
velocities[key] = 0;
|
||||
break;
|
||||
case MidiKeyPressure:
|
||||
key = event.key() +12;
|
||||
vel = event.velocity();
|
||||
if( velocities[key] != 0) {
|
||||
velocities[key] = vel;
|
||||
}
|
||||
for(voice=0; voice<9; ++voice) {
|
||||
if(voiceNote[voice] == key) {
|
||||
setVoiceVelocity(voice, vel);
|
||||
}
|
||||
}
|
||||
} else if( _me.m_type == MidiNoteOff ) {
|
||||
key = _me.key() +12;
|
||||
for(int i=0; i<9; ++i) {
|
||||
if( voiceNote[i] == key ) {
|
||||
theEmulator->write(0xA0+i, fnums[key] & 0xff);
|
||||
theEmulator->write(0xB0+i, (fnums[key] & 0x1f00) >> 8 );
|
||||
voiceNote[i] = OPL2_VOICE_FREE;
|
||||
}
|
||||
break;
|
||||
case MidiPitchBend:
|
||||
// Update fnumber table
|
||||
// Pitchbend should be in the range 0...16383 but the new range knob gets it wrong.
|
||||
// tmp_pb = (2*BEND_CENTS)*((float)event.m_data.m_param[0]/16383)-BEND_CENTS;
|
||||
|
||||
// Something like 100 cents = 8192, but offset by 8192 so the +/-100 cents range goes from 0...16383?
|
||||
tmp_pb = ( event.pitchBend()-8192 ) * pitchBendRange / 8192;
|
||||
|
||||
if( tmp_pb != pitchbend ) {
|
||||
pitchbend = tmp_pb;
|
||||
tuneEqual(69, 440.0);
|
||||
}
|
||||
} else {
|
||||
printf("Midi event type %d\n",_me.m_type);
|
||||
// 224 - pitch wheel
|
||||
// 160 - aftertouch?
|
||||
}
|
||||
// Update pitch of sounding notes
|
||||
for( int v=0; v<9; ++v ) {
|
||||
if( voiceNote[v] != OPL2_VOICE_FREE ) {
|
||||
theEmulator->write(0xA0+v, fnums[voiceNote[v] ] & 0xff);
|
||||
theEmulator->write(0xB0+v, 32 + ((fnums[voiceNote[v]] & 0x1f00) >> 8) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MidiControlChange:
|
||||
switch (event.controllerNumber()) {
|
||||
case MidiControllerRegisteredParameterNumberLSB:
|
||||
RPNfine = event.controllerValue();
|
||||
break;
|
||||
case MidiControllerRegisteredParameterNumberMSB:
|
||||
RPNcoarse = event.controllerValue();
|
||||
break;
|
||||
case MidiControllerDataEntry:
|
||||
if( (RPNcoarse << 8) + RPNfine == MidiPitchBendSensitivityRPN) {
|
||||
pitchBendRange = event.controllerValue() * 100;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Midi CC %02x %02x\n", event.controllerNumber(), event.controllerValue() );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Midi event type %d\n",event.type());
|
||||
}
|
||||
emulatorMutex.unlock();
|
||||
return true;
|
||||
}
|
||||
@@ -332,7 +442,6 @@ void opl2instrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
void opl2instrument::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
printf("loadSettings!\n");
|
||||
op1_a_mdl.loadSettings( _this, "op1_a" );
|
||||
op1_d_mdl.loadSettings( _this, "op1_d" );
|
||||
op1_s_mdl.loadSettings( _this, "op1_s" );
|
||||
@@ -366,19 +475,14 @@ void opl2instrument::loadSettings( const QDomElement & _this )
|
||||
|
||||
}
|
||||
|
||||
// Load a preset in binary form
|
||||
// Load a patch into the emulator
|
||||
void opl2instrument::loadPatch(unsigned char inst[14]) {
|
||||
const unsigned int adlib_opadd[] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
|
||||
// Set all voices
|
||||
printf("%02x %02x %02x %02x %02x ",inst[0],inst[1],inst[2],inst[3],inst[4]);
|
||||
printf("%02x %02x %02x %02x %02x %02x\n",inst[5],inst[6],inst[7],inst[8],inst[9],inst[10]);
|
||||
|
||||
emulatorMutex.lock();
|
||||
for(int v=0; v<9; ++v) {
|
||||
theEmulator->write(0x20+adlib_opadd[v],inst[0]); // op1 AM/VIB/EG/KSR/Multiplier
|
||||
theEmulator->write(0x23+adlib_opadd[v],inst[1]); // op2
|
||||
theEmulator->write(0x40+adlib_opadd[v],inst[2]); // op1 KSL/Output Level
|
||||
theEmulator->write(0x43+adlib_opadd[v],inst[3]); // op2
|
||||
// theEmulator->write(0x40+adlib_opadd[v],inst[2]); // op1 KSL/Output Level - these are handled by noteon/aftertouch code
|
||||
// theEmulator->write(0x43+adlib_opadd[v],inst[3]); // op2
|
||||
theEmulator->write(0x60+adlib_opadd[v],inst[4]); // op1 A/D
|
||||
theEmulator->write(0x63+adlib_opadd[v],inst[5]); // op2
|
||||
theEmulator->write(0x80+adlib_opadd[v],inst[6]); // op1 S/R
|
||||
@@ -391,10 +495,10 @@ void opl2instrument::loadPatch(unsigned char inst[14]) {
|
||||
}
|
||||
|
||||
void opl2instrument::tuneEqual(int center, float Hz) {
|
||||
float tmp;
|
||||
for(int n=0; n<128; ++n) {
|
||||
float tmp = Hz*pow(2, (n-center)/12.0);
|
||||
tmp = Hz*pow( 2, ( n - center ) / 12.0 + pitchbend / 1200.0 );
|
||||
fnums[n] = Hz2fnum( tmp );
|
||||
//printf("%d: %d %d %f\n", n, (fnums[n] & 0x1c00) >> 10, fnums[n] & 0x3ff,tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +516,6 @@ int opl2instrument::Hz2fnum(float Hz) {
|
||||
// Load one of the default patches
|
||||
void opl2instrument::loadGMPatch() {
|
||||
unsigned char *inst = midi_fm_instruments[m_patchModel.value()];
|
||||
// printf("loadGMPatch: %d ", m_patchModel.value());
|
||||
loadPatch(inst);
|
||||
}
|
||||
|
||||
@@ -423,7 +526,6 @@ void opl2instrument::loadGMPatch() {
|
||||
|
||||
// Update patch from the models to the chip emulation
|
||||
void opl2instrument::updatePatch() {
|
||||
printf("updatePatch()\n");
|
||||
unsigned char *inst = midi_fm_instruments[0];
|
||||
inst[0] = ( op1_trem_mdl.value() ? 128 : 0 ) +
|
||||
( op1_vib_mdl.value() ? 64 : 0 ) +
|
||||
@@ -456,10 +558,16 @@ void opl2instrument::updatePatch() {
|
||||
inst[12] = 0;
|
||||
inst[13] = 0;
|
||||
|
||||
// Not part of the patch per se
|
||||
// Not part of the per-voice patch info
|
||||
theEmulator->write(0xBD, (trem_depth_mdl.value() ? 128 : 0 ) +
|
||||
(vib_depth_mdl.value() ? 64 : 0 ));
|
||||
|
||||
// have to do this, as the level knobs might've changed
|
||||
for( int voice = 0; voice < 9 ; ++voice) {
|
||||
if(voiceNote[voice]!=OPL2_VOICE_FREE) {
|
||||
setVoiceVelocity(voice, velocities[voiceNote[voice]] );
|
||||
}
|
||||
}
|
||||
loadPatch(inst);
|
||||
}
|
||||
|
||||
@@ -552,9 +660,9 @@ opl2instrumentView::opl2instrumentView( Instrument * _instrument,
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
|
||||
"artwork" ) );
|
||||
setPalette( pal );
|
||||
|
||||
|
||||
|
||||
}
|
||||
opl2instrumentView::~opl2instrumentView() {
|
||||
// Nobody else seems to delete their knobs and buttons?
|
||||
}
|
||||
|
||||
void opl2instrumentView::modelChanged()
|
||||
@@ -604,4 +712,5 @@ void opl2instrumentView::modelChanged()
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "moc_opl2instrument.cxx"
|
||||
|
||||
@@ -34,19 +34,23 @@
|
||||
#include "pixmap_button.h"
|
||||
|
||||
#define OPL2_VOICE_FREE 255
|
||||
#define OPL2_NO_VOICE 255
|
||||
// The "normal" range for LMMS pitchbends
|
||||
#define DEFAULT_BEND_CENTS 100
|
||||
|
||||
class opl2instrument : public Instrument
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
opl2instrument( InstrumentTrack * _instrument_track );
|
||||
virtual ~opl2instrument();
|
||||
|
||||
virtual QString nodeName() const;
|
||||
virtual PluginView * instantiateView( QWidget * _parent );
|
||||
|
||||
inline virtual bool isMidiBased() const { return true; }
|
||||
|
||||
virtual bool handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time );
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _this );
|
||||
@@ -107,20 +111,35 @@ private:
|
||||
fpp_t frameCount;
|
||||
short *renderbuffer;
|
||||
int voiceNote[9];
|
||||
int heldNotes[128];
|
||||
// Least recently used voices
|
||||
int voiceLRU[9];
|
||||
// 0 - no note, >0 - note on velocity
|
||||
int velocities[128];
|
||||
// These include both octave and Fnumber
|
||||
int fnums[128];
|
||||
// in cents, range defaults to +/-100 cents (should this be changeable?)
|
||||
int pitchbend;
|
||||
int pitchBendRange;
|
||||
|
||||
int popVoice();
|
||||
int pushVoice(int v);
|
||||
|
||||
int Hz2fnum(float Hz);
|
||||
static QMutex emulatorMutex;
|
||||
void setVoiceVelocity(int voice, int vel);
|
||||
|
||||
// Pitch bend range comes through RPNs.
|
||||
int RPNcoarse, RPNfine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class opl2instrumentView : public InstrumentView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
opl2instrumentView( Instrument * _instrument, QWidget * _parent );
|
||||
virtual ~opl2instrumentView();
|
||||
lcdSpinBox *m_patch;
|
||||
void modelChanged();
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#ifndef GB_APU_H
|
||||
#define GB_APU_H
|
||||
|
||||
typedef long gb_time_t; // clock cycle count
|
||||
typedef unsigned gb_addr_t; // 16-bit address
|
||||
typedef int gb_time_t; // clock cycle count
|
||||
typedef int gb_addr_t; // 16-bit address
|
||||
|
||||
#include "Gb_Oscs.h"
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 26 KiB |
@@ -81,6 +81,7 @@ PeakControllerEffect::~PeakControllerEffect()
|
||||
if( idx >= 0 )
|
||||
{
|
||||
PeakController::s_effects.remove( idx );
|
||||
engine::getSong()->removeController( m_autoController );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "PeakController.h"
|
||||
#include "peak_controller_effect_controls.h"
|
||||
#include "peak_controller_effect.h"
|
||||
#include "preset_preview_play_handle.h"
|
||||
|
||||
|
||||
PeakControllerEffectControls::
|
||||
@@ -66,7 +67,7 @@ void PeakControllerEffectControls::loadSettings( const QDomElement & _this )
|
||||
}
|
||||
m_effect->m_effectId = effectId;
|
||||
|
||||
if( m_effect->m_autoController )
|
||||
if( m_effect->m_autoController && presetPreviewPlayHandle::isPreviewing() == false )
|
||||
{
|
||||
delete m_effect->m_autoController;
|
||||
m_effect->m_autoController = 0;
|
||||
|
||||
@@ -87,7 +87,8 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) :
|
||||
m_font( NULL ),
|
||||
m_fontId( 0 ),
|
||||
m_filename( "" ),
|
||||
m_lastMidiPitch( 8192 ),
|
||||
m_lastMidiPitch( -1 ),
|
||||
m_lastMidiPitchRange( -1 ),
|
||||
m_channel( 1 ),
|
||||
m_bankNum( 0, 0, 999, this, tr("Bank") ),
|
||||
m_patchNum( 0, 0, 127, this, tr("Patch") ),
|
||||
@@ -679,12 +680,21 @@ void sf2Instrument::play( sampleFrame * _working_buffer )
|
||||
const fpp_t frames = engine::mixer()->framesPerPeriod();
|
||||
|
||||
m_synthMutex.lock();
|
||||
if( m_lastMidiPitch != instrumentTrack()->midiPitch() )
|
||||
|
||||
const int currentMidiPitch = instrumentTrack()->midiPitch();
|
||||
if( m_lastMidiPitch != currentMidiPitch )
|
||||
{
|
||||
m_lastMidiPitch = instrumentTrack()->midiPitch();
|
||||
m_lastMidiPitch = currentMidiPitch;
|
||||
fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch );
|
||||
}
|
||||
|
||||
const int currentMidiPitchRange = instrumentTrack()->midiPitchRange();
|
||||
if( m_lastMidiPitchRange != currentMidiPitchRange )
|
||||
{
|
||||
m_lastMidiPitchRange = currentMidiPitchRange;
|
||||
fluid_synth_pitch_wheel_sens( m_synth, m_channel, m_lastMidiPitchRange );
|
||||
}
|
||||
|
||||
if( m_internalSampleRate < engine::mixer()->processingSampleRate() &&
|
||||
m_srcState != NULL )
|
||||
{
|
||||
|
||||
@@ -129,6 +129,7 @@ private:
|
||||
int m_notesRunning[128];
|
||||
sample_rate_t m_internalSampleRate;
|
||||
int m_lastMidiPitch;
|
||||
int m_lastMidiPitchRange;
|
||||
int m_channel;
|
||||
|
||||
lcdSpinBoxModel m_bankNum;
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
@@ -310,13 +310,12 @@ void vestigeInstrument::play( sampleFrame * _buf )
|
||||
|
||||
|
||||
|
||||
bool vestigeInstrument::handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time )
|
||||
bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time )
|
||||
{
|
||||
m_pluginMutex.lock();
|
||||
if( m_plugin != NULL )
|
||||
{
|
||||
m_plugin->processMidiEvent( _me, _time );
|
||||
m_plugin->processMidiEvent( event, time );
|
||||
}
|
||||
m_pluginMutex.unlock();
|
||||
|
||||
@@ -779,8 +778,7 @@ void VestigeInstrumentView::noteOffAll( void )
|
||||
{
|
||||
for( int key = 0; key <= MidiMaxNote; ++key )
|
||||
{
|
||||
m_vi->m_plugin->processMidiEvent(
|
||||
midiEvent( MidiNoteOff, 0, key, 0 ), 0 );
|
||||
m_vi->m_plugin->processMidiEvent( MidiEvent( MidiNoteOff, 0, key, 0 ), 0 );
|
||||
}
|
||||
}
|
||||
m_vi->m_pluginMutex.unlock();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* vestige.h - instrument VeSTige for hosting VST-plugins
|
||||
*
|
||||
* Copyright (c) 2005-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
#include "midi.h"
|
||||
#include "note.h"
|
||||
#include "knob.h"
|
||||
|
||||
@@ -69,8 +68,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time );
|
||||
|
||||
virtual PluginView * instantiateView( QWidget * _parent );
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ struct ERect
|
||||
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "midi.h"
|
||||
#include "Midi.h"
|
||||
#include "communication.h"
|
||||
|
||||
#include "VST_sync_shm.h"
|
||||
@@ -132,8 +132,7 @@ public:
|
||||
virtual void process( const sampleFrame * _in, sampleFrame * _out );
|
||||
|
||||
|
||||
virtual void processMidiEvent( const midiEvent & _event,
|
||||
const f_cnt_t _offset );
|
||||
virtual void processMidiEvent( const MidiEvent& event, const f_cnt_t offset );
|
||||
|
||||
// set given sample-rate for plugin
|
||||
virtual void updateSampleRate()
|
||||
@@ -774,16 +773,15 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out )
|
||||
// dispatcher-call, so we create static copies of the
|
||||
// data and post them
|
||||
#define MIDI_EVENT_BUFFER_COUNT 1024
|
||||
static char event_buf[sizeof( VstMidiEvent * ) *
|
||||
MIDI_EVENT_BUFFER_COUNT +
|
||||
sizeof( VstEvents )];
|
||||
static char eventsBuffer[sizeof( VstEvents ) + sizeof( VstMidiEvent * ) * MIDI_EVENT_BUFFER_COUNT];
|
||||
static VstMidiEvent vme[MIDI_EVENT_BUFFER_COUNT];
|
||||
VstEvents * events = (VstEvents *) event_buf;
|
||||
|
||||
VstEvents* events = (VstEvents *) eventsBuffer;
|
||||
events->reserved = 0;
|
||||
events->numEvents = m_midiEvents.size();
|
||||
|
||||
int idx = 0;
|
||||
for( VstMidiEventList::iterator it = m_midiEvents.begin();
|
||||
it != m_midiEvents.end(); ++it, ++idx )
|
||||
for( VstMidiEventList::iterator it = m_midiEvents.begin(); it != m_midiEvents.end(); ++it, ++idx )
|
||||
{
|
||||
memcpy( &vme[idx], &*it, sizeof( VstMidiEvent ) );
|
||||
events->events[idx] = (VstEvent *) &vme[idx];
|
||||
@@ -831,36 +829,37 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out )
|
||||
|
||||
|
||||
|
||||
void RemoteVstPlugin::processMidiEvent( const midiEvent & _event,
|
||||
const f_cnt_t _offset )
|
||||
void RemoteVstPlugin::processMidiEvent( const MidiEvent& event, const f_cnt_t offset )
|
||||
{
|
||||
VstMidiEvent event;
|
||||
VstMidiEvent vme;
|
||||
|
||||
event.type = kVstMidiType;
|
||||
event.byteSize = 24;
|
||||
event.deltaFrames = _offset;
|
||||
event.flags = 0;
|
||||
event.detune = 0;
|
||||
event.noteLength = 0;
|
||||
event.noteOffset = 0;
|
||||
event.noteOffVelocity = 0;
|
||||
event.reserved1 = 0;
|
||||
event.reserved2 = 0;
|
||||
event.midiData[0] = _event.m_type + _event.m_channel;
|
||||
switch( _event.m_type )
|
||||
vme.type = kVstMidiType;
|
||||
vme.byteSize = 24;
|
||||
vme.deltaFrames = offset;
|
||||
vme.flags = 0;
|
||||
vme.detune = 0;
|
||||
vme.noteLength = 0;
|
||||
vme.noteOffset = 0;
|
||||
vme.noteOffVelocity = 0;
|
||||
vme.reserved1 = 0;
|
||||
vme.reserved2 = 0;
|
||||
vme.midiData[0] = event.type() + event.channel();
|
||||
|
||||
switch( event.type() )
|
||||
{
|
||||
case MidiPitchBend:
|
||||
event.midiData[1] = _event.m_data.m_param[0] & 0x7f;
|
||||
event.midiData[2] = _event.m_data.m_param[0] >> 7;
|
||||
vme.midiData[1] = event.param( 0 ) & 0x7f;
|
||||
vme.midiData[2] = event.param( 1 ) >> 7;
|
||||
break;
|
||||
// TODO: handle more special cases
|
||||
default:
|
||||
event.midiData[1] = _event.key();
|
||||
event.midiData[2] = _event.velocity();
|
||||
vme.midiData[1] = event.key();
|
||||
vme.midiData[2] = event.velocity();
|
||||
break;
|
||||
}
|
||||
event.midiData[3] = 0;
|
||||
m_midiEvents.push_back( event );
|
||||
vme.midiData[3] = 0;
|
||||
|
||||
m_midiEvents.push_back( vme );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* LocalZynAddSubFx.cpp - local implementation of ZynAddSubFx plugin
|
||||
*
|
||||
* Copyright (c) 2009-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -190,47 +190,43 @@ void LocalZynAddSubFx::setLmmsWorkingDir( const std::string & _dir )
|
||||
|
||||
|
||||
|
||||
void LocalZynAddSubFx::processMidiEvent( const midiEvent & _e )
|
||||
void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event )
|
||||
{
|
||||
// all functions are called while m_master->mutex is held
|
||||
static NULLMidiIn midiIn;
|
||||
|
||||
switch( _e.m_type )
|
||||
switch( event.type() )
|
||||
{
|
||||
case MidiNoteOn:
|
||||
if( _e.velocity() > 0 )
|
||||
if( event.velocity() > 0 )
|
||||
{
|
||||
if( _e.key() <= 0 || _e.key() >= 128 )
|
||||
if( event.key() <= 0 || event.key() >= 128 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( m_runningNotes[_e.key()] > 0 )
|
||||
if( m_runningNotes[event.key()] > 0 )
|
||||
{
|
||||
m_master->NoteOff( _e.channel(), _e.key() );
|
||||
m_master->NoteOff( event.channel(), event.key() );
|
||||
}
|
||||
++m_runningNotes[_e.key()];
|
||||
m_master->NoteOn( _e.channel(), _e.key(), _e.velocity() );
|
||||
++m_runningNotes[event.key()];
|
||||
m_master->NoteOn( event.channel(), event.key(), event.velocity() );
|
||||
break;
|
||||
}
|
||||
case MidiNoteOff:
|
||||
if( _e.key() <= 0 || _e.key() >= 128 )
|
||||
if( event.key() <= 0 || event.key() >= 128 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( --m_runningNotes[_e.key()] <= 0 )
|
||||
if( --m_runningNotes[event.key()] <= 0 )
|
||||
{
|
||||
m_master->NoteOff( _e.channel(), _e.key() );
|
||||
m_master->NoteOff( event.channel(), event.key() );
|
||||
}
|
||||
break;
|
||||
case MidiPitchBend:
|
||||
m_master->SetController( _e.channel(), C_pitchwheel,
|
||||
_e.m_data.m_param[0] +
|
||||
_e.m_data.m_param[1]*128-8192 );
|
||||
m_master->SetController( event.channel(), C_pitchwheel, event.pitchBend()-8192 );
|
||||
break;
|
||||
case MidiControlChange:
|
||||
m_master->SetController( _e.channel(),
|
||||
midiIn.getcontroller( _e.m_data.m_param[0] ),
|
||||
_e.m_data.m_param[1] );
|
||||
m_master->SetController( event.channel(), midiIn.getcontroller( event.controllerNumber() ), event.controllerValue() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* LocalZynAddSubFx.h - local implementation of ZynAddSubFx plugin
|
||||
*
|
||||
* Copyright (c) 2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef _LOCAL_ZYNADDSUBFX_H
|
||||
#define _LOCAL_ZYNADDSUBFX_H
|
||||
|
||||
#include "MidiEvent.h"
|
||||
#include "note.h"
|
||||
|
||||
class Master;
|
||||
@@ -48,7 +49,7 @@ public:
|
||||
void setPresetDir( const std::string & _dir );
|
||||
void setLmmsWorkingDir( const std::string & _dir );
|
||||
|
||||
void processMidiEvent( const midiEvent & _e );
|
||||
void processMidiEvent( const MidiEvent& event );
|
||||
|
||||
void processAudio( sampleFrame * _out );
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* RemoteZynAddSubFx.cpp - ZynAddSubFx-embedding plugin
|
||||
*
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -126,10 +126,9 @@ public:
|
||||
}
|
||||
|
||||
// all functions are called while m_master->mutex is held
|
||||
virtual void processMidiEvent( const midiEvent & _e,
|
||||
const f_cnt_t /* _offset */ )
|
||||
virtual void processMidiEvent( const MidiEvent& event, const f_cnt_t /* _offset */ )
|
||||
{
|
||||
LocalZynAddSubFx::processMidiEvent( _e );
|
||||
LocalZynAddSubFx::processMidiEvent( event );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -340,14 +340,13 @@ void ZynAddSubFxInstrument::play( sampleFrame * _buf )
|
||||
|
||||
|
||||
|
||||
bool ZynAddSubFxInstrument::handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time )
|
||||
bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time )
|
||||
{
|
||||
// do not forward external MIDI Control Change events if the according
|
||||
// LED is not checked
|
||||
if( _me.type() == MidiControlChange &&
|
||||
_me.sourcePort() != this &&
|
||||
m_forwardMidiCcModel.value() == false )
|
||||
if( event.type() == MidiControlChange &&
|
||||
event.sourcePort() != this &&
|
||||
m_forwardMidiCcModel.value() == false )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -355,11 +354,11 @@ bool ZynAddSubFxInstrument::handleMidiEvent( const midiEvent & _me,
|
||||
m_pluginMutex.lock();
|
||||
if( m_remotePlugin )
|
||||
{
|
||||
m_remotePlugin->processMidiEvent( _me, 0 );
|
||||
m_remotePlugin->processMidiEvent( event, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_plugin->processMidiEvent( _me );
|
||||
m_plugin->processMidiEvent( event );
|
||||
}
|
||||
m_pluginMutex.unlock();
|
||||
|
||||
@@ -446,8 +445,7 @@ void ZynAddSubFxInstrument::initPlugin()
|
||||
|
||||
void ZynAddSubFxInstrument::sendControlChange( MidiControllers midiCtl, float value )
|
||||
{
|
||||
handleMidiEvent( midiEvent( MidiControlChange, instrumentTrack()->midiPort()->realOutputChannel(), midiCtl, (int) value, this ),
|
||||
midiTime() );
|
||||
handleMidiEvent( MidiEvent( MidiControlChange, instrumentTrack()->midiPort()->realOutputChannel(), midiCtl, (int) value, this ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ public:
|
||||
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
|
||||
virtual bool handleMidiEvent( const midiEvent & _me,
|
||||
const midiTime & _time );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime() );
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 84 KiB |
@@ -35,7 +35,7 @@ Controller::~Controller()
|
||||
|
||||
void Controller::defaults()
|
||||
{
|
||||
setpitchwheelbendrange(200); //2 halftones
|
||||
setpitchwheelbendrange(100); //2 halftones
|
||||
expression.receive = 1;
|
||||
panning.depth = 64;
|
||||
filtercutoff.depth = 64;
|
||||
|
||||
@@ -157,10 +157,9 @@ void Sequencer::resettime(timestruct *t)
|
||||
t->abs = 0.0;
|
||||
t->rel = 0.0;
|
||||
|
||||
timeval tval;
|
||||
|
||||
t->last = 0.0;
|
||||
#ifndef OS_WINDOWS
|
||||
timeval tval;
|
||||
if(gettimeofday(&tval, NULL) == 0)
|
||||
t->last = tval.tv_sec + tval.tv_usec * 0.000001;
|
||||
#endif
|
||||
@@ -168,9 +167,9 @@ void Sequencer::resettime(timestruct *t)
|
||||
|
||||
void Sequencer::updatecounter(timestruct *t)
|
||||
{
|
||||
timeval tval;
|
||||
double current = 0.0;
|
||||
#ifndef OS_WINDOWS
|
||||
timeval tval;
|
||||
if(gettimeofday(&tval, NULL) == 0)
|
||||
current = tval.tv_sec + tval.tv_usec * 0.000001;
|
||||
#endif
|
||||
|
||||