Implement multiple Output Port (32)
Remove drmr2.ttl Add drmr2-mkttl to dynamicly generate drmr2.ttl
This commit is contained in:
parent
647b6f9ed9
commit
3c08afc403
@ -74,6 +74,9 @@ set_target_properties (drmr2_ui
|
|||||||
COMPILE_FLAGS ${ui_compile_flags}
|
COMPILE_FLAGS ${ui_compile_flags}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# drmr2.ttl generation
|
||||||
|
add_custom_command(TARGET drmr2 COMMAND ./drmr2-mkttl WORKING_DIRECTORY ..)
|
||||||
|
|
||||||
# Custom test commands
|
# Custom test commands
|
||||||
add_executable ( htest
|
add_executable ( htest
|
||||||
EXCLUDE_FROM_ALL
|
EXCLUDE_FROM_ALL
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
DrMr2
|
DrMr2
|
||||||
====
|
====
|
||||||
|
|
||||||
DrMr2 is a fork from DrMr, with additional patches comming from falkTX & PeterN
|
DrMr2 is a fork from DrMr, with additional patches comming from falkTX & PeterN.
|
||||||
|
The first aim is to let DrMR2 to be more flexible.
|
||||||
|
|
||||||
|
The first evolution implemented is the multiple output audio port (defaulted to 32).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
153
drmr2-mkttl
Executable file
153
drmr2-mkttl
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
out_file="drmr2.ttl"
|
||||||
|
outport_nb=32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_port()
|
||||||
|
{
|
||||||
|
echo -e >>${out_file} " ["
|
||||||
|
|
||||||
|
case "$#"
|
||||||
|
in
|
||||||
|
"2")
|
||||||
|
printf >>${out_file} "$2" "${idx}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"3")
|
||||||
|
printf >>${out_file} "$2" "${idx}" "$3"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"4")
|
||||||
|
printf >>${out_file} "$2" "${idx}" "$3" "$4"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo -e >>${out_file} "\n ]$1"
|
||||||
|
|
||||||
|
idx=$((${idx} + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
>${out_file}
|
||||||
|
|
||||||
|
echo -n >>${out_file} '@prefix lv2: <http://lv2plug.in/ns/lv2core#>.
|
||||||
|
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
|
||||||
|
@prefix doap: <http://usefulinc.com/ns/doap#>.
|
||||||
|
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
|
||||||
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
|
||||||
|
@prefix ui: <http://lv2plug.in/ns/extensions/ui#>.
|
||||||
|
@prefix atom: <http://lv2plug.in/ns/ext/atom#>.
|
||||||
|
@prefix urid: <http://lv2plug.in/ns/ext/urid#>.
|
||||||
|
|
||||||
|
<http://github.com/AlkorZ3/drmr2>
|
||||||
|
a lv2:InstrumentPlugin, lv2:Plugin;
|
||||||
|
lv2:binary <drmr2.so>;
|
||||||
|
doap:name "DrMr2 Sampler";
|
||||||
|
doap:maintainer [
|
||||||
|
foaf:name "AlkorZ3";
|
||||||
|
foaf:homepage <http://github.com/AlkorZ3/drmr2/wiki>;
|
||||||
|
foaf:mbox <alkorz3@rx3.net>
|
||||||
|
] ;
|
||||||
|
doap:license <http://usefulinc.com/doap/licenses/gpl>;
|
||||||
|
lv2:requiredFeature urid:map;
|
||||||
|
ui:ui <http://github.com/AlkorZ3/drmr2#ui>;
|
||||||
|
lv2:extensionData <http://lv2plug.in/ns/ext/state#interface>;
|
||||||
|
lv2:port'
|
||||||
|
|
||||||
|
idx=0
|
||||||
|
|
||||||
|
add_port "," " a lv2:InputPort , atom:AtomPort;
|
||||||
|
atom:bufferType atom:Sequence ;
|
||||||
|
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent>,
|
||||||
|
<http://lv2plug.in/ns/ext/atom#Resource>;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"control\";
|
||||||
|
lv2:name \"Control\";"
|
||||||
|
|
||||||
|
|
||||||
|
idx=1
|
||||||
|
out_id=0
|
||||||
|
|
||||||
|
while [[ "${out_id}" -lt "${outport_nb}" ]]
|
||||||
|
do
|
||||||
|
add_port "," " a lv2:AudioPort, lv2:OutputPort;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"audio_%02d_out_1\";
|
||||||
|
lv2:name \"Audio %02d - Out 1\";" "${out_id}" "${out_id}"
|
||||||
|
|
||||||
|
add_port "," " a lv2:AudioPort, lv2:OutputPort;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"audio_%02d_out_2\";
|
||||||
|
lv2:name \"Audio %02d - Out 2\";" "${out_id}" "${out_id}"
|
||||||
|
|
||||||
|
out_id=$((${out_id} + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_port "," " a lv2:ControlPort, lv2:InputPort;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"base_note\";
|
||||||
|
lv2:name \"Midi Base Note\";
|
||||||
|
lv2:minimum 21;
|
||||||
|
lv2:maximum 107;
|
||||||
|
lv2:default 36;
|
||||||
|
lv2:portProperty lv2:integer;"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
out_id=0
|
||||||
|
|
||||||
|
while [[ "${out_id}" -lt "32" ]]
|
||||||
|
do
|
||||||
|
add_port "," " a lv2:ControlPort, lv2:InputPort;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"gain_%02d\";
|
||||||
|
lv2:name \"Sample Gain %02d\";
|
||||||
|
lv2:minimum -60.0;
|
||||||
|
lv2:maximum 6.0;
|
||||||
|
lv2:default 0.0;
|
||||||
|
lv2:scalePoint [
|
||||||
|
rdfs:label \"-inf\" ;
|
||||||
|
rdf:value -60.0;
|
||||||
|
]" "${out_id}" "${out_id}"
|
||||||
|
|
||||||
|
out_id=$((${out_id} + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
out_id=0
|
||||||
|
|
||||||
|
while [[ "${out_id}" -lt "32" ]]
|
||||||
|
do
|
||||||
|
add_port "," " a lv2:ControlPort, lv2:InputPort;
|
||||||
|
lv2:index %d;
|
||||||
|
lv2:symbol \"pan_%02d\";
|
||||||
|
lv2:name \"Sample Pan %02d\";
|
||||||
|
lv2:minimum -1.0;
|
||||||
|
lv2:maximum 1.0;
|
||||||
|
lv2:default 0.0;" "${out_id}" "${out_id}"
|
||||||
|
|
||||||
|
out_id=$((${out_id} + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_port "." " a lv2:OutputPort , atom:AtomPort ;
|
||||||
|
atom:bufferType atom:Sequence ;
|
||||||
|
atom:supports <http://lv2plug.in/ns/ext/atom#Resource> ;
|
||||||
|
lv2:index %d ;
|
||||||
|
lv2:symbol \"core_events\" ;
|
||||||
|
lv2:name \"Core Events\""
|
||||||
|
|
||||||
|
echo >>${out_file} '
|
||||||
|
|
||||||
|
<http://github.com/AlkorZ3/drmr2#ui>
|
||||||
|
a ui:GtkUI ;
|
||||||
|
ui:binary <drmr2_ui.so> .'
|
163
drmr2.c
163
drmr2.c
@ -65,6 +65,10 @@ static void* load_thread(void* arg) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static LV2_Handle
|
static LV2_Handle
|
||||||
instantiate(const LV2_Descriptor* descriptor,
|
instantiate(const LV2_Descriptor* descriptor,
|
||||||
double rate,
|
double rate,
|
||||||
@ -121,8 +125,11 @@ instantiate(const LV2_Descriptor* descriptor,
|
|||||||
drmr->request_buf = malloc(REQ_BUF_SIZE*sizeof(char*));
|
drmr->request_buf = malloc(REQ_BUF_SIZE*sizeof(char*));
|
||||||
memset(drmr->request_buf,0,REQ_BUF_SIZE*sizeof(char*));
|
memset(drmr->request_buf,0,REQ_BUF_SIZE*sizeof(char*));
|
||||||
|
|
||||||
|
drmr->left = malloc(32*sizeof(float*));
|
||||||
|
drmr->right = malloc(32*sizeof(float*));
|
||||||
drmr->gains = malloc(32*sizeof(float*));
|
drmr->gains = malloc(32*sizeof(float*));
|
||||||
drmr->pans = malloc(32*sizeof(float*));
|
drmr->pans = malloc(32*sizeof(float*));
|
||||||
|
|
||||||
for(i = 0;i<32;i++) {
|
for(i = 0;i<32;i++) {
|
||||||
drmr->gains[i] = NULL;
|
drmr->gains[i] = NULL;
|
||||||
drmr->pans[i] = NULL;
|
drmr->pans[i] = NULL;
|
||||||
@ -131,42 +138,65 @@ instantiate(const LV2_Descriptor* descriptor,
|
|||||||
return (LV2_Handle)drmr;
|
return (LV2_Handle)drmr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
connect_port(LV2_Handle instance,
|
connect_port(LV2_Handle instance,
|
||||||
uint32_t port,
|
uint32_t port,
|
||||||
void* data) {
|
void* data)
|
||||||
|
{
|
||||||
DrMr* drmr = (DrMr*)instance;
|
DrMr* drmr = (DrMr*)instance;
|
||||||
DrMrPortIndex port_index = (DrMrPortIndex)port;
|
DrMrPortIndex port_index = (DrMrPortIndex)port;
|
||||||
switch (port_index) {
|
|
||||||
|
switch (port_index)
|
||||||
|
{
|
||||||
case DRMR_CONTROL:
|
case DRMR_CONTROL:
|
||||||
drmr->control_port = (LV2_Atom_Sequence*)data;
|
drmr->control_port = (LV2_Atom_Sequence*)data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DRMR_CORE_EVENT:
|
case DRMR_CORE_EVENT:
|
||||||
drmr->core_event_port = (LV2_Atom_Sequence*)data;
|
drmr->core_event_port = (LV2_Atom_Sequence*)data;
|
||||||
break;
|
break;
|
||||||
case DRMR_LEFT:
|
|
||||||
drmr->left = (float*)data;
|
|
||||||
break;
|
|
||||||
case DRMR_RIGHT:
|
|
||||||
drmr->right = (float*)data;
|
|
||||||
break;
|
|
||||||
case DRMR_BASENOTE:
|
case DRMR_BASENOTE:
|
||||||
if (data) drmr->baseNote = (float*)data;
|
if (data) drmr->baseNote = (float*)data;
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (port_index >= DRMR_GAIN_ONE && port_index <= DRMR_GAIN_THIRTYTWO) {
|
default:
|
||||||
|
if( port_index >= DRMR_LEFT_00 && port_index <= DRMR_RIGHT_31)
|
||||||
|
{
|
||||||
|
int outoff = (port_index - DRMR_LEFT_00) / 2;
|
||||||
|
|
||||||
|
if( ( port_index - DRMR_LEFT_00) % 2)
|
||||||
|
{
|
||||||
|
drmr->right[outoff] = (float*)data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drmr->left[outoff] = (float*)data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( port_index >= DRMR_GAIN_ONE && port_index <= DRMR_GAIN_THIRTYTWO)
|
||||||
|
{
|
||||||
int goff = port_index - DRMR_GAIN_ONE;
|
int goff = port_index - DRMR_GAIN_ONE;
|
||||||
drmr->gains[goff] = (float*)data;
|
drmr->gains[goff] = (float*)data;
|
||||||
}
|
}
|
||||||
|
else if( port_index >= DRMR_PAN_ONE && port_index <= DRMR_PAN_THIRTYTWO)
|
||||||
if (port_index >= DRMR_PAN_ONE && port_index <= DRMR_PAN_THIRTYTWO) {
|
{
|
||||||
int poff = port_index - DRMR_PAN_ONE;
|
int poff = port_index - DRMR_PAN_ONE;
|
||||||
drmr->pans[poff] = (float*)data;
|
drmr->pans[poff] = (float*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline LV2_Atom *build_update_message(DrMr *drmr) {
|
static inline LV2_Atom *build_update_message(DrMr *drmr) {
|
||||||
LV2_Atom_Forge_Frame set_frame;
|
LV2_Atom_Forge_Frame set_frame;
|
||||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||||
@ -179,6 +209,10 @@ static inline LV2_Atom *build_update_message(DrMr *drmr) {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline LV2_Atom *build_state_message(DrMr *drmr) {
|
static inline LV2_Atom *build_state_message(DrMr *drmr) {
|
||||||
LV2_Atom_Forge_Frame set_frame;
|
LV2_Atom_Forge_Frame set_frame;
|
||||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||||
@ -197,6 +231,10 @@ static inline LV2_Atom *build_state_message(DrMr *drmr) {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline LV2_Atom *build_midi_info_message(DrMr *drmr, uint8_t *data) {
|
static inline LV2_Atom *build_midi_info_message(DrMr *drmr, uint8_t *data) {
|
||||||
LV2_Atom_Forge_Frame set_frame;
|
LV2_Atom_Forge_Frame set_frame;
|
||||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||||
@ -207,6 +245,10 @@ static inline LV2_Atom *build_midi_info_message(DrMr *drmr, uint8_t *data) {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline void layer_to_sample(drmr_sample *sample, float gain) {
|
static inline void layer_to_sample(drmr_sample *sample, float gain) {
|
||||||
int i;
|
int i;
|
||||||
float mapped_gain = (1-(gain/GAIN_MIN));
|
float mapped_gain = (1-(gain/GAIN_MIN));
|
||||||
@ -229,6 +271,10 @@ static inline void layer_to_sample(drmr_sample *sample, float gain) {
|
|||||||
sample->data = sample->layers[0].data;
|
sample->data = sample->layers[0].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data, uint32_t offset) {
|
static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data, uint32_t offset) {
|
||||||
// need to mutex this to avoid getting the samples array
|
// need to mutex this to avoid getting the samples array
|
||||||
// changed after the check that the midi-note is valid
|
// changed after the check that the midi-note is valid
|
||||||
@ -251,6 +297,10 @@ static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data, uint3
|
|||||||
pthread_mutex_unlock(&drmr->load_mutex);
|
pthread_mutex_unlock(&drmr->load_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline void untrigger_sample(DrMr *drmr, int nn, uint32_t offset) {
|
static inline void untrigger_sample(DrMr *drmr, int nn, uint32_t offset) {
|
||||||
pthread_mutex_lock(&drmr->load_mutex);
|
pthread_mutex_lock(&drmr->load_mutex);
|
||||||
if (nn >= 0 && nn < drmr->num_samples) {
|
if (nn >= 0 && nn < drmr->num_samples) {
|
||||||
@ -265,13 +315,17 @@ static inline void untrigger_sample(DrMr *drmr, int nn, uint32_t offset) {
|
|||||||
pthread_mutex_unlock(&drmr->load_mutex);
|
pthread_mutex_unlock(&drmr->load_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define DB3SCALE -0.8317830986718104f
|
#define DB3SCALE -0.8317830986718104f
|
||||||
#define DB3SCALEPO 1.8317830986718104f
|
#define DB3SCALEPO 1.8317830986718104f
|
||||||
// taken from lv2 example amp plugin
|
// taken from lv2 example amp plugin
|
||||||
#define DB_CO(g) ((g) > GAIN_MIN ? powf(10.0f, (g) * 0.05f) : 0.0f)
|
#define DB_CO(g) ((g) > GAIN_MIN ? powf(10.0f, (g) * 0.05f) : 0.0f)
|
||||||
|
|
||||||
static void run(LV2_Handle instance, uint32_t n_samples) {
|
static void run(LV2_Handle instance, uint32_t n_samples) {
|
||||||
int i,baseNote;
|
int i, j, baseNote;
|
||||||
DrMr* drmr = (DrMr*)instance;
|
DrMr* drmr = (DrMr*)instance;
|
||||||
|
|
||||||
baseNote = (int)floorf(*(drmr->baseNote));
|
baseNote = (int)floorf(*(drmr->baseNote));
|
||||||
@ -371,59 +425,82 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
|
|||||||
|
|
||||||
lv2_atom_forge_pop(&drmr->forge, &seq_frame);
|
lv2_atom_forge_pop(&drmr->forge, &seq_frame);
|
||||||
|
|
||||||
for(i = 0;i<n_samples;i++) {
|
|
||||||
drmr->left[i] = 0.0f;
|
|
||||||
drmr->right[i] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&drmr->load_mutex);
|
pthread_mutex_lock(&drmr->load_mutex);
|
||||||
for (i = 0;i < drmr->num_samples;i++) {
|
|
||||||
|
for (i = 0;i < drmr->num_samples;i++)
|
||||||
|
{
|
||||||
int pos,lim;
|
int pos,lim;
|
||||||
drmr_sample* cs = drmr->samples+i;
|
drmr_sample* cs = drmr->samples+i;
|
||||||
if ((cs->active || cs->dataoffset) && (cs->limit > 0)) {
|
|
||||||
|
if ((cs->active || cs->dataoffset) && (cs->limit > 0))
|
||||||
|
{
|
||||||
float coef_right, coef_left;
|
float coef_right, coef_left;
|
||||||
if (i < 32) {
|
if (i < 32)
|
||||||
|
{
|
||||||
float gain = DB_CO(*(drmr->gains[i]));
|
float gain = DB_CO(*(drmr->gains[i]));
|
||||||
float pan_right = ((*drmr->pans[i])+1)/2.0f;
|
float pan_right = ((*drmr->pans[i])+1)/2.0f;
|
||||||
float pan_left = 1-pan_right;
|
float pan_left = 1-pan_right;
|
||||||
coef_right = (pan_right * (DB3SCALE * pan_right + DB3SCALEPO))*gain*cs->velocity;
|
coef_right = (pan_right * (DB3SCALE * pan_right + DB3SCALEPO))*gain*cs->velocity;
|
||||||
coef_left = (pan_left * (DB3SCALE * pan_left + DB3SCALEPO))*gain*cs->velocity;
|
coef_left = (pan_left * (DB3SCALE * pan_left + DB3SCALEPO))*gain*cs->velocity;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
coef_right = coef_left = 1.0f;
|
coef_right = coef_left = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int datastart, dataend;
|
int datastart, dataend;
|
||||||
if (cs->active) {
|
if (cs->active)
|
||||||
|
{
|
||||||
datastart = cs->dataoffset;
|
datastart = cs->dataoffset;
|
||||||
dataend = n_samples;
|
dataend = n_samples;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
datastart = 0;
|
datastart = 0;
|
||||||
dataend = cs->dataoffset;
|
dataend = cs->dataoffset;
|
||||||
}
|
}
|
||||||
cs->dataoffset = 0;
|
cs->dataoffset = 0;
|
||||||
|
|
||||||
if (cs->info->channels == 1) { // play mono sample
|
for( j = 0; j<n_samples; j++)
|
||||||
|
{
|
||||||
|
drmr->left[i][j] = 0.0f;
|
||||||
|
drmr->right[i][j] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs->info->channels == 1)
|
||||||
|
{ // play mono sample
|
||||||
lim = (n_samples < (cs->limit - cs->offset)?n_samples:(cs->limit-cs->offset));
|
lim = (n_samples < (cs->limit - cs->offset)?n_samples:(cs->limit-cs->offset));
|
||||||
for (pos = datastart; pos < lim && pos < dataend; pos++) {
|
|
||||||
drmr->left[pos] += cs->data[cs->offset]*coef_left;
|
for (pos = datastart; pos < lim && pos < dataend; pos++)
|
||||||
drmr->right[pos] += cs->data[cs->offset]*coef_right;
|
{
|
||||||
|
drmr->left[i][pos] += cs->data[cs->offset]*coef_left;
|
||||||
|
drmr->right[i][pos] += cs->data[cs->offset]*coef_right;
|
||||||
cs->offset++;
|
cs->offset++;
|
||||||
}
|
}
|
||||||
} else { // play stereo sample
|
}
|
||||||
|
else
|
||||||
|
{ // play stereo sample
|
||||||
lim = (cs->limit-cs->offset)/cs->info->channels;
|
lim = (cs->limit-cs->offset)/cs->info->channels;
|
||||||
|
|
||||||
if (lim > n_samples) lim = n_samples;
|
if (lim > n_samples) lim = n_samples;
|
||||||
for (pos = datastart; pos < lim && pos < dataend; pos++) {
|
for (pos = datastart; pos < lim && pos < dataend; pos++)
|
||||||
drmr->left[pos] += cs->data[cs->offset++]*coef_left;
|
{
|
||||||
drmr->right[pos] += cs->data[cs->offset++]*coef_right;
|
drmr->left[i][pos] += cs->data[cs->offset++]*coef_left;
|
||||||
|
drmr->right[i][pos] += cs->data[cs->offset++]*coef_right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs->offset >= cs->limit) cs->active = 0;
|
if (cs->offset >= cs->limit) cs->active = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&drmr->load_mutex);
|
pthread_mutex_unlock(&drmr->load_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void cleanup(LV2_Handle instance) {
|
static void cleanup(LV2_Handle instance) {
|
||||||
DrMr* drmr = (DrMr*)instance;
|
DrMr* drmr = (DrMr*)instance;
|
||||||
pthread_cancel(drmr->load_thread);
|
pthread_cancel(drmr->load_thread);
|
||||||
@ -434,6 +511,10 @@ static void cleanup(LV2_Handle instance) {
|
|||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static LV2_State_Status
|
static LV2_State_Status
|
||||||
save_state(LV2_Handle instance,
|
save_state(LV2_Handle instance,
|
||||||
LV2_State_Store_Function store,
|
LV2_State_Store_Function store,
|
||||||
@ -496,6 +577,10 @@ save_state(LV2_Handle instance,
|
|||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static LV2_State_Status
|
static LV2_State_Status
|
||||||
restore_state(LV2_Handle instance,
|
restore_state(LV2_Handle instance,
|
||||||
LV2_State_Retrieve_Function retrieve,
|
LV2_State_Retrieve_Function retrieve,
|
||||||
@ -559,12 +644,20 @@ restore_state(LV2_Handle instance,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const void* extension_data(const char* uri) {
|
static const void* extension_data(const char* uri) {
|
||||||
static const LV2_State_Interface state_iface = { save_state, restore_state };
|
static const LV2_State_Interface state_iface = { save_state, restore_state };
|
||||||
if (!strcmp(uri, LV2_STATE__interface)) return &state_iface;
|
if (!strcmp(uri, LV2_STATE__interface)) return &state_iface;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const LV2_Descriptor descriptor = {
|
static const LV2_Descriptor descriptor = {
|
||||||
DRMR_URI,
|
DRMR_URI,
|
||||||
instantiate,
|
instantiate,
|
||||||
@ -576,6 +669,10 @@ static const LV2_Descriptor descriptor = {
|
|||||||
extension_data
|
extension_data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LV2_SYMBOL_EXPORT
|
LV2_SYMBOL_EXPORT
|
||||||
const LV2_Descriptor*
|
const LV2_Descriptor*
|
||||||
lv2_descriptor(uint32_t index)
|
lv2_descriptor(uint32_t index)
|
||||||
|
70
drmr2.h
70
drmr2.h
@ -72,8 +72,70 @@ typedef struct {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DRMR_CONTROL = 0,
|
DRMR_CONTROL = 0,
|
||||||
DRMR_LEFT,
|
DRMR_LEFT_00,
|
||||||
DRMR_RIGHT,
|
DRMR_RIGHT_00,
|
||||||
|
DRMR_LEFT_01,
|
||||||
|
DRMR_RIGHT_01,
|
||||||
|
DRMR_LEFT_02,
|
||||||
|
DRMR_RIGHT_02,
|
||||||
|
DRMR_LEFT_03,
|
||||||
|
DRMR_RIGHT_03,
|
||||||
|
DRMR_LEFT_04,
|
||||||
|
DRMR_RIGHT_04,
|
||||||
|
DRMR_LEFT_05,
|
||||||
|
DRMR_RIGHT_05,
|
||||||
|
DRMR_LEFT_06,
|
||||||
|
DRMR_RIGHT_06,
|
||||||
|
DRMR_LEFT_07,
|
||||||
|
DRMR_RIGHT_07,
|
||||||
|
DRMR_LEFT_08,
|
||||||
|
DRMR_RIGHT_08,
|
||||||
|
DRMR_LEFT_09,
|
||||||
|
DRMR_RIGHT_09,
|
||||||
|
DRMR_LEFT_10,
|
||||||
|
DRMR_RIGHT_10,
|
||||||
|
DRMR_LEFT_11,
|
||||||
|
DRMR_RIGHT_11,
|
||||||
|
DRMR_LEFT_12,
|
||||||
|
DRMR_RIGHT_12,
|
||||||
|
DRMR_LEFT_13,
|
||||||
|
DRMR_RIGHT_13,
|
||||||
|
DRMR_LEFT_14,
|
||||||
|
DRMR_RIGHT_14,
|
||||||
|
DRMR_LEFT_15,
|
||||||
|
DRMR_RIGHT_15,
|
||||||
|
DRMR_LEFT_16,
|
||||||
|
DRMR_RIGHT_16,
|
||||||
|
DRMR_LEFT_17,
|
||||||
|
DRMR_RIGHT_17,
|
||||||
|
DRMR_LEFT_18,
|
||||||
|
DRMR_RIGHT_18,
|
||||||
|
DRMR_LEFT_19,
|
||||||
|
DRMR_RIGHT_19,
|
||||||
|
DRMR_LEFT_20,
|
||||||
|
DRMR_RIGHT_20,
|
||||||
|
DRMR_LEFT_21,
|
||||||
|
DRMR_RIGHT_21,
|
||||||
|
DRMR_LEFT_22,
|
||||||
|
DRMR_RIGHT_22,
|
||||||
|
DRMR_LEFT_23,
|
||||||
|
DRMR_RIGHT_23,
|
||||||
|
DRMR_LEFT_24,
|
||||||
|
DRMR_RIGHT_24,
|
||||||
|
DRMR_LEFT_25,
|
||||||
|
DRMR_RIGHT_25,
|
||||||
|
DRMR_LEFT_26,
|
||||||
|
DRMR_RIGHT_26,
|
||||||
|
DRMR_LEFT_27,
|
||||||
|
DRMR_RIGHT_27,
|
||||||
|
DRMR_LEFT_28,
|
||||||
|
DRMR_RIGHT_28,
|
||||||
|
DRMR_LEFT_29,
|
||||||
|
DRMR_RIGHT_29,
|
||||||
|
DRMR_LEFT_30,
|
||||||
|
DRMR_RIGHT_30,
|
||||||
|
DRMR_LEFT_31,
|
||||||
|
DRMR_RIGHT_31,
|
||||||
DRMR_BASENOTE,
|
DRMR_BASENOTE,
|
||||||
DRMR_GAIN_ONE,
|
DRMR_GAIN_ONE,
|
||||||
DRMR_GAIN_TWO,
|
DRMR_GAIN_TWO,
|
||||||
@ -162,8 +224,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Ports
|
// Ports
|
||||||
float* left;
|
float** left;
|
||||||
float* right;
|
float** right;
|
||||||
LV2_Atom_Sequence *control_port;
|
LV2_Atom_Sequence *control_port;
|
||||||
LV2_Atom_Sequence *core_event_port;
|
LV2_Atom_Sequence *core_event_port;
|
||||||
|
|
||||||
|
897
drmr2.ttl
897
drmr2.ttl
@ -1,897 +0,0 @@
|
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>.
|
|
||||||
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
|
||||||
@prefix doap: <http://usefulinc.com/ns/doap#>.
|
|
||||||
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
|
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
|
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#>.
|
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
|
|
||||||
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
|
|
||||||
|
|
||||||
<http://github.com/AlkorZ3/drmr2>
|
|
||||||
a lv2:InstrumentPlugin, lv2:Plugin;
|
|
||||||
lv2:binary <drmr2.so>;
|
|
||||||
doap:name "DrMr2 Sampler";
|
|
||||||
doap:maintainer [
|
|
||||||
foaf:name "AlkorZ3" ;
|
|
||||||
foaf:homepage <http://github.com/AlkorZ3/drmr2/wiki> ;
|
|
||||||
foaf:mbox <alkorz3@rx3.net>
|
|
||||||
] ;
|
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
|
||||||
lv2:requiredFeature urid:map ;
|
|
||||||
ui:ui <http://github.com/AlkorZ3/drmr2#ui> ;
|
|
||||||
lv2:extensionData <http://lv2plug.in/ns/ext/state#interface> ;
|
|
||||||
lv2:port [
|
|
||||||
a lv2:InputPort , atom:AtomPort;
|
|
||||||
atom:bufferType atom:Sequence ;
|
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ,
|
|
||||||
<http://lv2plug.in/ns/ext/atom#Resource> ;
|
|
||||||
lv2:index 0;
|
|
||||||
lv2:symbol "control";
|
|
||||||
lv2:name "Control";
|
|
||||||
],
|
|
||||||
[
|
|
||||||
a lv2:OutputPort , atom:AtomPort ;
|
|
||||||
atom:bufferType atom:Sequence ;
|
|
||||||
atom:supports <http://lv2plug.in/ns/ext/atom#Resource> ;
|
|
||||||
lv2:index 68 ;
|
|
||||||
lv2:symbol "core_events" ;
|
|
||||||
lv2:name "Core Events"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
a lv2:AudioPort, lv2:OutputPort;
|
|
||||||
lv2:index 1;
|
|
||||||
lv2:symbol "left";
|
|
||||||
lv2:name "Left";
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:AudioPort, lv2:OutputPort;
|
|
||||||
lv2:index 2;
|
|
||||||
lv2:symbol "right";
|
|
||||||
lv2:name "Right";
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 3;
|
|
||||||
lv2:symbol "base_note";
|
|
||||||
lv2:name "Midi Base Note";
|
|
||||||
lv2:minimum 21;
|
|
||||||
lv2:maximum 107;
|
|
||||||
lv2:default 36;
|
|
||||||
lv2:portProperty lv2:integer;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 4;
|
|
||||||
lv2:symbol "gain_one";
|
|
||||||
lv2:name "Sample One Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 5;
|
|
||||||
lv2:symbol "gain_two";
|
|
||||||
lv2:name "Sample Two Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 6;
|
|
||||||
lv2:symbol "gain_three";
|
|
||||||
lv2:name "Sample Three Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 7;
|
|
||||||
lv2:symbol "gain_four";
|
|
||||||
lv2:name "Sample Four Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 8;
|
|
||||||
lv2:symbol "gain_five";
|
|
||||||
lv2:name "Sample Five Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 9;
|
|
||||||
lv2:symbol "gain_six";
|
|
||||||
lv2:name "Sample Six Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 10;
|
|
||||||
lv2:symbol "gain_seven";
|
|
||||||
lv2:name "Sample Seven Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 11;
|
|
||||||
lv2:symbol "gain_eight";
|
|
||||||
lv2:name "Sample Eight Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 12;
|
|
||||||
lv2:symbol "gain_nine";
|
|
||||||
lv2:name "Sample Nine Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 13;
|
|
||||||
lv2:symbol "gain_ten";
|
|
||||||
lv2:name "Sample Ten Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 14;
|
|
||||||
lv2:symbol "gain_eleven";
|
|
||||||
lv2:name "Sample Eleven Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 15;
|
|
||||||
lv2:symbol "gain_twelve";
|
|
||||||
lv2:name "Sample Twelve Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 16;
|
|
||||||
lv2:symbol "gain_thirteen";
|
|
||||||
lv2:name "Sample Thirteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 17;
|
|
||||||
lv2:symbol "gain_fourteen";
|
|
||||||
lv2:name "Sample Fourteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 18;
|
|
||||||
lv2:symbol "gain_fifteen";
|
|
||||||
lv2:name "Sample Fifteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 19;
|
|
||||||
lv2:symbol "gain_sixteen";
|
|
||||||
lv2:name "Sample Sixteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 20;
|
|
||||||
lv2:symbol "gain_seventeen";
|
|
||||||
lv2:name "Sample Seventeen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 21;
|
|
||||||
lv2:symbol "gain_eighteen";
|
|
||||||
lv2:name "Sample Eighteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 22;
|
|
||||||
lv2:symbol "gain_nineteen";
|
|
||||||
lv2:name "Sample Nineteen Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 23;
|
|
||||||
lv2:symbol "gain_twenty";
|
|
||||||
lv2:name "Sample Twenty Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 24;
|
|
||||||
lv2:symbol "gain_twentyone";
|
|
||||||
lv2:name "Sample Twenty One Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 25;
|
|
||||||
lv2:symbol "gain_twentytwo";
|
|
||||||
lv2:name "Sample Twenty Two Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 26;
|
|
||||||
lv2:symbol "gain_twentythree";
|
|
||||||
lv2:name "Sample Twenty Three Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 27;
|
|
||||||
lv2:symbol "gain_twentyfour";
|
|
||||||
lv2:name "Sample Twenty Four Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 28;
|
|
||||||
lv2:symbol "gain_twentyfive";
|
|
||||||
lv2:name "Sample Twenty Five Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 29;
|
|
||||||
lv2:symbol "gain_twentysix";
|
|
||||||
lv2:name "Sample Twenty Six Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 30;
|
|
||||||
lv2:symbol "gain_twentyseven";
|
|
||||||
lv2:name "Sample Twenty Seven Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 31;
|
|
||||||
lv2:symbol "gain_twentyeight";
|
|
||||||
lv2:name "Sample Twenty Eight Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 32;
|
|
||||||
lv2:symbol "gain_twentynine";
|
|
||||||
lv2:name "Sample Twenty Nine Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 33;
|
|
||||||
lv2:symbol "gain_thirty";
|
|
||||||
lv2:name "Sample Thirty Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 34;
|
|
||||||
lv2:symbol "gain_thirtyone";
|
|
||||||
lv2:name "Sample Thirty One Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 35;
|
|
||||||
lv2:symbol "gain_thirtytwo";
|
|
||||||
lv2:name "Sample Thirty Two Gain";
|
|
||||||
lv2:minimum -60.0;
|
|
||||||
lv2:maximum 6.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -60.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 36;
|
|
||||||
lv2:symbol "pan_one";
|
|
||||||
lv2:name "Sample One Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 37;
|
|
||||||
lv2:symbol "pan_two";
|
|
||||||
lv2:name "Sample Two Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 38;
|
|
||||||
lv2:symbol "pan_three";
|
|
||||||
lv2:name "Sample Three Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 39;
|
|
||||||
lv2:symbol "pan_four";
|
|
||||||
lv2:name "Sample Four Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 40;
|
|
||||||
lv2:symbol "pan_five";
|
|
||||||
lv2:name "Sample Five Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 41;
|
|
||||||
lv2:symbol "pan_six";
|
|
||||||
lv2:name "Sample Six Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 42;
|
|
||||||
lv2:symbol "pan_seven";
|
|
||||||
lv2:name "Sample Seven Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 43;
|
|
||||||
lv2:symbol "pan_eight";
|
|
||||||
lv2:name "Sample Eight Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 44;
|
|
||||||
lv2:symbol "pan_nine";
|
|
||||||
lv2:name "Sample Nine Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 45;
|
|
||||||
lv2:symbol "pan_ten";
|
|
||||||
lv2:name "Sample Ten Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 46;
|
|
||||||
lv2:symbol "pan_eleven";
|
|
||||||
lv2:name "Sample Eleven Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 47;
|
|
||||||
lv2:symbol "pan_twelve";
|
|
||||||
lv2:name "Sample Twelve Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 48;
|
|
||||||
lv2:symbol "pan_thirteen";
|
|
||||||
lv2:name "Sample Thirteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 49;
|
|
||||||
lv2:symbol "pan_fourteen";
|
|
||||||
lv2:name "Sample Fourteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 50;
|
|
||||||
lv2:symbol "pan_fifteen";
|
|
||||||
lv2:name "Sample Fifteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 51;
|
|
||||||
lv2:symbol "pan_sixteen";
|
|
||||||
lv2:name "Sample Sixteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 52;
|
|
||||||
lv2:symbol "pan_seventeen";
|
|
||||||
lv2:name "Sample Seventeen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 53;
|
|
||||||
lv2:symbol "pan_eighteen";
|
|
||||||
lv2:name "Sample Eighteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 54;
|
|
||||||
lv2:symbol "pan_nineteen";
|
|
||||||
lv2:name "Sample Nineteen Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 55;
|
|
||||||
lv2:symbol "pan_twenty";
|
|
||||||
lv2:name "Sample Twenty Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 56;
|
|
||||||
lv2:symbol "pan_twentyone";
|
|
||||||
lv2:name "Sample Twenty One Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 57;
|
|
||||||
lv2:symbol "pan_twentytwo";
|
|
||||||
lv2:name "Sample Twenty Two Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 58;
|
|
||||||
lv2:symbol "pan_twentythree";
|
|
||||||
lv2:name "Sample Twenty Three Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 59;
|
|
||||||
lv2:symbol "pan_twentyfour";
|
|
||||||
lv2:name "Sample Twenty Four Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 60;
|
|
||||||
lv2:symbol "pan_twentyfive";
|
|
||||||
lv2:name "Sample Twenty Five Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 61;
|
|
||||||
lv2:symbol "pan_twentysix";
|
|
||||||
lv2:name "Sample Twenty Six Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 62;
|
|
||||||
lv2:symbol "pan_twentyseven";
|
|
||||||
lv2:name "Sample Twenty Seven Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 63;
|
|
||||||
lv2:symbol "pan_twentyeight";
|
|
||||||
lv2:name "Sample Twenty Eight Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 64;
|
|
||||||
lv2:symbol "pan_twentynine";
|
|
||||||
lv2:name "Sample Twenty Nine Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 65;
|
|
||||||
lv2:symbol "pan_thirty";
|
|
||||||
lv2:name "Sample Thirty Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 66;
|
|
||||||
lv2:symbol "pan_thirtyone";
|
|
||||||
lv2:name "Sample Thirty One Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
lv2:scalePoint [
|
|
||||||
rdfs:label "-inf" ;
|
|
||||||
rdf:value -1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
[
|
|
||||||
a lv2:ControlPort, lv2:InputPort;
|
|
||||||
lv2:index 67;
|
|
||||||
lv2:symbol "pan_thirtytwo";
|
|
||||||
lv2:name "Sample Thirty Two Pan";
|
|
||||||
lv2:minimum -1.0;
|
|
||||||
lv2:maximum 1.0;
|
|
||||||
lv2:default 0.0;
|
|
||||||
].
|
|
||||||
|
|
||||||
<http://github.com/AlkorZ3/drmr2#ui>
|
|
||||||
a ui:GtkUI ;
|
|
||||||
ui:binary <drmr2_ui.so> .
|
|
Loading…
Reference in New Issue
Block a user