Browse Source

Update zynaddsubfx

tags/1.9.7
falkTX 10 years ago
parent
commit
60fe7319c6
100 changed files with 2806 additions and 1461 deletions
  1. +1
    -0
      source/native-plugins/zynaddsubfx-src.cpp
  2. +2
    -0
      source/native-plugins/zynaddsubfx-ui.cpp
  3. +285
    -0
      source/native-plugins/zynaddsubfx/Containers/NotePool.cpp
  4. +113
    -0
      source/native-plugins/zynaddsubfx/Containers/NotePool.h
  5. +1
    -1
      source/native-plugins/zynaddsubfx/DSP/FormantFilter.cpp
  6. +24
    -5
      source/native-plugins/zynaddsubfx/Effects/EffectMgr.cpp
  7. +0
    -1
      source/native-plugins/zynaddsubfx/Effects/EffectMgr.h
  8. +7
    -5
      source/native-plugins/zynaddsubfx/Misc/Allocator.h
  9. +4
    -4
      source/native-plugins/zynaddsubfx/Misc/Config.cpp
  10. +24
    -18
      source/native-plugins/zynaddsubfx/Misc/Master.cpp
  11. +6
    -2
      source/native-plugins/zynaddsubfx/Misc/Master.h
  12. +1
    -1
      source/native-plugins/zynaddsubfx/Misc/Microtonal.cpp
  13. +76
    -23
      source/native-plugins/zynaddsubfx/Misc/MiddleWare.cpp
  14. +4
    -3
      source/native-plugins/zynaddsubfx/Misc/MiddleWare.h
  15. +203
    -471
      source/native-plugins/zynaddsubfx/Misc/Part.cpp
  16. +22
    -19
      source/native-plugins/zynaddsubfx/Misc/Part.h
  17. +4
    -12
      source/native-plugins/zynaddsubfx/Misc/PresetExtractor.cpp
  18. +42
    -0
      source/native-plugins/zynaddsubfx/Misc/Time.h
  19. +2
    -2
      source/native-plugins/zynaddsubfx/Misc/Util.h
  20. +1
    -1
      source/native-plugins/zynaddsubfx/Misc/WavFile.cpp
  21. +1
    -1
      source/native-plugins/zynaddsubfx/Misc/WavFile.h
  22. +1
    -1
      source/native-plugins/zynaddsubfx/Nio/WavEngine.cpp
  23. +1
    -1
      source/native-plugins/zynaddsubfx/Nio/WavEngine.h
  24. +33
    -50
      source/native-plugins/zynaddsubfx/Params/ADnoteParameters.cpp
  25. +2
    -4
      source/native-plugins/zynaddsubfx/Params/ADnoteParameters.h
  26. +8
    -1
      source/native-plugins/zynaddsubfx/Params/EnvelopeParams.cpp
  27. +5
    -4
      source/native-plugins/zynaddsubfx/Params/FilterParams.cpp
  28. +0
    -4
      source/native-plugins/zynaddsubfx/Params/LFOParams.cpp
  29. +8
    -1
      source/native-plugins/zynaddsubfx/Params/LFOParams.h
  30. +8
    -7
      source/native-plugins/zynaddsubfx/Params/PADnoteParameters.cpp
  31. +4
    -2
      source/native-plugins/zynaddsubfx/Params/SUBnoteParameters.cpp
  32. +70
    -30
      source/native-plugins/zynaddsubfx/Synth/ADnote.cpp
  33. +7
    -3
      source/native-plugins/zynaddsubfx/Synth/ADnote.h
  34. +58
    -72
      source/native-plugins/zynaddsubfx/Synth/LFO.cpp
  35. +25
    -12
      source/native-plugins/zynaddsubfx/Synth/LFO.h
  36. +112
    -71
      source/native-plugins/zynaddsubfx/Synth/OscilGen.cpp
  37. +1
    -1
      source/native-plugins/zynaddsubfx/Synth/OscilGen.h
  38. +13
    -6
      source/native-plugins/zynaddsubfx/Synth/PADnote.cpp
  39. +2
    -1
      source/native-plugins/zynaddsubfx/Synth/PADnote.h
  40. +1
    -1
      source/native-plugins/zynaddsubfx/Synth/Resonance.cpp
  41. +9
    -1
      source/native-plugins/zynaddsubfx/Synth/SUBnote.cpp
  42. +3
    -1
      source/native-plugins/zynaddsubfx/Synth/SUBnote.h
  43. +3
    -3
      source/native-plugins/zynaddsubfx/Synth/SynthNote.cpp
  44. +10
    -3
      source/native-plugins/zynaddsubfx/Synth/SynthNote.h
  45. +120
    -59
      source/native-plugins/zynaddsubfx/UI/ADnoteUI.fl
  46. +4
    -2
      source/native-plugins/zynaddsubfx/UI/BankUI.fl
  47. +2
    -2
      source/native-plugins/zynaddsubfx/UI/BankView.cpp
  48. +5
    -3
      source/native-plugins/zynaddsubfx/UI/ConfigUI.fl
  49. +5
    -1
      source/native-plugins/zynaddsubfx/UI/Connection.cpp
  50. +1
    -1
      source/native-plugins/zynaddsubfx/UI/ConnectionDummy.cpp
  51. +4
    -1
      source/native-plugins/zynaddsubfx/UI/EffUI.fl
  52. +117
    -47
      source/native-plugins/zynaddsubfx/UI/EnvelopeFreeEdit.cpp
  53. +94
    -106
      source/native-plugins/zynaddsubfx/UI/EnvelopeUI.fl
  54. +3
    -0
      source/native-plugins/zynaddsubfx/UI/FilterUI.fl
  55. +1
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_DialF.cpp
  56. +3
    -2
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_ListView.cpp
  57. +1
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Numeric_Input.cpp
  58. +5
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Pane.H
  59. +29
    -2
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Pane.cpp
  60. +3
    -2
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Slider.H
  61. +68
    -3
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Slider.cpp
  62. +21
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_TSlider.H
  63. +65
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_TSlider.cpp
  64. +16
    -10
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_VSlider.H
  65. +40
    -61
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_VSlider.cpp
  66. +1
    -2
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Widget.H
  67. +1
    -0
      source/native-plugins/zynaddsubfx/UI/Fl_Osc_Widget.cpp
  68. +3
    -0
      source/native-plugins/zynaddsubfx/UI/LFOUI.fl
  69. +71
    -8
      source/native-plugins/zynaddsubfx/UI/MasterUI.fl
  70. +1
    -2
      source/native-plugins/zynaddsubfx/UI/MicrotonalUI.fl
  71. +9
    -9
      source/native-plugins/zynaddsubfx/UI/NioUI.cpp
  72. +2
    -2
      source/native-plugins/zynaddsubfx/UI/Osc_DataModel.h
  73. +2
    -2
      source/native-plugins/zynaddsubfx/UI/Osc_IntModel.h
  74. +2
    -2
      source/native-plugins/zynaddsubfx/UI/Osc_ListModel.h
  75. +2
    -2
      source/native-plugins/zynaddsubfx/UI/Osc_SimpleListModel.h
  76. +10
    -10
      source/native-plugins/zynaddsubfx/UI/OscilGenUI.fl
  77. +1
    -2
      source/native-plugins/zynaddsubfx/UI/PADnoteUI.fl
  78. +7
    -11
      source/native-plugins/zynaddsubfx/UI/PartUI.fl
  79. +2
    -2
      source/native-plugins/zynaddsubfx/UI/PresetsUI.fl
  80. +1
    -1
      source/native-plugins/zynaddsubfx/UI/SUBnoteUI.fl
  81. +75
    -0
      source/native-plugins/zynaddsubfx/UI/TipWin.cpp
  82. +25
    -0
      source/native-plugins/zynaddsubfx/UI/TipWin.h
  83. +71
    -108
      source/native-plugins/zynaddsubfx/UI/WidgetPDial.cpp
  84. +10
    -0
      source/native-plugins/zynaddsubfx/UI/WidgetPDial.h
  85. +1
    -0
      source/native-plugins/zynaddsubfx/UI/guimain.cpp
  86. +5
    -2
      source/native-plugins/zynaddsubfx/globals.cpp
  87. +14
    -4
      source/native-plugins/zynaddsubfx/globals.h
  88. +25
    -4
      source/native-plugins/zynaddsubfx/main.cpp
  89. +2
    -2
      source/native-plugins/zynaddsubfx/rtosc/cpp/midimapper.cpp
  90. +1
    -1
      source/native-plugins/zynaddsubfx/rtosc/cpp/miditable.cpp
  91. +184
    -57
      source/native-plugins/zynaddsubfx/rtosc/cpp/ports.cpp
  92. +12
    -4
      source/native-plugins/zynaddsubfx/rtosc/cpp/subtree-serialize.cpp
  93. +1
    -4
      source/native-plugins/zynaddsubfx/rtosc/cpp/thread-link.cpp
  94. +2
    -2
      source/native-plugins/zynaddsubfx/rtosc/cpp/undo-history.cpp
  95. +211
    -1
      source/native-plugins/zynaddsubfx/rtosc/dispatch.c
  96. +4
    -2
      source/native-plugins/zynaddsubfx/rtosc/miditable.h
  97. +29
    -5
      source/native-plugins/zynaddsubfx/rtosc/port-sugar.h
  98. +8
    -1
      source/native-plugins/zynaddsubfx/rtosc/ports.h
  99. +166
    -58
      source/native-plugins/zynaddsubfx/rtosc/rtosc.c
  100. +31
    -0
      source/native-plugins/zynaddsubfx/rtosc/rtosc.h

+ 1
- 0
source/native-plugins/zynaddsubfx-src.cpp View File

@@ -68,6 +68,7 @@ extern "C" {
#include "zynaddsubfx/rtosc/cpp/undo-history.cpp" #include "zynaddsubfx/rtosc/cpp/undo-history.cpp"


// zynaddsubfx includes // zynaddsubfx includes
#include "zynaddsubfx/Containers/NotePool.cpp"
#include "zynaddsubfx/DSP/AnalogFilter.cpp" #include "zynaddsubfx/DSP/AnalogFilter.cpp"
#include "zynaddsubfx/DSP/FFTwrapper.cpp" #include "zynaddsubfx/DSP/FFTwrapper.cpp"
#include "zynaddsubfx/DSP/Filter.cpp" #include "zynaddsubfx/DSP/Filter.cpp"


+ 2
- 0
source/native-plugins/zynaddsubfx-ui.cpp View File

@@ -91,6 +91,7 @@ extern "C" {
#include "zynaddsubfx/UI/Fl_Osc_Pane.cpp" #include "zynaddsubfx/UI/Fl_Osc_Pane.cpp"
#include "zynaddsubfx/UI/Fl_Osc_Roller.cpp" #include "zynaddsubfx/UI/Fl_Osc_Roller.cpp"
#include "zynaddsubfx/UI/Fl_Osc_Slider.cpp" #include "zynaddsubfx/UI/Fl_Osc_Slider.cpp"
#include "zynaddsubfx/UI/Fl_Osc_TSlider.cpp"
#include "zynaddsubfx/UI/Fl_Osc_Value.cpp" #include "zynaddsubfx/UI/Fl_Osc_Value.cpp"
#include "zynaddsubfx/UI/Fl_Osc_VSlider.cpp" #include "zynaddsubfx/UI/Fl_Osc_VSlider.cpp"
#include "zynaddsubfx/UI/Fl_Osc_Widget.cpp" #include "zynaddsubfx/UI/Fl_Osc_Widget.cpp"
@@ -106,6 +107,7 @@ extern "C" {
#include "zynaddsubfx/UI/PresetsUI.cpp" #include "zynaddsubfx/UI/PresetsUI.cpp"
#include "zynaddsubfx/UI/ResonanceUI.cpp" #include "zynaddsubfx/UI/ResonanceUI.cpp"
#include "zynaddsubfx/UI/SUBnoteUI.cpp" #include "zynaddsubfx/UI/SUBnoteUI.cpp"
#include "zynaddsubfx/UI/TipWin.cpp"
#include "zynaddsubfx/UI/VirKeyboard.cpp" #include "zynaddsubfx/UI/VirKeyboard.cpp"
#include "zynaddsubfx/UI/guimain.cpp" #include "zynaddsubfx/UI/guimain.cpp"




+ 285
- 0
source/native-plugins/zynaddsubfx/Containers/NotePool.cpp View File

@@ -0,0 +1,285 @@
#include "NotePool.h"
//XXX eliminate dependence on Part.h
#include "../Misc/Part.h"
#include "../Misc/Allocator.h"
#include "../Synth/SynthNote.h"
#include <cstring>
#include <cassert>

NotePool::NotePool(void)
:needs_cleaning(0)
{
memset(ndesc, 0, sizeof(ndesc));
memset(sdesc, 0, sizeof(ndesc));
}
NotePool::activeNotesIter NotePool::activeNotes(NoteDescriptor &n)
{
const int off_d1 = &n-ndesc;
int off_d2 = 0;
assert(off_d1 <= POLYPHONY);
for(int i=0; i<off_d1; ++i)
off_d2 += ndesc[i].size;
return NotePool::activeNotesIter{sdesc+off_d2,sdesc+off_d2+n.size};
}

bool NotePool::NoteDescriptor::operator==(NoteDescriptor nd)
{
return age == nd.age && note == nd.note && sendto == nd.sendto && size == nd.size && status == nd.status;
}

//return either the first unused descriptor or the last valid descriptor which
//matches note/sendto
static int getMergeableDescriptor(uint8_t note, uint8_t sendto, bool legato,
NotePool::NoteDescriptor *ndesc)
{
int desc_id = 0;
for(int i=0; i<POLYPHONY; ++i, ++desc_id)
if(ndesc[desc_id].status == Part::KEY_OFF)
break;

//Out of free descriptors
if(ndesc[desc_id].status != Part::KEY_OFF)
return -1;

if(desc_id != 0) {
auto &nd = ndesc[desc_id-1];
if(nd.age == 0 && nd.note == note && nd.sendto == sendto
&& nd.status == Part::KEY_PLAYING && nd.legatoMirror == legato)
return desc_id-1;
}
return desc_id;
}
NotePool::activeDescIter NotePool::activeDesc(void)
{
cleanup();
return activeDescIter{*this};
}

NotePool::constActiveDescIter NotePool::activeDesc(void) const
{
const_cast<NotePool*>(this)->cleanup();
return constActiveDescIter{*this};
}

void NotePool::insertNote(uint8_t note, uint8_t sendto, SynthDescriptor desc, bool legato)
{
//Get first free note descriptor
int desc_id = getMergeableDescriptor(note, sendto, legato, ndesc);
assert(desc_id != -1);

ndesc[desc_id].note = note;
ndesc[desc_id].sendto = sendto;
ndesc[desc_id].size += 1;
ndesc[desc_id].status = Part::KEY_PLAYING;
ndesc[desc_id].legatoMirror = legato;

//Get first free synth descriptor
int sdesc_id = 0;
while(sdesc[sdesc_id].note)
sdesc_id++;
sdesc[sdesc_id] = desc;
};

void NotePool::upgradeToLegato(void)
{
for(auto &d:activeDesc())
if(d.status == Part::KEY_PLAYING)
for(auto &s:activeNotes(d))
insertLegatoNote(d.note, d.sendto, s);
}

void NotePool::insertLegatoNote(uint8_t note, uint8_t sendto, SynthDescriptor desc)
{
assert(desc.note);
desc.note = desc.note->cloneLegato();
insertNote(note, sendto, desc, true);
};

//There should only be one pair of notes which are still playing
void NotePool::applyLegato(LegatoParams &par)
{
for(auto &desc:activeDesc()) {
desc.note = par.midinote;
for(auto &synth:activeNotes(desc))
synth.note->legatonote(par);
}
};

//Note that isn't KEY_PLAYING or KEY_RELASED_AND_SUSTAINING
bool NotePool::existsRunningNote(void) const
{
//printf("runing note # =%d\n", getRunningNotes());
return getRunningNotes();
}

int NotePool::getRunningNotes(void) const
{
bool running[256] = {0};
for(auto &desc:activeDesc()) {
//printf("note!(%d)\n", desc.note);
if(desc.status == Part::KEY_PLAYING)
running[desc.note] = true;
}

int running_count = 0;
for(int i=0; i<256; ++i)
running_count += running[i];

return running_count;
}
int NotePool::enforceKeyLimit(int limit) const
{
//{
//int oldestnotepos = -1;
//if(notecount > keylimit) //find out the oldest note
// for(int i = 0; i < POLYPHONY; ++i) {
// int maxtime = 0;
// if(((partnote[i].status == KEY_PLAYING) || (partnote[i].status == KEY_RELEASED_AND_SUSTAINED)) && (partnote[i].time > maxtime)) {
// maxtime = partnote[i].time;
// oldestnotepos = i;
// }
// }
//if(oldestnotepos != -1)
// ReleaseNotePos(oldestnotepos);
//}
printf("Unimplemented enforceKeyLimit()\n");
return -1;
}

void NotePool::releasePlayingNotes(void)
{
for(auto &d:activeDesc()) {
if(d.status == Part::KEY_PLAYING) {
d.status = Part::KEY_RELEASED;
for(auto s:activeNotes(d))
s.note->releasekey();
}
}
}

void NotePool::release(NoteDescriptor &d)
{
d.status = Part::KEY_RELEASED;
for(auto s:activeNotes(d))
s.note->releasekey();
}

void NotePool::killAllNotes(void)
{
for(auto &d:activeDesc())
kill(d);
}

void NotePool::killNote(uint8_t note)
{
for(auto &d:activeDesc()) {
if(d.note == note)
kill(d);
}
}

void NotePool::kill(NoteDescriptor &d)
{
d.status = Part::KEY_OFF;
for(auto &s:activeNotes(d))
kill(s);
}

void NotePool::kill(SynthDescriptor &s)
{
//printf("Kill synth...\n");
s.note->memory.dealloc(s.note);
needs_cleaning = true;
}

const char *getStatus(int status_bits)
{
switch(status_bits)
{
case 0: return "OFF ";
case 1: return "PLAY";
case 2: return "SUST";
case 3: return "RELA";
default: return "INVD";
}
}

void NotePool::cleanup(void)
{
if(!needs_cleaning)
return;
needs_cleaning = false;
int new_length[POLYPHONY] = {0};
int cur_length[POLYPHONY] = {0};
//printf("Cleanup Start\n");
//dump();

//Identify the current length of all segments
//and the lengths discarding invalid entries

int last_valid_desc = 0;
for(int i=0; i<POLYPHONY; ++i)
if(ndesc[i].status != Part::KEY_OFF)
last_valid_desc = i;

//Find the real numbers of allocated notes
{
int cum_old = 0;

for(int i=0; i<=last_valid_desc; ++i) {
cur_length[i] = ndesc[i].size;
for(int j=0; j<ndesc[i].size; ++j)
new_length[i] += (bool)sdesc[cum_old++].note;
}
}


//Move the note descriptors
{
int cum_new = 0;
for(int i=0; i<=last_valid_desc; ++i) {
ndesc[i].size = new_length[i];
if(new_length[i] != 0)
ndesc[cum_new++] = ndesc[i];
else
ndesc[i].status = Part::KEY_OFF;
}
memset(ndesc+cum_new, 0, sizeof(*ndesc)*(POLYPHONY-cum_new));
}

//Move the synth descriptors
{
int total_notes=0;
for(int i=0; i<=last_valid_desc; ++i)
total_notes+=cur_length[i];

int cum_new = 0;
for(int i=0; i<total_notes; ++i)
if(sdesc[i].note)
sdesc[cum_new++] = sdesc[i];
memset(sdesc+cum_new, 0, sizeof(*sdesc)*(POLYPHONY*EXPECTED_USAGE-cum_new));
}
//printf("Cleanup Done\n");
//dump();
}

void NotePool::dump(void)
{
printf("NotePool::dump<\n");
const char *format =
" Note %d:%d age(%d) note(%d) sendto(%d) status(%s) legato(%d) type(%d) kit(%d) ptr(%p)\n";
int note_id=0;
int descriptor_id=0;
for(auto &d:activeDesc()) {
descriptor_id += 1;
for(auto &s:activeNotes(d)) {
note_id += 1;
printf(format,
note_id, descriptor_id,
d.age, d.note, d.sendto,
getStatus(d.status), d.legatoMirror, s.type, s.kit, s.note);
}
}
printf(">NotePool::dump\n");
}

+ 113
- 0
source/native-plugins/zynaddsubfx/Containers/NotePool.h View File

@@ -0,0 +1,113 @@
#pragma once
#include <stdint.h>
#include <functional>
#include "../globals.h"

//Expected upper bound of synths given that max polyphony is hit
#define EXPECTED_USAGE 3

struct LegatoParams;
class NotePool
{
public:
typedef uint8_t note_t;
//Currently this wastes a ton of bits due ot the legatoMirror flag
struct NoteDescriptor {
//acceptable overlap after 2 minutes
//run time at 48kHz 8 samples per buffer
//19 bit minimum
uint32_t age;
uint8_t note;
uint8_t sendto;
//max of 16 kit elms and 3 kit items per
uint8_t size;
uint8_t status;
bool legatoMirror;
bool operator==(NoteDescriptor);
};

//To be pedantic this wastes 2 or 6 bytes per descriptor
//depending on 32bit/64bit alignment rules
struct SynthDescriptor {
SynthNote *note;
uint8_t type;
uint8_t kit;
};


//Pool of notes
NoteDescriptor ndesc[POLYPHONY];
SynthDescriptor sdesc[POLYPHONY*EXPECTED_USAGE];
bool needs_cleaning;


//Iterators
struct activeNotesIter {
SynthDescriptor *begin() {return _b;};
SynthDescriptor *end() {return _e;};
SynthDescriptor *_b;
SynthDescriptor *_e;
};

struct activeDescIter {
activeDescIter(NotePool &_np):np(_np)
{
int off=0;
for(int i=0; i<POLYPHONY; ++i, ++off)
if(np.ndesc[i].status == 0)
break;
_end = np.ndesc+off;
}
NoteDescriptor *begin() {return np.ndesc;};
NoteDescriptor *end() { return _end; };
NoteDescriptor *_end;
NotePool &np;
};

struct constActiveDescIter {
constActiveDescIter(const NotePool &_np):np(_np)
{
int off=0;
for(int i=0; i<POLYPHONY; ++i, ++off)
if(np.ndesc[i].status == 0)
break;
_end = np.ndesc+off;
}
const NoteDescriptor *begin() const {return np.ndesc;};
const NoteDescriptor *end() const { return _end; };
const NoteDescriptor *_end;
const NotePool &np;
};

activeNotesIter activeNotes(NoteDescriptor &n);

activeDescIter activeDesc(void);
constActiveDescIter activeDesc(void) const;

NotePool(void);

//Operations
void insertNote(uint8_t note, uint8_t sendto, SynthDescriptor desc, bool legato=false);
void insertLegatoNote(uint8_t note, uint8_t sendto, SynthDescriptor desc);

void upgradeToLegato(void);
void applyLegato(LegatoParams &par);

//Note that isn't KEY_PLAYING or KEY_RELASED_AND_SUSTAINING
bool existsRunningNote(void) const;
int getRunningNotes(void) const;
int enforceKeyLimit(int limit) const;

void releasePlayingNotes(void);
void releaseNote(note_t note);
void release(NoteDescriptor &d);

void killAllNotes(void);
void killNote(note_t note);
void kill(NoteDescriptor &d);
void kill(SynthDescriptor &s);

void cleanup(void);

void dump(void);
};

+ 1
- 1
source/native-plugins/zynaddsubfx/DSP/FormantFilter.cpp View File

@@ -71,7 +71,7 @@ FormantFilter::FormantFilter(FilterParams *pars, Allocator *alloc, unsigned int
outgain = dB2rap(pars->getgain()); outgain = dB2rap(pars->getgain());


oldinput = -1.0f; oldinput = -1.0f;
Qfactor = 1.0f;
Qfactor = pars->getq();
oldQfactor = Qfactor; oldQfactor = Qfactor;
firsttime = 1; firsttime = 1;
} }


+ 24
- 5
source/native-plugins/zynaddsubfx/Effects/EffectMgr.cpp View File

@@ -45,7 +45,8 @@ static const rtosc::Ports local_ports = {
rSelf(EffectMgr), rSelf(EffectMgr),
rPaste, rPaste,
rRecurp(filterpars, "Filter Parameter for Dynamic Filter"), rRecurp(filterpars, "Filter Parameter for Dynamic Filter"),
{"parameter#128::i", rProp(alias) rDoc("Parameter Accessor"), NULL,
{"parameter#128::i:T:F", rProp(parameter) rProp(alias) rDoc("Parameter Accessor"),
NULL,
[](const char *msg, rtosc::RtData &d) [](const char *msg, rtosc::RtData &d)
{ {
EffectMgr *eff = (EffectMgr*)d.obj; EffectMgr *eff = (EffectMgr*)d.obj;
@@ -54,20 +55,37 @@ static const rtosc::Ports local_ports = {


if(!rtosc_narguments(msg)) if(!rtosc_narguments(msg))
d.reply(d.loc, "i", eff->geteffectparrt(atoi(mm))); d.reply(d.loc, "i", eff->geteffectparrt(atoi(mm)));
else {
else if(rtosc_type(msg, 0) == 'i'){
eff->seteffectparrt(atoi(mm), rtosc_argument(msg, 0).i); eff->seteffectparrt(atoi(mm), rtosc_argument(msg, 0).i);
d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm))); d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
} else if(rtosc_type(msg, 0) == 'T'){
eff->seteffectparrt(atoi(mm), 127);
d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
} else if(rtosc_type(msg, 0) == 'F'){
eff->seteffectparrt(atoi(mm), 0);
d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
} }
}}, }},
{"preset::i", rProp(alias) rDoc("Effect Preset Selector"), NULL,
{"preset::i", rProp(parameter) rProp(alias) rDoc("Effect Preset Selector"), NULL,
[](const char *msg, rtosc::RtData &d) [](const char *msg, rtosc::RtData &d)
{ {
char loc[1024];
EffectMgr *eff = (EffectMgr*)d.obj; EffectMgr *eff = (EffectMgr*)d.obj;
if(!rtosc_narguments(msg)) if(!rtosc_narguments(msg))
d.reply(d.loc, "i", eff->getpreset()); d.reply(d.loc, "i", eff->getpreset());
else { else {
eff->changepresetrt(rtosc_argument(msg, 0).i); eff->changepresetrt(rtosc_argument(msg, 0).i);
d.broadcast(d.loc, "i", eff->getpreset()); d.broadcast(d.loc, "i", eff->getpreset());

//update parameters as well
strncpy(loc, d.loc, 1024);
char *tail = rindex(loc, '/');
if(!tail)
return;
for(int i=0;i<128;++i) {
sprintf(tail+1, "parameter%d", i);
d.broadcast(loc, "i", eff->geteffectparrt(i));
}
} }
}}, }},
{"eq-coeffs:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL, {"eq-coeffs:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL,
@@ -84,7 +102,8 @@ static const rtosc::Ports local_ports = {
eq->getFilter(a,b); eq->getFilter(a,b);
d.reply(d.loc, "bb", sizeof(a), a, sizeof(b), b); d.reply(d.loc, "bb", sizeof(a), a, sizeof(b), b);
}}, }},
{"efftype::i", rDoc("Get Effect Type"), NULL, [](const char *m, rtosc::RtData &d)
{"efftype::i", rProp(parameter) rDoc("Get Effect Type"), NULL,
[](const char *m, rtosc::RtData &d)
{ {
EffectMgr *eff = (EffectMgr*)d.obj; EffectMgr *eff = (EffectMgr*)d.obj;
if(rtosc_narguments(m)) { if(rtosc_narguments(m)) {
@@ -385,7 +404,7 @@ void EffectMgr::paste(EffectMgr &e)
changeeffectrt(e.nefx, true); changeeffectrt(e.nefx, true);
changepresetrt(e.preset, true); changepresetrt(e.preset, true);
for(int i=0;i<128;++i) for(int i=0;i<128;++i)
seteffectparrt(e.settings[i], i);
seteffectparrt(i, e.settings[i]);
} }


void EffectMgr::add2XML(XMLwrapper *xml) void EffectMgr::add2XML(XMLwrapper *xml)


+ 0
- 1
source/native-plugins/zynaddsubfx/Effects/EffectMgr.h View File

@@ -80,7 +80,6 @@ class EffectMgr:public Presets
private: private:


//Parameters Prior to initialization //Parameters Prior to initialization
char effect_id;
char preset; char preset;
char settings[128]; char settings[128];




+ 7
- 5
source/native-plugins/zynaddsubfx/Misc/Allocator.h View File

@@ -86,12 +86,14 @@ class Allocator
//! the allocator for normal use //! the allocator for normal use
class AllocatorClass : public Allocator class AllocatorClass : public Allocator
{ {
void *alloc_mem(size_t mem_size);
void dealloc_mem(void *memory);
void addMemory(void *, size_t mem_size);
bool lowMemory(unsigned n, size_t chunk_size) const;
using Allocator::Allocator;
public:
void *alloc_mem(size_t mem_size);
void dealloc_mem(void *memory);
void addMemory(void *, size_t mem_size);
bool lowMemory(unsigned n, size_t chunk_size) const;
using Allocator::Allocator;
}; };
typedef AllocatorClass Alloc;


//! the dummy allocator, which does not allow any allocation //! the dummy allocator, which does not allow any allocation
class DummyAllocator : public Allocator class DummyAllocator : public Allocator


+ 4
- 4
source/native-plugins/zynaddsubfx/Misc/Config.cpp View File

@@ -32,7 +32,7 @@
#include "XMLwrapper.h" #include "XMLwrapper.h"


#define rStdString(name, len, ...) \ #define rStdString(name, len, ...) \
{STRINGIFY(name) "::s", rMap(length, len) DOC(__VA_ARGS__), NULL, rStringCb(name,len)}
{STRINGIFY(name) "::s", rMap(length, len) rProp(parameter) DOC(__VA_ARGS__), NULL, rStringCb(name,len)}
#define rStdStringCb(name, length) rBOIL_BEGIN \ #define rStdStringCb(name, length) rBOIL_BEGIN \
if(!strcmp("", args)) {\ if(!strcmp("", args)) {\
data.reply(loc, "s", obj->name); \ data.reply(loc, "s", obj->name); \
@@ -57,7 +57,7 @@ static const rtosc::Ports ports = {
rToggle(cfg.BankUIAutoClose, "Automatic Closing of BackUI After Patch Selection"), rToggle(cfg.BankUIAutoClose, "Automatic Closing of BackUI After Patch Selection"),
rParamI(cfg.GzipCompression, "Level of Gzip Compression For Save Files"), rParamI(cfg.GzipCompression, "Level of Gzip Compression For Save Files"),
rParamI(cfg.Interpolation, "Level of Interpolation, Linear/Cubic"), rParamI(cfg.Interpolation, "Level of Interpolation, Linear/Cubic"),
{"cfg.presetsDirList", rProp(parameter) rDoc("list of preset search directories"), 0,
{"cfg.presetsDirList", rDoc("list of preset search directories"), 0,
[](const char *msg, rtosc::RtData &d) [](const char *msg, rtosc::RtData &d)
{ {
Config &c = *(Config*)d.obj; Config &c = *(Config*)d.obj;
@@ -90,7 +90,7 @@ static const rtosc::Ports ports = {
rtosc_amessage(buffer, sizeof(buffer), d.loc, types, args); rtosc_amessage(buffer, sizeof(buffer), d.loc, types, args);
d.reply(buffer); d.reply(buffer);
}}, }},
{"cfg.bankRootDirList", rProp(parameter) rDoc("list of bank search directories"), 0,
{"cfg.bankRootDirList", rDoc("list of bank search directories"), 0,
[](const char *msg, rtosc::RtData &d) [](const char *msg, rtosc::RtData &d)
{ {
Config &c = *(Config*)d.obj; Config &c = *(Config*)d.obj;
@@ -133,7 +133,7 @@ static const rtosc::Ports ports = {
rParamI(cfg.VirKeybLayout, "Keyboard Layout For Virtual Piano Keyboard"), rParamI(cfg.VirKeybLayout, "Keyboard Layout For Virtual Piano Keyboard"),
//rParamS(cfg.LinuxALSAaudioDev), //rParamS(cfg.LinuxALSAaudioDev),
//rParamS(cfg.nameTag) //rParamS(cfg.nameTag)
{"cfg.OscilPower::i", rDoc("Size Of Oscillator Wavetable"), 0,
{"cfg.OscilPower::i", rProp(parameter) rDoc("Size Of Oscillator Wavetable"), 0,
[](const char *msg, rtosc::RtData &d) [](const char *msg, rtosc::RtData &d)
{ {
Config &c = *(Config*)d.obj; Config &c = *(Config*)d.obj;


+ 24
- 18
source/native-plugins/zynaddsubfx/Misc/Master.cpp View File

@@ -53,7 +53,9 @@ using namespace rtosc;


static const Ports sysefxPort = static const Ports sysefxPort =
{ {
{"part#" STRINGIFY(NUM_MIDI_PARTS) "::i", 0, 0, [](const char *m, RtData&d)
{"part#" STRINGIFY(NUM_MIDI_PARTS) "::i", rProp(parameter)
rDoc("gain on part to sysefx routing"), 0,
[](const char *m, RtData&d)
{ {
//ok, this is going to be an ugly workaround //ok, this is going to be an ugly workaround
//we know that if we are here the message previously MUST have //we know that if we are here the message previously MUST have
@@ -80,7 +82,8 @@ static const Ports sysefxPort =


static const Ports sysefsendto = static const Ports sysefsendto =
{ {
{"to#" STRINGIFY(NUM_SYS_EFX) "::i", 0, 0, [](const char *m, RtData&d)
{"to#" STRINGIFY(NUM_SYS_EFX) "::i",
rProp(parameter) rDoc("sysefx to sysefx routing gain"), 0, [](const char *m, RtData&d)
{ {
//same ugly workaround as before //same ugly workaround as before
const char *index_1 = m; const char *index_1 = m;
@@ -103,6 +106,7 @@ static const Ports sysefsendto =
}; };


static const Ports master_ports = { static const Ports master_ports = {
rString(last_xmz, XMZ_PATH_MAX, "File name for last name loaded if any."),
rRecursp(part, 16, "Part"),//NUM_MIDI_PARTS rRecursp(part, 16, "Part"),//NUM_MIDI_PARTS
rRecursp(sysefx, 4, "System Effect"),//NUM_SYS_EFX rRecursp(sysefx, 4, "System Effect"),//NUM_SYS_EFX
rRecursp(insefx, 8, "Insertion Effect"),//NUM_INS_EFX rRecursp(insefx, 8, "Insertion Effect"),//NUM_INS_EFX
@@ -112,10 +116,10 @@ static const Ports master_ports = {
rArrayI(Pinsparts, NUM_INS_EFX, "Part to insert part onto"), rArrayI(Pinsparts, NUM_INS_EFX, "Part to insert part onto"),
{"echo", rDoc("Hidden port to echo messages"), 0, [](const char *m, RtData&d) { {"echo", rDoc("Hidden port to echo messages"), 0, [](const char *m, RtData&d) {
d.reply(m-1);}}, d.reply(m-1);}},
{"get-vu", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
{"get-vu:", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
Master *m = (Master*)d.obj; Master *m = (Master*)d.obj;
d.reply("/vu-meter", "bb", sizeof(m->vu), &m->vu, sizeof(float)*NUM_MIDI_PARTS, m->vuoutpeakpart);}}, d.reply("/vu-meter", "bb", sizeof(m->vu), &m->vu, sizeof(float)*NUM_MIDI_PARTS, m->vuoutpeakpart);}},
{"reset-vu", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
{"reset-vu:", rDoc("Grab VU Data"), 0, [](const char *, RtData &d) {
Master *m = (Master*)d.obj; Master *m = (Master*)d.obj;
m->vuresetpeaks();}}, m->vuresetpeaks();}},
{"load-part:ib", rProp(internal) rDoc("Load Part From Middleware"), 0, [](const char *msg, RtData &d) { {"load-part:ib", rProp(internal) rDoc("Load Part From Middleware"), 0, [](const char *msg, RtData &d) {
@@ -129,14 +133,14 @@ static const Ports master_ports = {
p->initialize_rt(); p->initialize_rt();
//printf("part %d is now pointer %p\n", i, p); //printf("part %d is now pointer %p\n", i, p);
}}, }},
{"Pvolume::i", rDoc("Master Volume"), 0,
{"Pvolume::i", rProp(parameter) rDoc("Master Volume"), 0,
[](const char *m, rtosc::RtData &d) { [](const char *m, rtosc::RtData &d) {
if(rtosc_narguments(m)==0) { if(rtosc_narguments(m)==0) {
d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume); d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume);
} else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') { } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') {
((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127)); ((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127));
d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}}, d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}},
{"volume::i", rDoc("Master Volume"), 0,
{"volume::i", rProp(parameter) rDoc("Master Volume"), 0,
[](const char *m, rtosc::RtData &d) { [](const char *m, rtosc::RtData &d) {
if(rtosc_narguments(m)==0) { if(rtosc_narguments(m)==0) {
d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume); d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume);
@@ -200,7 +204,8 @@ static const Ports master_ports = {
[](const char *m, RtData &d){ [](const char *m, RtData &d){
Master *M = (Master*)d.obj; Master *M = (Master*)d.obj;
M->midi.clear_entry(rtosc_argument(m,0).s);}}, M->midi.clear_entry(rtosc_argument(m,0).s);}},
{"close-ui", rDoc("Request to close any connection named \"GUI\""), 0, [](const char *, RtData &d) {
{"close-ui:", rDoc("Request to close any connection named \"GUI\""), 0,
[](const char *, RtData &d) {
d.reply("/close-ui", "");}}, d.reply("/close-ui", "");}},
{"add-rt-memory:bi", rProp(internal) rDoc("Add Additional Memory To RT MemPool"), 0, {"add-rt-memory:bi", rProp(internal) rDoc("Add Additional Memory To RT MemPool"), 0,
[](const char *msg, RtData &d) [](const char *msg, RtData &d)
@@ -220,12 +225,13 @@ static const Ports master_ports = {
d.reply("/oscilsize", "f", m.synth.oscilsize_f); d.reply("/oscilsize", "f", m.synth.oscilsize_f);
d.reply("/oscilsize", "i", m.synth.oscilsize); d.reply("/oscilsize", "i", m.synth.oscilsize);
}}, }},
{"undo_pause",0,0,[](const char *, rtosc::RtData &d)
{d.reply("/undo_pause", "");}},
{"undo_resume",0,0,[](const char *, rtosc::RtData &d)
{d.reply("/undo_resume", "");}},
{"config/", 0, &Config::ports, [](const char *, rtosc::RtData &){}},
{"presets/", 0, &preset_ports, rBOIL_BEGIN
{"undo_pause:",rProp(internal) rDoc("pause undo event recording"),0,
[](const char *, rtosc::RtData &d) {d.reply("/undo_pause", "");}},
{"undo_resume:",rProp(internal) rDoc("resume undo event recording"),0,
[](const char *, rtosc::RtData &d) {d.reply("/undo_resume", "");}},
{"config/", rDoc("Top Level Application Configuration Parameters"), &Config::ports,
[](const char *, rtosc::RtData &){}},
{"presets/", rDoc("Parameter Presets"), &preset_ports, rBOIL_BEGIN
SNIP SNIP
preset_ports.dispatch(msg, data); preset_ports.dispatch(msg, data);
rBOIL_END}, rBOIL_END},
@@ -292,7 +298,7 @@ Master::Master(const SYNTH_T &synth_, Config* config)
:HDDRecorder(synth_), ctl(synth_), :HDDRecorder(synth_), ctl(synth_),
microtonal(config->cfg.GzipCompression), bank(config), microtonal(config->cfg.GzipCompression), bank(config),
midi(Master::ports), frozenState(false), pendingMemory(false), midi(Master::ports), frozenState(false), pendingMemory(false),
synth(synth_), gzip_compression(config->cfg.GzipCompression)
synth(synth_), time(synth), gzip_compression(config->cfg.GzipCompression)
{ {
bToU = NULL; bToU = NULL;
uToB = NULL; uToB = NULL;
@@ -306,6 +312,7 @@ Master::Master(const SYNTH_T &synth_, Config* config)
the_master = this; the_master = this;
#endif #endif


last_xmz[0] = 0;
fft = new FFTwrapper(synth.oscilsize); fft = new FFTwrapper(synth.oscilsize);


shutup = 0; shutup = 0;
@@ -315,7 +322,7 @@ Master::Master(const SYNTH_T &synth_, Config* config)
} }


for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
part[npart] = new Part(*memory, synth, config->cfg.GzipCompression,
part[npart] = new Part(*memory, synth, time, config->cfg.GzipCompression,
config->cfg.Interpolation, &microtonal, fft); config->cfg.Interpolation, &microtonal, fft);


//Insertion Effects init //Insertion Effects init
@@ -819,8 +826,8 @@ void Master::AudioOut(float *outl, float *outr)
ShutUp(); ShutUp();
} }


//update the LFO's time
LFOParams::time++;
//update the global frame timer
time++;
} }


//TODO review the respective code from yoshimi for this //TODO review the respective code from yoshimi for this
@@ -1056,7 +1063,6 @@ int Master::saveXML(const char *filename)
} }





int Master::loadXML(const char *filename) int Master::loadXML(const char *filename)
{ {
XMLwrapper *xml = new XMLwrapper(); XMLwrapper *xml = new XMLwrapper();


+ 6
- 2
source/native-plugins/zynaddsubfx/Misc/Master.h View File

@@ -28,6 +28,7 @@
#include <rtosc/miditable.h> #include <rtosc/miditable.h>
#include <rtosc/ports.h> #include <rtosc/ports.h>


#include "Time.h"
#include "Bank.h" #include "Bank.h"
#include "Recorder.h" #include "Recorder.h"


@@ -53,6 +54,8 @@ class Master
/** Destructor*/ /** Destructor*/
~Master(); ~Master();


char last_xmz[XMZ_PATH_MAX];

void applyOscEvent(const char *event); void applyOscEvent(const char *event);


/**Saves all settings to a XML file /**Saves all settings to a XML file
@@ -64,7 +67,6 @@ class Master


void defaults(); void defaults();



/**loads all settings from a XML file /**loads all settings from a XML file
* @return 0 for ok or -1 if there is an error*/ * @return 0 for ok or -1 if there is an error*/
int loadXML(const char *filename); int loadXML(const char *filename);
@@ -99,7 +101,8 @@ class Master


/**Audio Output*/ /**Audio Output*/
void AudioOut(float *outl, float *outr) REALTIME; void AudioOut(float *outl, float *outr) REALTIME;
/**Audio Output (for callback mode). This allows the program to be controled by an external program*/
/**Audio Output (for callback mode).
* This allows the program to be controled by an external program*/
void GetAudioOutSamples(size_t nsamples, void GetAudioOutSamples(size_t nsamples,
unsigned samplerate, unsigned samplerate,
float *outl, float *outl,
@@ -171,6 +174,7 @@ class Master
rtosc::ThreadLink *uToB; rtosc::ThreadLink *uToB;
bool pendingMemory; bool pendingMemory;
const SYNTH_T &synth; const SYNTH_T &synth;
AbsTime time;
const int& gzip_compression; //!< value from config const int& gzip_compression; //!< value from config
private: private:
float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];


+ 1
- 1
source/native-plugins/zynaddsubfx/Misc/Microtonal.cpp View File

@@ -67,7 +67,7 @@ const rtosc::Ports Microtonal::ports = {
rString(Pname, MICROTONAL_MAX_NAME_LEN, "Microtonal Name"), rString(Pname, MICROTONAL_MAX_NAME_LEN, "Microtonal Name"),
rString(Pcomment, MICROTONAL_MAX_NAME_LEN, "Microtonal Name"), rString(Pcomment, MICROTONAL_MAX_NAME_LEN, "Microtonal Name"),


{"octavesize:", 0, 0, [](const char*, RtData &d)
{"octavesize:", rDoc("Get octave size"), 0, [](const char*, RtData &d)
{ {
Microtonal &m = *(Microtonal*)d.obj; Microtonal &m = *(Microtonal*)d.obj;
d.reply(d.loc, "i", m.getoctavesize()); d.reply(d.loc, "i", m.getoctavesize());


+ 76
- 23
source/native-plugins/zynaddsubfx/Misc/MiddleWare.cpp View File

@@ -236,6 +236,11 @@ void rescanForBanks(Bank &bank, std::function<void(const char*)> cb)


void loadBank(Bank &bank, int pos, std::function<void(const char*)> cb) void loadBank(Bank &bank, int pos, std::function<void(const char*)> cb)
{ {
char response[2048];
if(!rtosc_message(response, 2048, "/loadbank", "i", pos))
errx(1, "Failure to handle bank update properly...");
if(cb)
cb(response);
if(bank.bankpos != pos) { if(bank.bankpos != pos) {
bank.bankpos = pos; bank.bankpos = pos;
bank.loadbank(bank.banks[pos].dir); bank.loadbank(bank.banks[pos].dir);
@@ -433,13 +438,13 @@ namespace Nio
using std::get; using std::get;
using rtosc::rtMsg; using rtosc::rtMsg;
rtosc::Ports ports = { rtosc::Ports ports = {
{"sink-list:", 0, 0, [](const char *msg, rtosc::RtData &d) {
{"sink-list:", 0, 0, [](const char *, rtosc::RtData &d) {
auto list = Nio::getSinks(); auto list = Nio::getSinks();
char *ret = rtosc_splat(d.loc, list); char *ret = rtosc_splat(d.loc, list);
d.reply(ret); d.reply(ret);
delete [] ret; delete [] ret;
}}, }},
{"source-list:", 0, 0, [](const char *msg, rtosc::RtData &d) {
{"source-list:", 0, 0, [](const char *, rtosc::RtData &d) {
auto list = Nio::getSources(); auto list = Nio::getSources();
char *ret = rtosc_splat(d.loc, list); char *ret = rtosc_splat(d.loc, list);
d.reply(ret); d.reply(ret);
@@ -489,7 +494,7 @@ public:
void doReadOnlyOp(std::function<void()> read_only_fn); void doReadOnlyOp(std::function<void()> read_only_fn);




void saveBankSlot(int npart, int nslot, Master *master, Fl_Osc_Interface *osc)
void saveBankSlot(int npart, int nslot, Master *master)
{ {
int err = 0; int err = 0;
doReadOnlyOp([master,nslot,npart,&err](){ doReadOnlyOp([master,nslot,npart,&err](){
@@ -502,7 +507,7 @@ public:
} }
} }


void renameBankSlot(int slot, string name, Master *master, Fl_Osc_Interface *osc)
void renameBankSlot(int slot, string name, Master *master)
{ {
int err = master->bank.setname(slot, name, -1); int err = master->bank.setname(slot, name, -1);
if(err) { if(err) {
@@ -513,7 +518,7 @@ public:
} }
} }


void swapBankSlot(int slota, int slotb, Master *master, Fl_Osc_Interface *osc)
void swapBankSlot(int slota, int slotb, Master *master)
{ {
int err = master->bank.swapslot(slota, slotb); int err = master->bank.swapslot(slota, slotb);
if(err) { if(err) {
@@ -524,7 +529,7 @@ public:
} }
} }


void clearBankSlot(int slot, Master *master, Fl_Osc_Interface *osc)
void clearBankSlot(int slot, Master *master)
{ {
int err = master->bank.clearslot(slot); int err = master->bank.clearslot(slot);
if(err) { if(err) {
@@ -557,7 +562,14 @@ public:
/*printf("results: '%s' '%d'\n",fname.c_str(), res);*/}); /*printf("results: '%s' '%d'\n",fname.c_str(), res);*/});
} }


void loadPart(int npart, const char *filename, Master *master, Fl_Osc_Interface *osc)
void loadPendingBank(int par, Bank &bank)
{
if(((unsigned int)par < bank.banks.size())
&& (bank.banks[par].dir != bank.bankfiletitle))
bank.loadbank(bank.banks[par].dir);
}

void loadPart(int npart, const char *filename, Master *master)
{ {
actual_load[npart]++; actual_load[npart]++;


@@ -565,9 +577,12 @@ public:
return; return;
assert(actual_load[npart] <= pending_load[npart]); assert(actual_load[npart] <= pending_load[npart]);


//load part in async fashion when possible
#if HAVE_ASYNC
auto alloc = std::async(std::launch::async, auto alloc = std::async(std::launch::async,
[master,filename,this,npart](){ [master,filename,this,npart](){
Part *p = new Part(*master->memory, synth, Part *p = new Part(*master->memory, synth,
master->time,
config->cfg.GzipCompression, config->cfg.GzipCompression,
config->cfg.Interpolation, config->cfg.Interpolation,
&master->microtonal, master->fft); &master->microtonal, master->fft);
@@ -589,6 +604,20 @@ public:
} }


Part *p = alloc.get(); Part *p = alloc.get();
#else
Part *p = new Part(*master->memory, synth, master->time,
config->cfg.GzipCompression,
config->cfg.Interpolation,
&master->microtonal, master->fft);
if(p->loadXMLinstrument(filename))
fprintf(stderr, "Warning: failed to load part<%s>!\n", filename);

auto isLateLoad = [this,npart]{
return actual_load[npart] != pending_load[npart];
};

p->applyparameters(isLateLoad);
#endif


obj_store.extractPart(p, npart); obj_store.extractPart(p, npart);
kits.extractPart(p, npart); kits.extractPart(p, npart);
@@ -605,6 +634,7 @@ public:
if(npart == -1) if(npart == -1)
return; return;
Part *p = new Part(*master->memory, synth, Part *p = new Part(*master->memory, synth,
master->time,
config->cfg.GzipCompression, config->cfg.GzipCompression,
config->cfg.Interpolation, config->cfg.Interpolation,
&master->microtonal, master->fft); &master->microtonal, master->fft);
@@ -628,7 +658,10 @@ public:
m->uToB = uToB; m->uToB = uToB;
m->bToU = bToU; m->bToU = bToU;
if(filename) { if(filename) {
m->loadXML(filename);
if ( m->loadXML(filename) ) {
delete m;
return;
}
m->applyparameters(); m->applyparameters();
} }


@@ -658,7 +691,8 @@ public:


void tick(void) void tick(void)
{ {
while(lo_server_recv_noblock(server, 0));
if(server)
while(lo_server_recv_noblock(server, 0));
while(bToU->hasNext()) { while(bToU->hasNext()) {
const char *rtmsg = bToU->read(); const char *rtmsg = bToU->read();
bToUhandle(rtmsg); bToUhandle(rtmsg);
@@ -815,13 +849,19 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_,
LO_UDP, liblo_error_cb); LO_UDP, liblo_error_cb);
else else
server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb);
lo_server_add_method(server, NULL, NULL, handler_function, mw);
fprintf(stderr, "lo server running on %d\n", lo_server_get_port(server));

if(server) {
lo_server_add_method(server, NULL, NULL, handler_function, mw);
fprintf(stderr, "lo server running on %d\n", lo_server_get_port(server));
} else
fprintf(stderr, "lo server could not be started :-/\n");



#ifndef PLUGINVERSION #ifndef PLUGINVERSION
if(!isPlugin()) { if(!isPlugin()) {
clean_up_tmp_nams(); clean_up_tmp_nams();
create_tmp_file((unsigned)lo_server_get_port(server));
if(server)
create_tmp_file((unsigned)lo_server_get_port(server));
} }
#endif #endif


@@ -869,7 +909,8 @@ MiddleWareImpl::~MiddleWareImpl(void)


warnMemoryLeaks(); warnMemoryLeaks();


lo_server_free(server);
if(server)
lo_server_free(server);


delete master; delete master;
delete osc; delete osc;
@@ -966,7 +1007,10 @@ void MiddleWareImpl::bToUhandle(const char *rtmsg, bool dummy)
uToB->write("/add-rt-memory", "bi", sizeof(void*), &mem, N); uToB->write("/add-rt-memory", "bi", sizeof(void*), &mem, N);
} else if(!strcmp(rtmsg, "/setprogram") } else if(!strcmp(rtmsg, "/setprogram")
&& !strcmp(rtosc_argument_string(rtmsg),"cc")) { && !strcmp(rtosc_argument_string(rtmsg),"cc")) {
loadPart(rtosc_argument(rtmsg,0).i, master->bank.ins[rtosc_argument(rtmsg,1).i].filename.c_str(), master, osc);
loadPart(rtosc_argument(rtmsg,0).i, master->bank.ins[rtosc_argument(rtmsg,1).i].filename.c_str(), master);
} else if(!strcmp(rtmsg, "/setbank")
&& !strcmp(rtosc_argument_string(rtmsg), "c")) {
loadPendingBank(rtosc_argument(rtmsg,0).i, master->bank);
} else if(!strcmp("/undo_pause", rtmsg)) { } else if(!strcmp("/undo_pause", rtmsg)) {
recording_undo = false; recording_undo = false;
} else if(!strcmp("/undo_resume", rtmsg)) { } else if(!strcmp("/undo_resume", rtmsg)) {
@@ -1148,7 +1192,7 @@ void MiddleWareImpl::handleMsg(const char *msg)
if(last_url == "GUI") if(last_url == "GUI")
bank_cb = [this](const char *msg){if(osc)osc->tryLink(msg);}; bank_cb = [this](const char *msg){if(osc)osc->tryLink(msg);};
else else
bank_cb = [this](const char *msg){this->bToUhandle(msg, 1);};
bank_cb = [this](const char *msg){if(osc)osc->tryLink(msg);this->bToUhandle(msg, 1);};


if(!strcmp(msg, "/refresh_bank") && !strcmp(rtosc_argument_string(msg), "i")) { if(!strcmp(msg, "/refresh_bank") && !strcmp(rtosc_argument_string(msg), "i")) {
refreshBankView(master->bank, rtosc_argument(msg,0).i, bank_cb); refreshBankView(master->bank, rtosc_argument(msg,0).i, bank_cb);
@@ -1184,22 +1228,22 @@ void MiddleWareImpl::handleMsg(const char *msg)
loadMaster(NULL); loadMaster(NULL);
} else if(!strcmp(msg, "/load_xiz") && !strcmp(rtosc_argument_string(msg), "is")) { } else if(!strcmp(msg, "/load_xiz") && !strcmp(rtosc_argument_string(msg), "is")) {
pending_load[rtosc_argument(msg,0).i]++; pending_load[rtosc_argument(msg,0).i]++;
loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master, osc);
loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
} else if(strstr(msg, "load-part") && !strcmp(rtosc_argument_string(msg), "is")) { } else if(strstr(msg, "load-part") && !strcmp(rtosc_argument_string(msg), "is")) {
pending_load[rtosc_argument(msg,0).i]++; pending_load[rtosc_argument(msg,0).i]++;
loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master, osc);
loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
} else if(!strcmp(msg, "/setprogram") } else if(!strcmp(msg, "/setprogram")
&& !strcmp(rtosc_argument_string(msg),"c")) { && !strcmp(rtosc_argument_string(msg),"c")) {
pending_load[0]++; pending_load[0]++;
loadPart(0, master->bank.ins[rtosc_argument(msg,0).i].filename.c_str(), master, osc);
loadPart(0, master->bank.ins[rtosc_argument(msg,0).i].filename.c_str(), master);
} else if(strstr(msg, "save-bank-part") && !strcmp(rtosc_argument_string(msg), "ii")) { } else if(strstr(msg, "save-bank-part") && !strcmp(rtosc_argument_string(msg), "ii")) {
saveBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master, osc);
saveBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master);
} else if(strstr(msg, "bank-rename") && !strcmp(rtosc_argument_string(msg), "is")) { } else if(strstr(msg, "bank-rename") && !strcmp(rtosc_argument_string(msg), "is")) {
renameBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master, osc);
renameBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
} else if(strstr(msg, "swap-bank-slots") && !strcmp(rtosc_argument_string(msg), "ii")) { } else if(strstr(msg, "swap-bank-slots") && !strcmp(rtosc_argument_string(msg), "ii")) {
swapBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master, osc);
swapBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master);
} else if(strstr(msg, "clear-bank-slot") && !strcmp(rtosc_argument_string(msg), "i")) { } else if(strstr(msg, "clear-bank-slot") && !strcmp(rtosc_argument_string(msg), "i")) {
clearBankSlot(rtosc_argument(msg,0).i, master, osc);
clearBankSlot(rtosc_argument(msg,0).i, master);
} else if(strstr(msg, "/config/")) { } else if(strstr(msg, "/config/")) {
handleConfig(msg); handleConfig(msg);
} else if(strstr(msg, "/presets/")) { } else if(strstr(msg, "/presets/")) {
@@ -1215,6 +1259,8 @@ void MiddleWareImpl::handleMsg(const char *msg)
undo.seekHistory(-1); undo.seekHistory(-1);
} else if(!strcmp(msg, "/redo")) { } else if(!strcmp(msg, "/redo")) {
undo.seekHistory(+1); undo.seekHistory(+1);
} else if(!strcmp(msg, "/ui/title")) {
;//drop the message into the abyss
} else } else
uToB->raw_write(msg); uToB->raw_write(msg);
} }
@@ -1316,6 +1362,10 @@ void MiddleWare::transmitMsg(const char *path, const char *args, va_list va)
fprintf(stderr, "Error in transmitMsg(va)n"); fprintf(stderr, "Error in transmitMsg(va)n");
} }


void MiddleWare::pendingSetBank(int bank)
{
impl->bToU->write("/setbank", "c", bank);
}
void MiddleWare::pendingSetProgram(int part, int program) void MiddleWare::pendingSetProgram(int part, int program)
{ {
impl->pending_load[part]++; impl->pending_load[part]++;
@@ -1339,7 +1389,10 @@ const SYNTH_T &MiddleWare::getSynth(void) const


const char* MiddleWare::getServerAddress(void) const const char* MiddleWare::getServerAddress(void) const
{ {
return lo_server_get_url(impl->server);
if(impl->server)
return lo_server_get_url(impl->server);
else
return "NULL";
} }


const PresetsStore& MiddleWare::getPresetsStore() const const PresetsStore& MiddleWare::getPresetsStore() const


+ 4
- 3
source/native-plugins/zynaddsubfx/Misc/MiddleWare.h View File

@@ -4,15 +4,14 @@
#include <string> #include <string>


struct SYNTH_T; struct SYNTH_T;
class Config;
class Master;
class Master;
class PresetsStore; class PresetsStore;


//Link between realtime and non-realtime layers //Link between realtime and non-realtime layers
class MiddleWare class MiddleWare
{ {
public: public:
MiddleWare(SYNTH_T synth, Config *config,
MiddleWare(SYNTH_T synth, class Config *config,
int preferred_port = -1); int preferred_port = -1);
~MiddleWare(void); ~MiddleWare(void);
void updateResources(Master *m); void updateResources(Master *m);
@@ -34,6 +33,8 @@ class MiddleWare
void transmitMsg(const char *, const char *args, ...); void transmitMsg(const char *, const char *args, ...);
//Handle a rtosc Message uToB //Handle a rtosc Message uToB
void transmitMsg(const char *, const char *args, va_list va); void transmitMsg(const char *, const char *args, va_list va);
//Indicate that a bank will be loaded
void pendingSetBank(int bank);
//Indicate that a program will be loaded on a known part //Indicate that a program will be loaded on a known part
void pendingSetProgram(int part, int program); void pendingSetProgram(int part, int program);
//Get/Set the active bToU url //Get/Set the active bToU url


+ 203
- 471
source/native-plugins/zynaddsubfx/Misc/Part.cpp View File

@@ -73,7 +73,8 @@ static const Ports partPorts = {
rToggle(Pnoteon, "If the channel accepts note on events"), rToggle(Pnoteon, "If the channel accepts note on events"),
//TODO FIXME Change to 0=OFF 1=MULTI 2=SINGLE //TODO FIXME Change to 0=OFF 1=MULTI 2=SINGLE
rParamI(Pkitmode, "Kit mode enable"), rParamI(Pkitmode, "Kit mode enable"),
rToggle(Pdrummode, "Drum mode enable"),
rToggle(Pdrummode, "Drum mode enable\n"
"When drum mode is enabled all keys are mapped to 12tET and legato is disabled"),
rToggle(Ppolymode, "Polyphoney mode"), rToggle(Ppolymode, "Polyphoney mode"),
rToggle(Plegatomode, "Legato enable"), rToggle(Plegatomode, "Legato enable"),
rParamZyn(info.Ptype, "Class of Instrument"), rParamZyn(info.Ptype, "Class of Instrument"),
@@ -82,11 +83,15 @@ static const Ports partPorts = {
rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"), rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"),
rArray(Pefxroute, NUM_PART_EFX, "Effect Routing"), rArray(Pefxroute, NUM_PART_EFX, "Effect Routing"),
rArrayT(Pefxbypass, NUM_PART_EFX, "If an effect is bypassed"), rArrayT(Pefxbypass, NUM_PART_EFX, "If an effect is bypassed"),
{"captureMin:", NULL, NULL, [](const char *, RtData &r)
{"captureMin:", rDoc("Capture minimum valid note"), NULL,
[](const char *, RtData &r)
{Part *p = (Part*)r.obj; p->Pminkey = p->lastnote;}}, {Part *p = (Part*)r.obj; p->Pminkey = p->lastnote;}},
{"captureMax:", NULL, NULL, [](const char *, RtData &r)
{"captureMax:", rDoc("Capture maximum valid note"), NULL,
[](const char *, RtData &r)
{Part *p = (Part*)r.obj; p->Pmaxkey = p->lastnote;}}, {Part *p = (Part*)r.obj; p->Pmaxkey = p->lastnote;}},
{"polyType::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"polyType::c:i", rProp(parameter) rOptions(Polyphonic, Monophonic, Legato)
rDoc("synthesis polyphony type"), NULL,
[](const char *msg, RtData &d)
{ {
Part *p = (Part*)d.obj; Part *p = (Part*)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -108,7 +113,8 @@ static const Ports partPorts = {
p->Ppolymode = 0; p->Ppolymode = 0;
p->Plegatomode = 1; p->Plegatomode = 1;
}}}, }}},
{"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0, [](const char *, RtData &d)
{"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0,
[](const char *, RtData &d)
{ {
//XXX todo forward this event for middleware to handle //XXX todo forward this event for middleware to handle
//Part *p = (Part*)d.obj; //Part *p = (Part*)d.obj;
@@ -159,23 +165,24 @@ static const Ports kitPorts = {
rToggle(Ppadenabled, "PADsynth enable"), rToggle(Ppadenabled, "PADsynth enable"),
rParamZyn(Psendtoparteffect, "Effect Levels"), rParamZyn(Psendtoparteffect, "Effect Levels"),
rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"), rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"),
{"captureMin:", NULL, NULL, [](const char *, RtData &r)
{"captureMin:", rDoc("Capture minimum valid note"), NULL,
[](const char *, RtData &r)
{Part::Kit *p = (Part::Kit*)r.obj; p->Pminkey = p->parent->lastnote;}}, {Part::Kit *p = (Part::Kit*)r.obj; p->Pminkey = p->parent->lastnote;}},
{"captureMax:", NULL, NULL, [](const char *, RtData &r)
{"captureMax:", rDoc("Capture maximum valid note"), NULL, [](const char *, RtData &r)
{Part::Kit *p = (Part::Kit*)r.obj; p->Pmaxkey = p->parent->lastnote;}}, {Part::Kit *p = (Part::Kit*)r.obj; p->Pmaxkey = p->parent->lastnote;}},
{"padpars-data:b", rProp(internal), 0,
{"padpars-data:b", rProp(internal) rDoc("Set PADsynth data pointer"), 0,
[](const char *msg, RtData &d) { [](const char *msg, RtData &d) {
rObject &o = *(rObject*)d.obj; rObject &o = *(rObject*)d.obj;
assert(o.padpars == NULL); assert(o.padpars == NULL);
o.padpars = *(decltype(o.padpars)*)rtosc_argument(msg, 0).b.data; o.padpars = *(decltype(o.padpars)*)rtosc_argument(msg, 0).b.data;
}}, }},
{"adpars-data:b", rProp(internal), 0,
{"adpars-data:b", rProp(internal) rDoc("Set ADsynth data pointer"), 0,
[](const char *msg, RtData &d) { [](const char *msg, RtData &d) {
rObject &o = *(rObject*)d.obj; rObject &o = *(rObject*)d.obj;
assert(o.adpars == NULL); assert(o.adpars == NULL);
o.adpars = *(decltype(o.adpars)*)rtosc_argument(msg, 0).b.data; o.adpars = *(decltype(o.adpars)*)rtosc_argument(msg, 0).b.data;
}}, }},
{"subpars-data:b", rProp(internal), 0,
{"subpars-data:b", rProp(internal) rDoc("Set SUBsynth data pointer"), 0,
[](const char *msg, RtData &d) { [](const char *msg, RtData &d) {
rObject &o = *(rObject*)d.obj; rObject &o = *(rObject*)d.obj;
assert(o.subpars == NULL); assert(o.subpars == NULL);
@@ -188,18 +195,23 @@ static const Ports kitPorts = {
const Ports &Part::Kit::ports = kitPorts; const Ports &Part::Kit::ports = kitPorts;
const Ports &Part::ports = partPorts; const Ports &Part::ports = partPorts;


Part::Part(Allocator &alloc, const SYNTH_T &synth_,
Part::Part(Allocator &alloc, const SYNTH_T &synth_, const AbsTime &time_,
const int &gzip_compression, const int &interpolation, const int &gzip_compression, const int &interpolation,
Microtonal *microtonal_, FFTwrapper *fft_) Microtonal *microtonal_, FFTwrapper *fft_)
:ctl(synth_), memory(alloc), synth(synth_),
:Pdrummode(false),
Ppolymode(true),
Plegatomode(false),
partoutl(new float[synth_.buffersize]),
partoutr(new float[synth_.buffersize]),
ctl(synth_),
microtonal(microtonal_),
fft(fft_),
memory(alloc),
synth(synth_),
time(time_),
gzip_compression(gzip_compression), gzip_compression(gzip_compression),
interpolation(interpolation) interpolation(interpolation)
{ {
microtonal = microtonal_;
fft = fft_;
partoutl = new float [synth.buffersize];
partoutr = new float [synth.buffersize];

monomemClear(); monomemClear();


for(int n = 0; n < NUM_KIT_ITEMS; ++n) { for(int n = 0; n < NUM_KIT_ITEMS; ++n) {
@@ -217,6 +229,7 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_,
partefx[nefx] = new EffectMgr(memory, synth, 1); partefx[nefx] = new EffectMgr(memory, synth, 1);
Pefxbypass[nefx] = false; Pefxbypass[nefx] = false;
} }
assert(partefx[0]);


for(int n = 0; n < NUM_PART_EFX + 1; ++n) { for(int n = 0; n < NUM_PART_EFX + 1; ++n) {
partfxinputl[n] = new float [synth.buffersize]; partfxinputl[n] = new float [synth.buffersize];
@@ -226,28 +239,15 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_,
killallnotes = false; killallnotes = false;
oldfreq = -1.0f; oldfreq = -1.0f;



for(int i = 0; i < POLYPHONY; ++i) {
partnote[i].status = KEY_OFF;
partnote[i].note = -1;
partnote[i].itemsplaying = 0;
for(int j = 0; j < NUM_KIT_ITEMS; ++j) {
partnote[i].kititem[j].adnote = NULL;
partnote[i].kititem[j].subnote = NULL;
partnote[i].kititem[j].padnote = NULL;
}
partnote[i].time = 0;
}
cleanup(); cleanup();


Pname = new char[PART_MAX_NAME_LEN]; Pname = new char[PART_MAX_NAME_LEN];


oldvolumel = oldvolumer = 0.5f; oldvolumel = oldvolumer = 0.5f;
lastnote = -1; lastnote = -1;
lastpos = 0; // lastpos will store previously used NoteOn(...)'s pos.
lastlegatomodevalid = false; // To store previous legatomodevalid value.


defaults(); defaults();
assert(partefx[0]);
} }


void Part::cloneTraits(Part &p) const void Part::cloneTraits(Part &p) const
@@ -334,8 +334,7 @@ void Part::defaultsinstrument()
*/ */
void Part::cleanup(bool final_) void Part::cleanup(bool final_)
{ {
for(int k = 0; k < POLYPHONY; ++k)
KillNotePos(k);
notePool.killAllNotes();
for(int i = 0; i < synth.buffersize; ++i) { for(int i = 0; i < synth.buffersize; ++i) {
partoutl[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; partoutl[i] = final_ ? 0.0f : synth.denormalkillbuf[i];
partoutr[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; partoutr[i] = final_ ? 0.0f : synth.denormalkillbuf[i];
@@ -371,6 +370,16 @@ Part::~Part()
} }
} }


void assert_kit_sanity(const Part::Kit *kits)
{
for(int i=0; i<NUM_KIT_ITEMS; ++i) {
//an enabled kit must have a corresponding parameter object
assert(!kits[i].Padenabled || kits[i].adpars);
assert(!kits[i].Ppadenabled || kits[i].padpars);
assert(!kits[i].Psubenabled || kits[i].subpars);
}
}

/* /*
* Note On Messages * Note On Messages
*/ */
@@ -378,299 +387,92 @@ void Part::NoteOn(unsigned char note,
unsigned char velocity, unsigned char velocity,
int masterkeyshift) int masterkeyshift)
{ {
// Legato and MonoMem used vars:
int posb = POLYPHONY - 1; // Just a dummy initial value.
bool legatomodevalid = false; //true when legato mode is determined applicable.
bool doinglegato = false; // true when we determined we do a legato note.
bool ismonofirstnote = false; /*(In Mono/Legato) true when we determined
no other notes are held down or sustained.*/
int lastnotecopy = lastnote; //Useful after lastnote has been changed.
//Verify Basic Mode and sanity
const bool isRunningNote = notePool.existsRunningNote();
const bool doingLegato = isRunningNote && isLegatoMode() &&
lastlegatomodevalid;


if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey)) if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey))
return; return;


// MonoMem stuff:
if(!Ppolymode) { // If Poly is off
monomemPush(note); // Add note to the list.
monomem[note].velocity = velocity; // Store this note's velocity.
monomem[note].mkeyshift = masterkeyshift; /* Store masterkeyshift too*/
if((partnote[lastpos].status != KEY_PLAYING)
&& (partnote[lastpos].status != KEY_RELEASED_AND_SUSTAINED))
ismonofirstnote = true; // No other keys are held or sustained.
} else if(!monomemEmpty())
monomemClear();

lastnote = note;

int pos = -1;
for(int i = 0; i < POLYPHONY; ++i)
if(partnote[i].status == KEY_OFF) {
pos = i;
break;
}

if(Plegatomode && !Pdrummode) {
if(Ppolymode != 0) {
fprintf(
stderr,
"ZynAddSubFX WARNING: Poly and Legato modes are both On, that should not happen ! ... Disabling Legato mode ! - (Part.cpp::NoteOn(..))\n");
Plegatomode = 0;
}
else {
// Legato mode is on and applicable.
legatomodevalid = true;
if((not ismonofirstnote) && (lastlegatomodevalid)) {
// At least one other key is held or sustained, and the
// previous note was played while in valid legato mode.
doinglegato = true; // So we'll do a legato note.
pos = lastpos; // A legato note uses same pos as previous..
posb = lastposb; // .. same goes for posb.
}
else {
// Legato mode is valid, but this is only a first note.
for(int i = 0; i < POLYPHONY; ++i)
if((partnote[i].status == KEY_PLAYING)
|| (partnote[i].status == KEY_RELEASED_AND_SUSTAINED))
ReleaseNotePos(i);

// Set posb
posb = (pos + 1) % POLYPHONY; //We really want it (if the following fails)
for(int i = 0; i < POLYPHONY; ++i)
if((partnote[i].status == KEY_OFF) && (pos != i)) {
posb = i;
break;
}
}
lastposb = posb; // Keep a trace of used posb
}
}
else // Legato mode is either off or non-applicable.
if(!Ppolymode) { //if the mode is 'mono' turn off all other notes
for(int i = 0; i < POLYPHONY; ++i)
if(partnote[i].status == KEY_PLAYING)
ReleaseNotePos(i);
ReleaseSustainedKeys();
}
lastlegatomodevalid = legatomodevalid;

if(pos == -1)
fprintf(stderr,
"%s",
"NOTES TOO MANY (> POLYPHONY) - (Part.cpp::NoteOn(..))\n");
else {
//start the note
partnote[pos].status = KEY_PLAYING;
partnote[pos].note = note;
if(legatomodevalid) {
partnote[posb].status = KEY_PLAYING;
partnote[posb].note = note;
}
verifyKeyMode();
assert_kit_sanity(kit);


//this computes the velocity sensing of the part
float vel = VelF(velocity / 127.0f, Pvelsns);
//Preserve Note Stack
if(isMonoMode() || isLegatoMode()) {
monomemPush(note);
monomem[note].velocity = velocity;
monomem[note].mkeyshift = masterkeyshift;


//compute the velocity offset
vel = limit(vel + (Pveloffs - 64.0f) / 64.0f, 0.0f, 1.0f);
} else if(!monomemEmpty())
monomemClear();


//compute the keyshift
int partkeyshift = (int)Pkeyshift - 64;
int keyshift = masterkeyshift + partkeyshift;
//Mono/Legato Release old notes
if(isMonoMode() || (isLegatoMode() && !doingLegato))
notePool.releasePlayingNotes();


//initialise note frequency
float notebasefreq;
if(Pdrummode == 0) {
notebasefreq = microtonal->getnotefreq(note, keyshift);
if(notebasefreq < 0.0f)
return;//the key is no mapped
}
else
notebasefreq = 440.0f * powf(2.0f, (note - 69.0f) / 12.0f);

//Portamento
if(oldfreq < 1.0f)
oldfreq = notebasefreq;//this is only the first note is played

// For Mono/Legato: Force Portamento Off on first
// notes. That means it is required that the previous note is
// still held down or sustained for the Portamento to activate
// (that's like Legato).
bool portamento = false;
if(Ppolymode || !ismonofirstnote)
// I added a third argument to the
// ctl.initportamento(...) function to be able
// to tell it if we're doing a legato note.
portamento = ctl.initportamento(oldfreq, notebasefreq, doinglegato);

if(portamento)
ctl.portamento.noteusing = pos;
oldfreq = notebasefreq;

lastpos = pos; // Keep a trace of used pos.

if(doinglegato) {
// Do Legato note
if(Pkitmode == 0) { // "normal mode" legato note

auto note1 = partnote[pos].kititem[0];
auto note2 = partnote[posb].kititem[0];
LegatoParams pars = {notebasefreq, vel, portamento, note, true};
if(kit[0].Padenabled && note1.adnote && note2.adnote) {
note1.adnote->legatonote(pars);
note2.adnote->legatonote(pars);
}
lastlegatomodevalid = isLegatoMode();


if(kit[0].Psubenabled && note1.subnote && note2.subnote) {
note1.subnote->legatonote(pars);
note2.subnote->legatonote(pars);
}
//Compute Note Parameters
const float vel = getVelocity(velocity, Pvelsns, Pveloffs);
const int partkeyshift = (int)Pkeyshift - 64;
const int keyshift = masterkeyshift + partkeyshift;
const float notebasefreq = getBaseFreq(note, keyshift);


if(kit[0].Ppadenabled && note1.padnote && note2.padnote) {
note1.padnote->legatonote(pars);
note2.padnote->legatonote(pars);
}
}
else { // "kit mode" legato note
int ci = 0;
for(int item = 0; item < NUM_KIT_ITEMS; ++item) {

//Make sure the key is valid and not across multiple ranges
if(kit[item].Pmuted || !inRange(note, kit[item].Pminkey, kit[item].Pmaxkey)
|| !inRange((unsigned char)lastnotecopy, kit[item].Pminkey, kit[item].Pmaxkey))
continue;

auto note1 = partnote[pos].kititem[ci];
auto note2 = partnote[posb].kititem[ci];
LegatoParams pars = {notebasefreq, vel, portamento, note, true};
note1.sendtoparteffect = limit((int)kit[item].Psendtoparteffect, 0, NUM_PART_EFX);
note2.sendtoparteffect = limit((int)kit[item].Psendtoparteffect, 0, NUM_PART_EFX);

if(kit[item].Padenabled && kit[item].adpars && note1.adnote && note2.adnote) {
note1.adnote->legatonote(pars);
note2.adnote->legatonote(pars);
}
if(kit[item].Psubenabled && kit[item].subpars && note1.subnote && note2.subnote) {
note1.subnote->legatonote(pars);
note2.subnote->legatonote(pars);
}
if(kit[item].Ppadenabled && kit[item].padpars && note1.padnote && note2.padnote) {
note1.padnote->legatonote(pars);
note2.padnote->legatonote(pars);
}

if(kit[item].adpars || kit[item].subpars || kit[item].padpars) {
ci++;
if((kit[item].Padenabled || kit[item].Psubenabled || kit[item].Ppadenabled) && (Pkitmode == 2))
break;
}
}
if(ci == 0) {
// No legato were performed at all, so pretend nothing happened:
monomemPop(monomemBack()); // Remove last note from the list.
lastnote = lastnotecopy; // Set lastnote back to previous value.
}
}
return; // Ok, Legato note done, return.
}
if(notebasefreq < 0)
return;


partnote[pos].itemsplaying = 0;
if(legatomodevalid)
partnote[posb].itemsplaying = 0;

if(Pkitmode == 0) { //init the notes for the "normal mode"
partnote[pos].kititem[0].sendtoparteffect = 0;
SynthParams pars{memory, ctl, synth, notebasefreq, vel, (bool) portamento, note, false};

if(kit[0].Padenabled)
partnote[pos].kititem[0].adnote =
memory.alloc<ADnote>(kit[0].adpars, pars);
if(kit[0].Psubenabled)
partnote[pos].kititem[0].subnote =
memory.alloc<SUBnote>(kit[0].subpars, pars);
if(kit[0].Ppadenabled)
partnote[pos].kititem[0].padnote =
memory.alloc<PADnote>(kit[0].padpars, pars,
interpolation);


if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled)
partnote[pos].itemsplaying++;

// Spawn another note (but silent) if legatomodevalid==true
if(legatomodevalid) {
partnote[posb].kititem[0].sendtoparteffect = 0;
pars.quiet = true;

if(kit[0].Padenabled)
partnote[posb].kititem[0].adnote =
memory.alloc<ADnote>(kit[0].adpars, pars);
if(kit[0].Psubenabled)
partnote[posb].kititem[0].subnote =
memory.alloc<SUBnote>(kit[0].subpars, pars);
if(kit[0].Ppadenabled)
partnote[posb].kititem[0].padnote =
memory.alloc<PADnote>(kit[0].padpars, pars,
interpolation);

if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled)
partnote[posb].itemsplaying++;
}
}
else //init the notes for the "kit mode"
for(int item = 0; item < NUM_KIT_ITEMS; ++item) {
if(kit[item].Pmuted || !inRange(note, kit[item].Pminkey, kit[item].Pmaxkey))
continue;
//Portamento
lastnote = note;
if(oldfreq < 1.0f)
oldfreq = notebasefreq;//this is only the first note is played

// For Mono/Legato: Force Portamento Off on first
// notes. That means it is required that the previous note is
// still held down or sustained for the Portamento to activate
// (that's like Legato).
bool portamento = false;
if(Ppolymode || isRunningNote)
portamento = ctl.initportamento(oldfreq, notebasefreq, doingLegato);

oldfreq = notebasefreq;

//Adjust Existing Notes
if(doingLegato) {
LegatoParams pars = {notebasefreq, vel, portamento, note, true};
notePool.applyLegato(pars);
return;
}


int ci = partnote[pos].itemsplaying; //ci=current item
auto &note1 = partnote[pos].kititem[ci];

//if this parameter is 127 for "unprocessed"
note1.sendtoparteffect = limit((int)kit[item].Psendtoparteffect, 0, NUM_PART_EFX);

SynthParams pars{memory, ctl, synth, notebasefreq, vel, (bool) portamento, note, false};

if(kit[item].adpars && kit[item].Padenabled)
note1.adnote =
memory.alloc<ADnote>(kit[item].adpars, pars);

if(kit[item].subpars && kit[item].Psubenabled)
note1.subnote =
memory.alloc<SUBnote>(kit[item].subpars, pars);

if(kit[item].padpars && kit[item].Ppadenabled)
note1.padnote =
memory.alloc<PADnote>(kit[item].padpars, pars,
interpolation);

// Spawn another note (but silent) if legatomodevalid==true
if(legatomodevalid) {
auto &note2 = partnote[posb].kititem[ci];
note2.sendtoparteffect = limit((int)kit[item].Psendtoparteffect, 0, NUM_PART_EFX);

pars.quiet = true;
if(kit[item].adpars && kit[item].Padenabled)
note2.adnote =
memory.alloc<ADnote>(kit[item].adpars, pars);
if(kit[item].subpars && kit[item].Psubenabled)
note2.subnote =
memory.alloc<SUBnote>(kit[item].subpars, pars);
if(kit[item].padpars && kit[item].Ppadenabled)
note2.padnote =
memory.alloc<PADnote>(kit[item].padpars, pars,
interpolation);

if(kit[item].adpars || kit[item].subpars || kit[item].padpars)
partnote[posb].itemsplaying++;
}
//Create New Notes
for(uint8_t i = 0; i < NUM_KIT_ITEMS; ++i) {
auto &item = kit[i];
if(Pkitmode != 0 && !item.validNote(note))
continue;


if(kit[item].adpars || kit[item].subpars) {
partnote[pos].itemsplaying++;
if((kit[item].Padenabled || kit[item].Psubenabled || kit[item].Ppadenabled) && (Pkitmode == 2))
break;
}
}
SynthParams pars{memory, ctl, synth, time, notebasefreq, vel,
portamento, note, false};
const int sendto = Pkitmode ? item.sendto() : 0;

if(item.Padenabled)
notePool.insertNote(note, sendto,
{memory.alloc<ADnote>(kit[i].adpars, pars), 0, i});
if(item.Psubenabled)
notePool.insertNote(note, sendto,
{memory.alloc<SUBnote>(kit[i].subpars, pars), 1, i});
if(item.Ppadenabled)
notePool.insertNote(note, sendto,
{memory.alloc<PADnote>(kit[i].padpars, pars, interpolation), 2, i});

//Partial Kit Use
if(isNonKit() || (isSingleKit() && item.active()))
break;
} }


//this only release the keys if there is maximum number of keys allowed
if(isLegatoMode())
notePool.upgradeToLegato();

//Enforce the key limit
setkeylimit(Pkeylimit); setkeylimit(Pkeylimit);
} }


@@ -683,17 +485,18 @@ void Part::NoteOff(unsigned char note) //release the key
if(!monomemEmpty()) if(!monomemEmpty())
monomemPop(note); monomemPop(note);


for(int i = POLYPHONY - 1; i >= 0; i--) //first note in, is first out if there are same note multiple times
if((partnote[i].status == KEY_PLAYING) && (partnote[i].note == note)) {
if(!ctl.sustain.sustain) { //the sustain pedal is not pushed
if(!Ppolymode && !monomemEmpty())
MonoMemRenote();//Play most recent still active note
else
ReleaseNotePos(i);
}
else //the sustain pedal is pushed
partnote[i].status = KEY_RELEASED_AND_SUSTAINED;
for(auto &desc:notePool.activeDesc()) {
if(desc.note != note)
continue;
if(!ctl.sustain.sustain) { //the sustain pedal is not pushed
if((isMonoMode() || isLegatoMode()) && !monomemEmpty())
MonoMemRenote();//Play most recent still active note
else
notePool.release(desc);
} }
else //the sustain pedal is pushed
desc.status = KEY_RELEASED_AND_SUSTAINED;
}
} }


void Part::PolyphonicAftertouch(unsigned char note, void Part::PolyphonicAftertouch(unsigned char note,
@@ -709,36 +512,12 @@ void Part::PolyphonicAftertouch(unsigned char note,
if(!Ppolymode) // if Poly is off if(!Ppolymode) // if Poly is off
monomem[note].velocity = velocity; // Store this note's velocity. monomem[note].velocity = velocity; // Store this note's velocity.



for(int i = 0; i < POLYPHONY; ++i)
if((partnote[i].note == note) && (partnote[i].status == KEY_PLAYING)) {
/* update velocity */
// compute the velocity offset
float vel = VelF(velocity / 127.0f, Pvelsns) + (Pveloffs - 64.0f) / 64.0f;
vel = limit(vel, 0.0f, 1.0f);

if(!Pkitmode) { // "normal mode"
if(kit[0].Padenabled && partnote[i].kititem[0].adnote)
partnote[i].kititem[0].adnote->setVelocity(vel);
if(kit[0].Psubenabled && partnote[i].kititem[0].subnote)
partnote[i].kititem[0].subnote->setVelocity(vel);
if(kit[0].Ppadenabled && partnote[i].kititem[0].padnote)
partnote[i].kititem[0].padnote->setVelocity(vel);
}
else // "kit mode"
for(int item = 0; item < NUM_KIT_ITEMS; ++item) {
if(kit[item].Pmuted || !inRange(note, kit[item].Pminkey, kit[item].Pmaxkey))
continue;

if(kit[item].Padenabled && partnote[i].kititem[item].adnote)
partnote[i].kititem[item].adnote->setVelocity(vel);
if(kit[item].Psubenabled && partnote[i].kititem[item].subnote)
partnote[i].kititem[item].subnote->setVelocity(vel);
if(kit[item].Ppadenabled && partnote[i].kititem[item].padnote)
partnote[i].kititem[item].padnote->setVelocity(vel);
}
}

const float vel = getVelocity(velocity, Pvelsns, Pveloffs);
for(auto &d:notePool.activeDesc()) {
if(d.note == note && d.status == KEY_PLAYING)
for(auto &s:notePool.activeNotes(d))
s.note->setVelocity(vel);
}
} }


/* /*
@@ -839,13 +618,14 @@ void Part::SetController(unsigned int type, int par)
void Part::ReleaseSustainedKeys() void Part::ReleaseSustainedKeys()
{ {
// Let's call MonoMemRenote() on some conditions: // Let's call MonoMemRenote() on some conditions:
if(Ppolymode == 0 && !monomemEmpty())
if((isMonoMode() || isLegatoMode()) && !monomemEmpty())
if(monomemBack() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. if(monomemBack() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check.
MonoMemRenote(); // To play most recent still held note. MonoMemRenote(); // To play most recent still held note.


for(int i = 0; i < POLYPHONY; ++i)
if(partnote[i].status == KEY_RELEASED_AND_SUSTAINED)
ReleaseNotePos(i);
for(auto &d:notePool.activeDesc())
if(d.status == KEY_RELEASED_AND_SUSTAINED)
for(auto &s:notePool.activeNotes(d))
s.note->releasekey();
} }


/* /*
@@ -854,10 +634,10 @@ void Part::ReleaseSustainedKeys()


void Part::ReleaseAllKeys() void Part::ReleaseAllKeys()
{ {
for(int i = 0; i < POLYPHONY; ++i)
if((partnote[i].status != KEY_RELEASED)
&& (partnote[i].status != KEY_OFF)) //thanks to Frank Neumann
ReleaseNotePos(i);
for(auto &d:notePool.activeDesc())
if(d.status != KEY_RELEASED)
for(auto &s:notePool.activeNotes(d))
s.note->releasekey();
} }


// Call NoteOn(...) with the most recent still held key as new note // Call NoteOn(...) with the most recent still held key as new note
@@ -866,50 +646,36 @@ void Part::MonoMemRenote()
{ {
unsigned char mmrtempnote = monomemBack(); // Last list element. unsigned char mmrtempnote = monomemBack(); // Last list element.
monomemPop(mmrtempnote); // We remove it, will be added again in NoteOn(...). monomemPop(mmrtempnote); // We remove it, will be added again in NoteOn(...).
if(Pnoteon == 0)
ReleaseNotePos(lastpos);
else
NoteOn(mmrtempnote, monomem[mmrtempnote].velocity,
monomem[mmrtempnote].mkeyshift);
NoteOn(mmrtempnote, monomem[mmrtempnote].velocity,
monomem[mmrtempnote].mkeyshift);
} }


/*
* Release note at position
*/
void Part::ReleaseNotePos(int pos)
float Part::getBaseFreq(int note, int keyshift) const
{ {
for(int j = 0; j < NUM_KIT_ITEMS; ++j) {
if(partnote[pos].kititem[j].adnote)
partnote[pos].kititem[j].adnote->releasekey();
if(Pdrummode)
return 440.0f * powf(2.0f, (note - 69.0f) / 12.0f);
else
return microtonal->getnotefreq(note, keyshift);
}


if(partnote[pos].kititem[j].subnote)
partnote[pos].kititem[j].subnote->releasekey();
float Part::getVelocity(uint8_t velocity, uint8_t velocity_sense,
uint8_t velocity_offset) const
{
//compute sense function
const float vel = VelF(velocity / 127.0f, velocity_sense);


if(partnote[pos].kititem[j].padnote)
partnote[pos].kititem[j].padnote->releasekey();
}
partnote[pos].status = KEY_RELEASED;
//compute the velocity offset
return limit(vel + (velocity_offset - 64.0f) / 64.0f, 0.0f, 1.0f);
} }



/*
* Kill note at position
*/
void Part::KillNotePos(int pos)
void Part::verifyKeyMode(void)
{ {
partnote[pos].status = KEY_OFF;
partnote[pos].note = -1;
partnote[pos].time = 0;
partnote[pos].itemsplaying = 0;

for(int j = 0; j < NUM_KIT_ITEMS; ++j) {
memory.dealloc(partnote[pos].kititem[j].adnote);
memory.dealloc(partnote[pos].kititem[j].subnote);
memory.dealloc(partnote[pos].kititem[j].padnote);
}
if(pos == ctl.portamento.noteusing) {
ctl.portamento.noteusing = -1;
ctl.portamento.used = 0;
if(Plegatomode && !Pdrummode && Ppolymode) {
fprintf(stderr,
"WARNING: Poly & Legato modes are On, that shouldn't happen\n"
"Disabling Legato mode...\n"
"(Part.cpp::NoteOn(..))\n");
Plegatomode = 0;
} }
} }


@@ -917,32 +683,15 @@ void Part::KillNotePos(int pos)
/* /*
* Set Part's key limit * Set Part's key limit
*/ */
void Part::setkeylimit(unsigned char Pkeylimit)
void Part::setkeylimit(unsigned char Pkeylimit_)
{ {
this->Pkeylimit = Pkeylimit;
Pkeylimit = Pkeylimit_;
int keylimit = Pkeylimit; int keylimit = Pkeylimit;
if(keylimit == 0) if(keylimit == 0)
keylimit = POLYPHONY - 5; keylimit = POLYPHONY - 5;


//release old keys if the number of notes>keylimit
if(Ppolymode != 0) {
int notecount = 0;
for(int i = 0; i < POLYPHONY; ++i)
if((partnote[i].status == KEY_PLAYING) || (partnote[i].status == KEY_RELEASED_AND_SUSTAINED))
notecount++;

int oldestnotepos = -1;
if(notecount > keylimit) //find out the oldest note
for(int i = 0; i < POLYPHONY; ++i) {
int maxtime = 0;
if(((partnote[i].status == KEY_PLAYING) || (partnote[i].status == KEY_RELEASED_AND_SUSTAINED)) && (partnote[i].time > maxtime)) {
maxtime = partnote[i].time;
oldestnotepos = i;
}
}
if(oldestnotepos != -1)
ReleaseNotePos(oldestnotepos);
}
if(notePool.getRunningNotes() > keylimit)
notePool.enforceKeyLimit(keylimit);
} }




@@ -954,65 +703,35 @@ void Part::AllNotesOff()
killallnotes = true; killallnotes = true;
} }


void Part::RunNote(unsigned int k)
/*
* Compute Part samples and store them in the partoutl[] and partoutr[]
*/
void Part::ComputePartSmps()
{ {
unsigned noteplay = 0;
for(int item = 0; item < partnote[k].itemsplaying; ++item) {
int sendcurrenttofx = partnote[k].kititem[item].sendtoparteffect;

for(unsigned type = 0; type < 3; ++type) {
//Select a note
SynthNote **note = NULL;
if(type == 0)
note = &partnote[k].kititem[item].adnote;
else if(type == 1)
note = &partnote[k].kititem[item].subnote;
else if(type == 2)
note = &partnote[k].kititem[item].padnote;

//Process if it exists
if(!(*note))
continue;
noteplay++;
assert(partefx[0]);
for(unsigned nefx = 0; nefx < NUM_PART_EFX + 1; ++nefx) {
memset(partfxinputl[nefx], 0, synth.bufferbytes);
memset(partfxinputr[nefx], 0, synth.bufferbytes);
}


for(auto &d:notePool.activeDesc()) {
d.age++;
for(auto &s:notePool.activeNotes(d)) {
float tmpoutr[synth.buffersize]; float tmpoutr[synth.buffersize];
float tmpoutl[synth.buffersize]; float tmpoutl[synth.buffersize];
(*note)->noteout(&tmpoutl[0], &tmpoutr[0]);
auto &note = *s.note;
note.noteout(&tmpoutl[0], &tmpoutr[0]);


if((*note)->finished())
memory.dealloc(*note);
for(int i = 0; i < synth.buffersize; ++i) { //add the note to part(mix) for(int i = 0; i < synth.buffersize; ++i) { //add the note to part(mix)
partfxinputl[sendcurrenttofx][i] += tmpoutl[i];
partfxinputr[sendcurrenttofx][i] += tmpoutr[i];
partfxinputl[d.sendto][i] += tmpoutl[i];
partfxinputr[d.sendto][i] += tmpoutr[i];
} }
}
}


//Kill note if there is no synth on that note
if(!noteplay)
KillNotePos(k);
}

/*
* Compute Part samples and store them in the partoutl[] and partoutr[]
*/
void Part::ComputePartSmps()
{
for(unsigned nefx = 0; nefx < NUM_PART_EFX + 1; ++nefx)
for(int i = 0; i < synth.buffersize; ++i) {
partfxinputl[nefx][i] = 0.0f;
partfxinputr[nefx][i] = 0.0f;
if(note.finished())
notePool.kill(s);
} }

for(unsigned k = 0; k < POLYPHONY; ++k) {
if(partnote[k].status == KEY_OFF)
continue;
partnote[k].time++;
//get the sampledata of the note and kill it if it's finished
RunNote(k);
} }



//Apply part's effects and mix them //Apply part's effects and mix them
for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) {
if(!Pefxbypass[nefx]) { if(!Pefxbypass[nefx]) {
@@ -1040,8 +759,8 @@ void Part::ComputePartSmps()
partoutl[i] *= tmp; partoutl[i] *= tmp;
partoutr[i] *= tmp; partoutr[i] *= tmp;
} }
for(int k = 0; k < POLYPHONY; ++k)
KillNotePos(k);
notePool.killAllNotes();
monomemClear();
killallnotes = false; killallnotes = false;
for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx)
partefx[nefx]->cleanup(); partefx[nefx]->cleanup();
@@ -1087,9 +806,7 @@ void Part::setkititemstatus(unsigned kititem, bool Penabled_)
delete kkit.padpars; delete kkit.padpars;
kkit.Pname[0] = '\0'; kkit.Pname[0] = '\0';


//Reset notes s.t. stale buffers will not get read
for(int k = 0; k < POLYPHONY; ++k)
KillNotePos(k);
notePool.killAllNotes();
} }
else { else {
//All parameters must be NULL in this case //All parameters must be NULL in this case
@@ -1247,8 +964,7 @@ void Part::kill_rt(void)
{ {
for(int i=0; i<NUM_PART_EFX; ++i) for(int i=0; i<NUM_PART_EFX; ++i)
partefx[i]->kill(); partefx[i]->kill();
for(int k = 0; k < POLYPHONY; ++k)
KillNotePos(k);
notePool.killAllNotes();
} }


void Part::monomemPush(char note) void Part::monomemPush(char note)
@@ -1414,3 +1130,19 @@ void Part::getfromXML(XMLwrapper *xml)
xml->exitbranch(); xml->exitbranch();
} }
} }

bool Part::Kit::active(void) const
{
return Padenabled || Psubenabled || Ppadenabled;
}

uint8_t Part::Kit::sendto(void) const
{
return limit((int)Psendtoparteffect, 0, NUM_PART_EFX);

}

bool Part::Kit::validNote(char note) const
{
return !Pmuted && inRange((uint8_t)note, Pminkey, Pmaxkey);
}

+ 22
- 19
source/native-plugins/zynaddsubfx/Misc/Part.h View File

@@ -27,6 +27,7 @@


#include "../globals.h" #include "../globals.h"
#include "../Params/Controller.h" #include "../Params/Controller.h"
#include "../Containers/NotePool.h"


#include <functional> #include <functional>


@@ -37,7 +38,7 @@ class Part
/**Constructor /**Constructor
* @param microtonal_ Pointer to the microtonal object * @param microtonal_ Pointer to the microtonal object
* @param fft_ Pointer to the FFTwrapper*/ * @param fft_ Pointer to the FFTwrapper*/
Part(Allocator &alloc, const SYNTH_T &synth,
Part(Allocator &alloc, const SYNTH_T &synth, const AbsTime &time,
const int& gzip_compression, const int& interpolation, const int& gzip_compression, const int& interpolation,
Microtonal *microtonal_, FFTwrapper *fft_); Microtonal *microtonal_, FFTwrapper *fft_);
/**Destructor*/ /**Destructor*/
@@ -97,6 +98,10 @@ class Part
SUBnoteParameters *subpars; SUBnoteParameters *subpars;
PADnoteParameters *padpars; PADnoteParameters *padpars;


bool active(void) const;
uint8_t sendto(void) const;
bool validNote(char note) const;

const static rtosc::Ports &ports; const static rtosc::Ports &ports;
} kit[NUM_KIT_ITEMS]; } kit[NUM_KIT_ITEMS];


@@ -118,6 +123,8 @@ class Part
unsigned char Pveloffs; //velocity offset unsigned char Pveloffs; //velocity offset
bool Pnoteon; //if the part receives NoteOn messages bool Pnoteon; //if the part receives NoteOn messages
int Pkitmode; //if the kitmode is enabled int Pkitmode; //if the kitmode is enabled

//XXX consider deprecating drum mode
bool Pdrummode; //if all keys are mapped and the system is 12tET (used for drums) bool Pdrummode; //if all keys are mapped and the system is 12tET (used for drums)


bool Ppolymode; //Part mode - 0=monophonic , 1=polyphonic bool Ppolymode; //Part mode - 0=monophonic , 1=polyphonic
@@ -156,25 +163,22 @@ class Part
const static rtosc::Ports &ports; const static rtosc::Ports &ports;


private: private:
void RunNote(unsigned k);
void KillNotePos(int pos);
void ReleaseNotePos(int pos);
void MonoMemRenote(); // MonoMem stuff. void MonoMemRenote(); // MonoMem stuff.
float getBaseFreq(int note, int keyshift) const;
float getVelocity(uint8_t velocity, uint8_t velocity_sense,
uint8_t velocity_offset) const;
void verifyKeyMode(void);
bool isPolyMode(void) const {return Ppolymode;}
bool isMonoMode(void) const {return !Ppolymode && !Plegatomode;};
bool isLegatoMode(void) const {return Plegatomode && !Pdrummode;}
bool isNonKit(void) const {return Pkitmode == 0;}
bool isMultiKit(void) const {return Pkitmode == 1;}
bool isSingleKit(void) const {return Pkitmode == 2;}


int killallnotes; //is set to 1 if I want to kill all notes

struct PartNotes {
NoteStatus status;
int note; //if there is no note playing, the "note"=-1
int itemsplaying;
struct {
SynthNote *adnote, *subnote, *padnote;
int sendtoparteffect;
} kititem[NUM_KIT_ITEMS];
int time;
};
bool killallnotes;

NotePool notePool;


int lastpos, lastposb; // To keep track of previously used pos and posb.
bool lastlegatomodevalid; // To keep track of previous legatomodevalid. bool lastlegatomodevalid; // To keep track of previous legatomodevalid.


// MonoMem stuff // MonoMem stuff
@@ -194,13 +198,12 @@ class Part
store the velocity and masterkeyshift values of a given note (the list only store note values). store the velocity and masterkeyshift values of a given note (the list only store note values).
For example 'monomem[note].velocity' would be the velocity value of the note 'note'.*/ For example 'monomem[note].velocity' would be the velocity value of the note 'note'.*/


PartNotes partnote[POLYPHONY];

float oldfreq; //this is used for portamento float oldfreq; //this is used for portamento
Microtonal *microtonal; Microtonal *microtonal;
FFTwrapper *fft; FFTwrapper *fft;
Allocator &memory; Allocator &memory;
const SYNTH_T &synth; const SYNTH_T &synth;
const AbsTime &time;
const int &gzip_compression, &interpolation; const int &gzip_compression, &interpolation;
}; };




+ 4
- 12
source/native-plugins/zynaddsubfx/Misc/PresetExtractor.cpp View File

@@ -30,7 +30,7 @@ static void dummy(const char *, rtosc::RtData&) {}
const rtosc::Ports real_preset_ports = const rtosc::Ports real_preset_ports =
{ {
{"scan-for-presets:", 0, 0, {"scan-for-presets:", 0, 0,
[](const char *msg, rtosc::RtData &d) {
[](const char *, rtosc::RtData &d) {
MiddleWare &mw = *(MiddleWare*)d.obj; MiddleWare &mw = *(MiddleWare*)d.obj;
mw.getPresetsStore().scanforpresets(); mw.getPresetsStore().scanforpresets();
auto &pre = mw.getPresetsStore().presets; auto &pre = mw.getPresetsStore().presets;
@@ -83,7 +83,7 @@ const rtosc::Ports real_preset_ports =
assert(false && "bad arguments"); assert(false && "bad arguments");
}}, }},
{"clipboard-type:", 0, 0, {"clipboard-type:", 0, 0,
[](const char *msg, rtosc::RtData &d) {
[](const char *, rtosc::RtData &d) {
const MiddleWare &mw = *(MiddleWare*)d.obj; const MiddleWare &mw = *(MiddleWare*)d.obj;
d.reply(d.loc, "s", mw.getPresetsStore().clipboard.type.c_str()); d.reply(d.loc, "s", mw.getPresetsStore().clipboard.type.c_str());
}}, }},
@@ -99,8 +99,8 @@ const rtosc::Ports real_preset_ports =
const rtosc::Ports preset_ports const rtosc::Ports preset_ports
{ {
{"scan-for-presets:", rDoc("Scan For Presets"), 0, dummy}, {"scan-for-presets:", rDoc("Scan For Presets"), 0, dummy},
{"copy:s:ss:si:ssi", rDoc("Copy <s> URL to <s> Name/Clipboard from subfield <i>"), 0, dummy},
{"paste:s:ss:si:ssi", rDoc("Paste <s> URL to <s> File-Name/Clipboard from subfield <i>"), 0, dummy},
{"copy:s:ss:si:ssi", rDoc("Copy (s)URL to (s) Name/Clipboard from subfield (i)"), 0, dummy},
{"paste:s:ss:si:ssi", rDoc("Paste (s) URL to (s) File-Name/Clipboard from subfield (i)"), 0, dummy},
{"clipboard-type:", rDoc("Type Stored In Clipboard"), 0, dummy}, {"clipboard-type:", rDoc("Type Stored In Clipboard"), 0, dummy},
{"delete:s", rDoc("Delete the given preset file"), 0, dummy}, {"delete:s", rDoc("Delete the given preset file"), 0, dummy},
}; };
@@ -123,14 +123,6 @@ const rtosc::Ports preset_ports
//Synth/Resonance.cpp: setpresettype("Presonance"); //Synth/Resonance.cpp: setpresettype("Presonance");




//Translate newer symbols to old preset types
std::vector<string> translate_preset_types(std::string metatype)
{
std::vector<string> results;
return results;
}


/***************************************************************************** /*****************************************************************************
* Implementation Methods * * Implementation Methods *
*****************************************************************************/ *****************************************************************************/


+ 42
- 0
source/native-plugins/zynaddsubfx/Misc/Time.h View File

@@ -0,0 +1,42 @@
#pragma once
#include <stdint.h>
#include "../globals.h"

class AbsTime
{
public:
AbsTime(const SYNTH_T &synth)
:frames(0),
s(synth){};
void operator++(){++frames;};
void operator++(int){frames++;};
int64_t time() const {return frames;};
float dt() const { return s.dt(); }
float framesPerSec() const { return 1/s.dt();}
int samplesPerFrame() const {return s.buffersize;}
private:
int64_t frames;
const SYNTH_T &s;
};

//Marker for an event relative to some position of the absolute timer
class RelTime
{
public:
RelTime(const AbsTime &t_, float sec)
:t(t_)
{
//Calculate time of event
double deltaFrames = sec*t.framesPerSec();
int64_t tmp = (int64_t)deltaFrames;
frame = t.time() + tmp;
sample = t.samplesPerFrame()*(deltaFrames-tmp);
}
bool inThisFrame() {return t.time() == frame;};
bool inPast() {return t.time() > frame;}
bool inFuture() {return t.time() < frame;}
private:
int64_t frame;
int32_t sample;
const AbsTime &t;
};

+ 2
- 2
source/native-plugins/zynaddsubfx/Misc/Util.h View File

@@ -157,12 +157,12 @@ char *rtosc_splat(const char *path, std::set<std::string>);
{STRINGIFY(name) "::i", rProp(parameter) rMap(min, 0) rMap(max, 127) DOC(__VA_ARGS__), NULL, rParamICb(name)} {STRINGIFY(name) "::i", rProp(parameter) rMap(min, 0) rMap(max, 127) DOC(__VA_ARGS__), NULL, rParamICb(name)}


#define rSelf(type) \ #define rSelf(type) \
{"self", rProp(internal) rMap(class, type) rDoc("port metadata"), 0, \
{"self:", rProp(internal) rMap(class, type) rDoc("port metadata"), 0, \
[](const char *, rtosc::RtData &d){ \ [](const char *, rtosc::RtData &d){ \
d.reply(d.loc, "b", sizeof(d.obj), &d.obj);}}\ d.reply(d.loc, "b", sizeof(d.obj), &d.obj);}}\


#define rPaste \ #define rPaste \
{"preset-type", rProp(internal), 0, \
{"preset-type:", rProp(internal) rDoc("clipboard type of object"), 0, \
[](const char *, rtosc::RtData &d){ \ [](const char *, rtosc::RtData &d){ \
rObject *obj = (rObject*)d.obj; \ rObject *obj = (rObject*)d.obj; \
d.reply(d.loc, "s", obj->type);}},\ d.reply(d.loc, "s", obj->type);}},\


+ 1
- 1
source/native-plugins/zynaddsubfx/Misc/WavFile.cpp View File

@@ -10,7 +10,7 @@
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2) for more details.
GNU General Public License (version 2 or later) for more details.


You should have received a copy of the GNU General Public License (version 2) You should have received a copy of the GNU General Public License (version 2)
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,


+ 1
- 1
source/native-plugins/zynaddsubfx/Misc/WavFile.h View File

@@ -13,7 +13,7 @@
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2) for more details.
GNU General Public License (version 2 or later) for more details.


You should have received a copy of the GNU General Public License (version 2) You should have received a copy of the GNU General Public License (version 2)
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,


+ 1
- 1
source/native-plugins/zynaddsubfx/Nio/WavEngine.cpp View File

@@ -9,7 +9,7 @@
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2) for more details.
GNU General Public License (version 2 or later) for more details.


You should have received a copy of the GNU General Public License (version 2) You should have received a copy of the GNU General Public License (version 2)
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,


+ 1
- 1
source/native-plugins/zynaddsubfx/Nio/WavEngine.h View File

@@ -13,7 +13,7 @@
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2) for more details.
GNU General Public License (version 2 or later) for more details.


You should have received a copy of the GNU General Public License (version 2) You should have received a copy of the GNU General Public License (version 2)
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,


+ 33
- 50
source/native-plugins/zynaddsubfx/Params/ADnoteParameters.cpp View File

@@ -62,11 +62,11 @@ static const Ports voicePorts = {
rParamZyn(Unison_vibratto, "Subvoice vibratto"), rParamZyn(Unison_vibratto, "Subvoice vibratto"),
rParamZyn(Unison_vibratto_speed, "Subvoice vibratto speed"), rParamZyn(Unison_vibratto_speed, "Subvoice vibratto speed"),
rOption(Unison_invert_phase, rOptions(none, random, 50%, 33%, 25%), "Subvoice Phases"), rOption(Unison_invert_phase, rOptions(none, random, 50%, 33%, 25%), "Subvoice Phases"),
rOption(Type, rOptions(Sound,Noise), "Type of Sound"),
rOption(Type, rOptions(Sound,White,Pink), "Type of Sound"),
rParamZyn(PDelay, "Voice Startup Delay"), rParamZyn(PDelay, "Voice Startup Delay"),
rToggle(Presonance, "Resonance Enable"), rToggle(Presonance, "Resonance Enable"),
rParamZyn(Pextoscil, "External Oscilator Selection"),
rParamZyn(PextFMoscil, "External FM Oscilator Selection"),
rParamI(Pextoscil, rMap(min, -1), rMap(max, 16), "External Oscilator Selection"),
rParamI(PextFMoscil, rMap(min, -1), rMap(max, 16), "External FM Oscilator Selection"),
rParamZyn(Poscilphase, "Oscillator Phase"), rParamZyn(Poscilphase, "Oscillator Phase"),
rParamZyn(PFMoscilphase, "FM Oscillator Phase"), rParamZyn(PFMoscilphase, "FM Oscillator Phase"),
rToggle(Pfilterbypass, "Filter Bypass"), rToggle(Pfilterbypass, "Filter Bypass"),
@@ -108,14 +108,19 @@ static const Ports voicePorts = {


//weird stuff for PCoarseDetune //weird stuff for PCoarseDetune
{"detunevalue:", NULL, NULL, [](const char *, RtData &d)
{"detunevalue:", rMap(unit,cents) rDoc("Get detune in cents"), NULL,
[](const char *, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
unsigned detuneType =
obj->PDetuneType == 0 ? *(obj->GlobalPDetuneType)
: obj->PDetuneType;
//TODO check if this is accurate or if PCoarseDetune is utilized //TODO check if this is accurate or if PCoarseDetune is utilized
//TODO do the same for the other engines //TODO do the same for the other engines
d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune));
d.reply(d.loc, "f", getdetune(detuneType, 0, obj->PDetune));
}}, }},
{"octave::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"octave::c:i", rProp(parameter) rDoc("Octave note offset"), NULL,
[](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -128,7 +133,8 @@ static const Ports voicePorts = {
obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024; obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024;
} }
}}, }},
{"coarsedetune::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"coarsedetune::c:i", rProp(parameter) rDoc("Coarse note detune"), NULL,
[](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -143,14 +149,18 @@ static const Ports voicePorts = {
}}, }},
//weird stuff for PCoarseDetune //weird stuff for PCoarseDetune
{"FMdetunevalue:", NULL, NULL, [](const char *, RtData &d)
{"FMdetunevalue:", rMap(unit,cents) rDoc("Get modulator detune"), NULL, [](const char *, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
unsigned detuneType =
obj->PFMDetuneType == 0 ? *(obj->GlobalPDetuneType)
: obj->PFMDetuneType;
//TODO check if this is accurate or if PCoarseDetune is utilized //TODO check if this is accurate or if PCoarseDetune is utilized
//TODO do the same for the other engines //TODO do the same for the other engines
d.reply(d.loc, "f", getdetune(obj->PFMDetuneType, 0, obj->PFMDetune));
d.reply(d.loc, "f", getdetune(detuneType, 0, obj->PFMDetune));
}}, }},
{"FMoctave::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"FMoctave::c:i", rProp(parameter) rDoc("Octave note offset for modulator"), NULL,
[](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -163,7 +173,8 @@ static const Ports voicePorts = {
obj->PFMCoarseDetune = k*1024 + obj->PFMCoarseDetune%1024; obj->PFMCoarseDetune = k*1024 + obj->PFMCoarseDetune%1024;
} }
}}, }},
{"FMcoarsedetune::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"FMcoarsedetune::c:i", rProp(parameter) rDoc("Coarse note detune for modulator"),
NULL, [](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -178,7 +189,8 @@ static const Ports voicePorts = {
}}, }},


//Reader //Reader
{"unisonFrequencySpreadCents:", NULL, NULL, [](const char *, RtData &d)
{"unisonFrequencySpreadCents:", rMap(unit,cents) rDoc("Unison Frequency Spread"),
NULL, [](const char *, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
d.reply(d.loc, "f", obj->getUnisonFrequencySpreadCents()); d.reply(d.loc, "f", obj->getUnisonFrequencySpreadCents());
@@ -224,12 +236,14 @@ static const Ports globalPorts = {
rParamZyn(Hrandgrouping, "How randomness is applied to multiple voices using the same oscil"), rParamZyn(Hrandgrouping, "How randomness is applied to multiple voices using the same oscil"),


//weird stuff for PCoarseDetune //weird stuff for PCoarseDetune
{"detunevalue:", NULL, NULL, [](const char *, RtData &d)
{"detunevalue:", rMap(unit,cents) rDoc("Get detune in cents"), NULL,
[](const char *, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune)); d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune));
}}, }},
{"octave::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"octave::c:i", rProp(parameter) rDoc("Octave note offset"), NULL,
[](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -242,7 +256,8 @@ static const Ports globalPorts = {
obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024; obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024;
} }
}}, }},
{"coarsedetune::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"coarsedetune::c:i", rProp(parameter) rDoc("Coarse note detune"), NULL,
[](const char *msg, RtData &d)
{ {
rObject *obj = (rObject *)d.obj; rObject *obj = (rObject *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -279,8 +294,10 @@ ADnoteParameters::ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_)
fft = fft_; fft = fft_;




for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
VoicePar[nvoice].GlobalPDetuneType = &GlobalPar.PDetuneType;
EnableVoice(synth, nvoice); EnableVoice(synth, nvoice);
}


defaults(); defaults();
} }
@@ -524,40 +541,6 @@ ADnoteParameters::~ADnoteParameters()
KillVoice(nvoice); KillVoice(nvoice);
} }


int ADnoteParameters::get_unison_size_index(int nvoice) const
{
int index = 0;
if(nvoice >= NUM_VOICES)
return 0;
int unison = VoicePar[nvoice].Unison_size;

while(1) {
if(ADnote_unison_sizes[index] >= unison)
return index;

if(ADnote_unison_sizes[index] == 0)
return index - 1;

index++;
}
return 0;
}

void ADnoteParameters::set_unison_size_index(int nvoice, int index) {
int unison = 1;
for(int i = 0; i <= index; ++i) {
unison = ADnote_unison_sizes[i];
if(unison == 0) {
unison = ADnote_unison_sizes[i - 1];
break;
}
}

VoicePar[nvoice].Unison_size = unison;
}



void ADnoteParameters::add2XMLsection(XMLwrapper *xml, int n) void ADnoteParameters::add2XMLsection(XMLwrapper *xml, int n)
{ {
int nvoice = n; int nvoice = n;


+ 2
- 4
source/native-plugins/zynaddsubfx/Params/ADnoteParameters.h View File

@@ -29,8 +29,6 @@
enum FMTYPE { enum FMTYPE {
NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD
}; };
static const int ADnote_unison_sizes[] =
{1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0};


/*****************************************************************/ /*****************************************************************/
/* GLOBAL PARAMETERS */ /* GLOBAL PARAMETERS */
@@ -284,6 +282,8 @@ struct ADnoteVoiceParam {
unsigned char PFMAmpEnvelopeEnabled; unsigned char PFMAmpEnvelopeEnabled;
EnvelopeParams *FMAmpEnvelope; EnvelopeParams *FMAmpEnvelope;


unsigned char *GlobalPDetuneType;

static const rtosc::Ports &ports; static const rtosc::Ports &ports;
}; };


@@ -306,8 +306,6 @@ class ADnoteParameters:public PresetsArray


float getBandwidthDetuneMultiplier() const; float getBandwidthDetuneMultiplier() const;
float getUnisonFrequencySpreadCents(int nvoice) const; float getUnisonFrequencySpreadCents(int nvoice) const;
int get_unison_size_index(int nvoice) const;
void set_unison_size_index(int nvoice, int index);
static const rtosc::Ports &ports; static const rtosc::Ports &ports;
void defaults(int n); //n is the nvoice void defaults(int n); //n is the nvoice
void add2XMLsection(XMLwrapper *xml, int n); void add2XMLsection(XMLwrapper *xml, int n);


+ 8
- 1
source/native-plugins/zynaddsubfx/Params/EnvelopeParams.cpp View File

@@ -22,6 +22,7 @@


#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <rtosc/ports.h> #include <rtosc/ports.h>
#include <rtosc/port-sugar.h> #include <rtosc/port-sugar.h>


@@ -131,7 +132,13 @@ void EnvelopeParams::paste(const EnvelopeParams &ep)
//Avoid undefined behavior //Avoid undefined behavior
if(&ep == this) if(&ep == this)
return; return;
memcpy((char*)this, (const char*)&ep, sizeof(*this));


char *base = (char*)&this->Pfreemode;
char *end = (char*)&this->DR_val;
assert(end-base > 0);
memcpy((char*)&this->Pfreemode, (const char*)&ep.Pfreemode, 1+end-base);
} }


float EnvelopeParams::getdt(char i) const float EnvelopeParams::getdt(char i) const


+ 5
- 4
source/native-plugins/zynaddsubfx/Params/FilterParams.cpp View File

@@ -105,13 +105,14 @@ const rtosc::Ports FilterParams::ports = {
if(rtosc_narguments(msg)) if(rtosc_narguments(msg))
rChangeCb; rChangeCb;
}}, }},
{"centerfreq:", NULL, NULL,
[](const char *, RtData &d) {
{"centerfreq:", rDoc("Get the center frequency of the formant's graph"),
NULL, [](const char *, RtData &d) {
FilterParams *obj = (FilterParams *) d.obj; FilterParams *obj = (FilterParams *) d.obj;
d.reply(d.loc, "f", obj->getcenterfreq()); d.reply(d.loc, "f", obj->getcenterfreq());
}}, }},
{"octavesfreq:", NULL, NULL,
[](const char *, RtData &d) {
{"octavesfreq:",
rDoc("Get the number of octave that the formant functions applies to"),
NULL, [](const char *, RtData &d) {
FilterParams *obj = (FilterParams *) d.obj; FilterParams *obj = (FilterParams *) d.obj;
d.reply(d.loc, "f", obj->getoctavesfreq()); d.reply(d.loc, "f", obj->getoctavesfreq());
}}, }},


+ 0
- 4
source/native-plugins/zynaddsubfx/Params/LFOParams.cpp View File

@@ -49,8 +49,6 @@ static const rtosc::Ports _ports = {


const rtosc::Ports &LFOParams::ports = _ports; const rtosc::Ports &LFOParams::ports = _ports;


int LFOParams::time;

LFOParams::LFOParams() LFOParams::LFOParams()
{ {
Dfreq = 64; Dfreq = 64;
@@ -61,7 +59,6 @@ LFOParams::LFOParams()
Ddelay = 0; Ddelay = 0;
Dcontinous = 0; Dcontinous = 0;
fel = 0; fel = 0;
time = 0;


defaults(); defaults();
} }
@@ -94,7 +91,6 @@ LFOParams::LFOParams(char Pfreq_,
Ddelay = Pdelay_; Ddelay = Pdelay_;
Dcontinous = Pcontinous_; Dcontinous = Pcontinous_;
fel = fel_; fel = fel_;
time = 0;


defaults(); defaults();
} }


+ 8
- 1
source/native-plugins/zynaddsubfx/Params/LFOParams.h View File

@@ -28,6 +28,14 @@


class XMLwrapper; class XMLwrapper;


#define LFO_SINE 0
#define LFO_TRIANGLE 1
#define LFO_SQUARE 2
#define LFO_RAMPUP 3
#define LFO_RAMPDOWN 4
#define LFO_EXP_DOWN1 5
#define LFO_EXP_DOWN2 6

class LFOParams:public Presets class LFOParams:public Presets
{ {
public: public:
@@ -60,7 +68,6 @@ class LFOParams:public Presets
unsigned char Pstretch; /**<how the LFO is "stretched" according the note frequency (64=no stretch)*/ unsigned char Pstretch; /**<how the LFO is "stretched" according the note frequency (64=no stretch)*/


int fel; //what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter) int fel; //what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter)
static int time; //is used by Pcontinous parameter


static const rtosc::Ports &ports; static const rtosc::Ports &ports;
private: private:


+ 8
- 7
source/native-plugins/zynaddsubfx/Params/PADnoteParameters.cpp View File

@@ -90,8 +90,6 @@ static const rtosc::Ports PADnotePorts =


PC(fixedfreq), PC(fixedfreq),
PC(fixedfreqET), PC(fixedfreqET),
//TODO detune, coarse detune
PC(DetuneType),
PC(Stereo), PC(Stereo),
PC(Panning), PC(Panning),
PC(AmpVelocityScaleFunction), PC(AmpVelocityScaleFunction),
@@ -115,7 +113,7 @@ static const rtosc::Ports PADnotePorts =
d.reply(d.loc, "i", p->Pbandwidth); d.reply(d.loc, "i", p->Pbandwidth);
}}}, }}},
{"bandwidthvalue:", NULL, NULL,
{"bandwidthvalue:", rMap(unit, cents) rDoc("Get Bandwidth"), NULL,
[](const char *, rtosc::RtData &d) { [](const char *, rtosc::RtData &d) {
PADnoteParameters *p = ((PADnoteParameters*)d.obj); PADnoteParameters *p = ((PADnoteParameters*)d.obj);
d.reply(d.loc, "f", p->setPbandwidth(p->Pbandwidth)); d.reply(d.loc, "f", p->setPbandwidth(p->Pbandwidth));
@@ -143,7 +141,7 @@ static const rtosc::Ports PADnotePorts =
d.reply(d.loc, "b", n*sizeof(float), tmp); d.reply(d.loc, "b", n*sizeof(float), tmp);
d.reply(d.loc, "i", realbw); d.reply(d.loc, "i", realbw);
delete[] tmp;}}, delete[] tmp;}},
{"sample#64:ifb", rDoc("Nothing to see here"), 0,
{"sample#64:ifb", rProp(internal) rDoc("Nothing to see here"), 0,
[](const char *m, rtosc::RtData &d) [](const char *m, rtosc::RtData &d)
{ {
PADnoteParameters *p = (PADnoteParameters*)d.obj; PADnoteParameters *p = (PADnoteParameters*)d.obj;
@@ -157,12 +155,14 @@ static const rtosc::Ports PADnotePorts =
//XXX TODO memory managment (deallocation of smp buffer) //XXX TODO memory managment (deallocation of smp buffer)
}}, }},
//weird stuff for PCoarseDetune //weird stuff for PCoarseDetune
{"detunevalue:", NULL, NULL, [](const char *, RtData &d)
{"detunevalue:", rMap(unit,cents) rDoc("Get detune value"), NULL,
[](const char *, RtData &d)
{ {
PADnoteParameters *obj = (PADnoteParameters *)d.obj; PADnoteParameters *obj = (PADnoteParameters *)d.obj;
d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune)); d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune));
}}, }},
{"octave::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"octave::c:i", rProp(parameter) rDoc("Octave note offset"), NULL,
[](const char *msg, RtData &d)
{ {
PADnoteParameters *obj = (PADnoteParameters *)d.obj; PADnoteParameters *obj = (PADnoteParameters *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -175,7 +175,8 @@ static const rtosc::Ports PADnotePorts =
obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024; obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024;
} }
}}, }},
{"coarsedetune::c:i", NULL, NULL, [](const char *msg, RtData &d)
{"coarsedetune::c:i", rProp(parameter) rDoc("Coarse note detune"), NULL,
[](const char *msg, RtData &d)
{ {
PADnoteParameters *obj = (PADnoteParameters *)d.obj; PADnoteParameters *obj = (PADnoteParameters *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {


+ 4
- 2
source/native-plugins/zynaddsubfx/Params/SUBnoteParameters.cpp View File

@@ -93,7 +93,8 @@ static const rtosc::Ports SUBnotePorts = {
d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune)); d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune));
}}, }},
//weird stuff for PCoarseDetune //weird stuff for PCoarseDetune
{"octave::c:i", rDoc("Note octave shift"), NULL, [](const char *msg, RtData &d)
{"octave::c:i", rProp(parameter) rDoc("Note octave shift"), NULL,
[](const char *msg, RtData &d)
{ {
SUBnoteParameters *obj = (SUBnoteParameters *)d.obj; SUBnoteParameters *obj = (SUBnoteParameters *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {
@@ -106,7 +107,8 @@ static const rtosc::Ports SUBnotePorts = {
obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024; obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024;
} }
}}, }},
{"coarsedetune::c:i", rDoc("Note coarse detune"), NULL, [](const char *msg, RtData &d)
{"coarsedetune::c:i", rProp(parameter) rDoc("Note coarse detune"), NULL,
[](const char *msg, RtData &d)
{ {
SUBnoteParameters *obj = (SUBnoteParameters *)d.obj; SUBnoteParameters *obj = (SUBnoteParameters *)d.obj;
if(!rtosc_narguments(msg)) { if(!rtosc_narguments(msg)) {


+ 70
- 30
source/native-plugins/zynaddsubfx/Synth/ADnote.cpp View File

@@ -49,7 +49,6 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars)
NoteEnabled = ON; NoteEnabled = ON;
basefreq = spars.frequency; basefreq = spars.frequency;
velocity = spars.velocity; velocity = spars.velocity;
time = 0.0f;
stereo = pars.GlobalPar.PStereo; stereo = pars.GlobalPar.PStereo;


NoteGlobalPar.Detune = getdetune(pars.GlobalPar.PDetuneType, NoteGlobalPar.Detune = getdetune(pars.GlobalPar.PDetuneType,
@@ -87,6 +86,9 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars)
NoteGlobalPar.Punch.Enabled = 0; NoteGlobalPar.Punch.Enabled = 0;


for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
for (int i = 0; i < 14; i++)
pinking[nvoice][i] = 0.0;

pars.VoicePar[nvoice].OscilSmp->newrandseed(prng()); pars.VoicePar[nvoice].OscilSmp->newrandseed(prng());
NoteVoicePar[nvoice].OscilSmp = NULL; NoteVoicePar[nvoice].OscilSmp = NULL;
NoteVoicePar[nvoice].FMSmp = NULL; NoteVoicePar[nvoice].FMSmp = NULL;
@@ -106,6 +108,10 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars)
if(unison < 1) if(unison < 1)
unison = 1; unison = 1;


// Since noise unison of greater than two is touch goofy...
if (pars.VoicePar[nvoice].Type != 0 && unison > 2)
unison = 2;

//compute unison //compute unison
unison_size[nvoice] = unison; unison_size[nvoice] = unison;


@@ -397,6 +403,13 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars)
initparameters(); initparameters();
} }


SynthNote *ADnote::cloneLegato(void)
{
SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
(bool)portamento, legato.param.midinote, true};
return memory.alloc<ADnote>(&pars, sp);
}

// ADlegatonote: This function is (mostly) a copy of ADnote(...) and // ADlegatonote: This function is (mostly) a copy of ADnote(...) and
// initparameters() stuck together with some lines removed so that it // initparameters() stuck together with some lines removed so that it
// only alter the already playing note (to perform legato). It is // only alter the already playing note (to perform legato). It is
@@ -711,6 +724,7 @@ void ADnote::initparameters()


// Global Parameters // Global Parameters
NoteGlobalPar.initparameters(pars.GlobalPar, synth, NoteGlobalPar.initparameters(pars.GlobalPar, synth,
time,
memory, basefreq, velocity, memory, basefreq, velocity,
stereo); stereo);


@@ -753,7 +767,7 @@ void ADnote::initparameters()
} }


if(param.PAmpLfoEnabled) { if(param.PAmpLfoEnabled) {
vce.AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, synth.dt());
vce.AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time);
newamplitude[nvoice] *= vce.AmpLfo->amplfoout(); newamplitude[nvoice] *= vce.AmpLfo->amplfoout();
} }


@@ -762,7 +776,7 @@ void ADnote::initparameters()
vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt());


if(param.PFreqLfoEnabled) if(param.PFreqLfoEnabled)
vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, synth.dt());
vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time);


/* Voice Filter Parameters Init */ /* Voice Filter Parameters Init */
if(param.PFilterEnabled != 0) { if(param.PFilterEnabled != 0) {
@@ -776,7 +790,7 @@ void ADnote::initparameters()
vce.FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); vce.FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt());


if(param.PFilterLfoEnabled) if(param.PFilterLfoEnabled)
vce.FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, synth.dt());
vce.FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time);


vce.FilterFreqTracking = vce.FilterFreqTracking =
param.VoiceFilter->getfreqtracking(basefreq); param.VoiceFilter->getfreqtracking(basefreq);
@@ -1071,7 +1085,6 @@ void ADnote::computecurrentparameters()
} }
} }
} }
time += synth.buffersize_f / synth.samplerate_f;
} }




@@ -1417,7 +1430,7 @@ inline void ADnote::ComputeVoiceOscillatorPitchModulation(int /*nvoice*/)
/* /*
* Computes the Noise * Computes the Noise
*/ */
inline void ADnote::ComputeVoiceNoise(int nvoice)
inline void ADnote::ComputeVoiceWhiteNoise(int nvoice)
{ {
for(int k = 0; k < unison_size[nvoice]; ++k) { for(int k = 0; k < unison_size[nvoice]; ++k) {
float *tw = tmpwave_unison[k]; float *tw = tmpwave_unison[k];
@@ -1426,6 +1439,25 @@ inline void ADnote::ComputeVoiceNoise(int nvoice)
} }
} }


inline void ADnote::ComputeVoicePinkNoise(int nvoice)
{
for(int k = 0; k < unison_size[nvoice]; ++k) {
float *tw = tmpwave_unison[k];
float *f = &pinking[nvoice][k > 0 ? 7 : 0];
for(int i = 0; i < synth.buffersize; ++i) {
float white = (RND-0.5)/4.0;
f[0] = 0.99886*f[0]+white*0.0555179;
f[1] = 0.99332*f[1]+white*0.0750759;
f[2] = 0.96900*f[2]+white*0.1538520;
f[3] = 0.86650*f[3]+white*0.3104856;
f[4] = 0.55000*f[4]+white*0.5329522;
f[5] = -0.7616*f[5]-white*0.0168980;
tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362;
f[6] = white*0.115926;
}
}
}





/* /*
@@ -1448,27 +1480,34 @@ int ADnote::noteout(float *outl, float *outr)
if((NoteVoicePar[nvoice].Enabled != ON) if((NoteVoicePar[nvoice].Enabled != ON)
|| (NoteVoicePar[nvoice].DelayTicks > 0)) || (NoteVoicePar[nvoice].DelayTicks > 0))
continue; continue;
if(NoteVoicePar[nvoice].noisetype == 0) //voice mode=sound
switch(NoteVoicePar[nvoice].FMEnabled) {
case MORPH:
ComputeVoiceOscillatorMorph(nvoice);
break;
case RING_MOD:
ComputeVoiceOscillatorRingModulation(nvoice);
break;
case PHASE_MOD:
ComputeVoiceOscillatorFrequencyModulation(nvoice, 0);
break;
case FREQ_MOD:
ComputeVoiceOscillatorFrequencyModulation(nvoice, 1);
break;
//case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break;
default:
ComputeVoiceOscillator_LinearInterpolation(nvoice);
//if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice);
}
else
ComputeVoiceNoise(nvoice);
switch (NoteVoicePar[nvoice].noisetype) {
case 0: //voice mode=sound
switch(NoteVoicePar[nvoice].FMEnabled) {
case MORPH:
ComputeVoiceOscillatorMorph(nvoice);
break;
case RING_MOD:
ComputeVoiceOscillatorRingModulation(nvoice);
break;
case PHASE_MOD:
ComputeVoiceOscillatorFrequencyModulation(nvoice, 0);
break;
case FREQ_MOD:
ComputeVoiceOscillatorFrequencyModulation(nvoice, 1);
break;
//case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break;
default:
ComputeVoiceOscillator_LinearInterpolation(nvoice);
//if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice);
}
break;
case 1:
ComputeVoiceWhiteNoise(nvoice);
break;
default:
ComputeVoicePinkNoise(nvoice);
break;
}
// Voice Processing // Voice Processing




@@ -1772,15 +1811,16 @@ void ADnote::Global::kill(Allocator &memory)


void ADnote::Global::initparameters(const ADnoteGlobalParam &param, void ADnote::Global::initparameters(const ADnoteGlobalParam &param,
const SYNTH_T &synth, const SYNTH_T &synth,
const AbsTime &time,
class Allocator &memory, class Allocator &memory,
float basefreq, float velocity, float basefreq, float velocity,
bool stereo) bool stereo)
{ {
FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt());
FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, synth.dt());
FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time);


AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt()); AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt());
AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, synth.dt());
AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time);


Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB
* VelF(velocity, param.PAmpVelocityScaleFunction); //sensing * VelF(velocity, param.PAmpVelocityScaleFunction); //sensing
@@ -1794,7 +1834,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam &param,
GlobalFilterR = NULL; GlobalFilterR = NULL;


FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt());
FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, synth.dt());
FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time);
FilterQ = param.GlobalFilter->getq(); FilterQ = param.GlobalFilter->getq();
FilterFreqTracking = param.GlobalFilter->getfreqtracking(basefreq); FilterFreqTracking = param.GlobalFilter->getfreqtracking(basefreq);
} }

+ 7
- 3
source/native-plugins/zynaddsubfx/Synth/ADnote.h View File

@@ -53,6 +53,8 @@ class ADnote:public SynthNote
int noteout(float *outl, float *outr); int noteout(float *outl, float *outr);
void releasekey(); void releasekey();
int finished() const; int finished() const;

virtual SynthNote *cloneLegato(void) override;
private: private:


/**Changes the frequency of an oscillator. /**Changes the frequency of an oscillator.
@@ -97,7 +99,8 @@ class ADnote:public SynthNote
inline void ComputeVoiceOscillatorPitchModulation(int nvoice); inline void ComputeVoiceOscillatorPitchModulation(int nvoice);


/**Generate Noise Samples for Voice*/ /**Generate Noise Samples for Voice*/
inline void ComputeVoiceNoise(int nvoice);
inline void ComputeVoiceWhiteNoise(int nvoice);
inline void ComputeVoicePinkNoise(int nvoice);


/**Fadein in a way that removes clicks but keep sound "punchy"*/ /**Fadein in a way that removes clicks but keep sound "punchy"*/
inline void fadein(float *smps) const; inline void fadein(float *smps) const;
@@ -119,6 +122,7 @@ class ADnote:public SynthNote
void kill(Allocator &memory); void kill(Allocator &memory);
void initparameters(const ADnoteGlobalParam &param, void initparameters(const ADnoteGlobalParam &param,
const SYNTH_T &synth, const SYNTH_T &synth,
const AbsTime &time,
class Allocator &memory, class Allocator &memory,
float basefreq, float velocity, float basefreq, float velocity,
bool stereo); bool stereo);
@@ -246,8 +250,8 @@ class ADnote:public SynthNote
/* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */
/********************************************************/ /********************************************************/


//time from the start of the note
float time;
//pinking filter (Paul Kellet)
float pinking[NUM_VOICES][14];


//the size of unison for a single voice //the size of unison for a single voice
int unison_size[NUM_VOICES]; int unison_size[NUM_VOICES];


+ 58
- 72
source/native-plugins/zynaddsubfx/Synth/LFO.cpp View File

@@ -28,8 +28,10 @@
#include <cstdio> #include <cstdio>
#include <cmath> #include <cmath>


LFO::LFO(const LFOParams &lfopars, float basefreq, float dt_)
:dt(dt_)
LFO::LFO(const LFOParams &lfopars, float basefreq, const AbsTime &t)
:delayTime(t, lfopars.Pdelay / 127.0f * 4.0f), //0..4 sec
waveShape(lfopars.PLFOtype),
deterministic(!lfopars.Pfreqrand)
{ {
int stretch = lfopars.Pstretch; int stretch = lfopars.Pstretch;
if(stretch == 0) if(stretch == 0)
@@ -38,24 +40,24 @@ LFO::LFO(const LFOParams &lfopars, float basefreq, float dt_)
//max 2x/octave //max 2x/octave
const float lfostretch = powf(basefreq / 440.0f, (stretch - 64.0f) / 63.0f); const float lfostretch = powf(basefreq / 440.0f, (stretch - 64.0f) / 63.0f);


float lfofreq =
const float lfofreq =
(powf(2, lfopars.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch; (powf(2, lfopars.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch;
incx = fabs(lfofreq) * dt;
phaseInc = fabs(lfofreq) * t.dt();


if(!lfopars.Pcontinous) { if(!lfopars.Pcontinous) {
if(lfopars.Pstartphase == 0) if(lfopars.Pstartphase == 0)
x = RND;
phase = RND;
else else
x = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f, 1.0f);
phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f, 1.0f);
} }
else { else {
const float tmp = fmod(lfopars.time * incx, 1.0f);
x = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f + tmp, 1.0f);
const float tmp = fmod(t.time() * phaseInc, 1.0f);
phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f + tmp, 1.0f);
} }


//Limit the Frequency(or else...) //Limit the Frequency(or else...)
if(incx > 0.49999999f)
incx = 0.499999999f;
if(phaseInc > 0.49999999f)
phaseInc = 0.499999999f;




lfornd = limit(lfopars.Prandomness / 127.0f, 0.0f, 1.0f); lfornd = limit(lfopars.Prandomness / 127.0f, 0.0f, 1.0f);
@@ -70,88 +72,72 @@ LFO::LFO(const LFOParams &lfopars, float basefreq, float dt_)
break; //in octave break; //in octave
default: default:
lfointensity = powf(2, lfopars.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi lfointensity = powf(2, lfopars.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi
x -= 0.25f; //chance the starting phase
phase -= 0.25f; //chance the starting phase
break; break;
} }


amp1 = (1 - lfornd) + lfornd * RND; amp1 = (1 - lfornd) + lfornd * RND;
amp2 = (1 - lfornd) + lfornd * RND; amp2 = (1 - lfornd) + lfornd * RND;
lfotype = lfopars.PLFOtype;
lfodelay = lfopars.Pdelay / 127.0f * 4.0f; //0..4 sec
incrnd = nextincrnd = 1.0f; incrnd = nextincrnd = 1.0f;
freqrndenabled = (lfopars.Pfreqrand != 0);
computenextincrnd();
computenextincrnd(); //twice because I want incrnd & nextincrnd to be random
computeNextFreqRnd();
computeNextFreqRnd(); //twice because I want incrnd & nextincrnd to be random
} }


LFO::~LFO() LFO::~LFO()
{} {}


/*
* LFO out
*/
float LFO::lfoout()
float LFO::baseOut(const char waveShape, const float phase) const
{ {
float out;
switch(lfotype) {
case 1: //LFO_TRIANGLE
if((x >= 0.0f) && (x < 0.25f))
out = 4.0f * x;
switch(waveShape) {
case LFO_TRIANGLE:
if(phase >= 0.0f && phase < 0.25f)
return 4.0f * phase;
else if(phase > 0.25f && phase < 0.75f)
return 2 - 4 * phase;
else else
if((x > 0.25f) && (x < 0.75f))
out = 2 - 4 * x;
else
out = 4.0f * x - 4.0f;
return 4.0f * phase - 4.0f;
break; break;
case 2: //LFO_SQUARE
if(x < 0.5f)
out = -1;
case LFO_SQUARE:
if(phase < 0.5f)
return -1;
else else
out = 1;
break;
case 3: //LFO_RAMPUP
out = (x - 0.5f) * 2.0f;
return 1;
break; break;
case 4: //LFO_RAMPDOWN
out = (0.5f - x) * 2.0f;
break;
case 5: //LFO_EXP_DOWN 1
out = powf(0.05f, x) * 2.0f - 1.0f;
break;
case 6: //LFO_EXP_DOWN 2
out = powf(0.001f, x) * 2.0f - 1.0f;
break;
default:
out = cosf(x * 2.0f * PI); //LFO_SINE
case LFO_RAMPUP: return (phase - 0.5f) * 2.0f;
case LFO_RAMPDOWN: return (0.5f - phase) * 2.0f;
case LFO_EXP_DOWN1: return powf(0.05f, phase) * 2.0f - 1.0f;
case LFO_EXP_DOWN2: return powf(0.001f, phase) * 2.0f - 1.0f;
default: return cosf(phase * 2.0f * PI); //LFO_SINE
} }
}




if((lfotype == 0) || (lfotype == 1))
out *= lfointensity * (amp1 + x * (amp2 - amp1));
float LFO::lfoout()
{
float out = baseOut(waveShape, phase);

if(waveShape == LFO_SINE || waveShape == LFO_TRIANGLE)
out *= lfointensity * (amp1 + phase * (amp2 - amp1));
else else
out *= lfointensity * amp2; out *= lfointensity * amp2;
if(lfodelay < 0.00001f) {
if(freqrndenabled == 0)
x += incx;
else {
float tmp = (incrnd * (1.0f - x) + nextincrnd * x);
if(tmp > 1.0f)
tmp = 1.0f;
else
if(tmp < 0.0f)
tmp = 0.0f;
x += incx * tmp;
}
if(x >= 1) {
x = fmod(x, 1.0f);
amp1 = amp2;
amp2 = (1 - lfornd) + lfornd * RND;

computenextincrnd();
}

if(delayTime.inFuture())
return out;

//Start oscillating
if(deterministic)
phase += phaseInc;
else {
const float tmp = (incrnd * (1.0f - phase) + nextincrnd * phase);
phase += phaseInc * limit(tmp, 0.0f, 1.0f);
}
if(phase >= 1) {
phase = fmod(phase, 1.0f);
amp1 = amp2;
amp2 = (1 - lfornd) + lfornd * RND;

computeNextFreqRnd();
} }
else
lfodelay -= dt;
return out; return out;
} }


@@ -164,9 +150,9 @@ float LFO::amplfoout()
} }




void LFO::computenextincrnd()
void LFO::computeNextFreqRnd()
{ {
if(freqrndenabled == 0)
if(deterministic)
return; return;
incrnd = nextincrnd; incrnd = nextincrnd;
nextincrnd = powf(0.5f, lfofreqrnd) + RND * (powf(2.0f, lfofreqrnd) - 1.0f); nextincrnd = powf(0.5f, lfofreqrnd) + RND * (powf(2.0f, lfofreqrnd) - 1.0f);


+ 25
- 12
source/native-plugins/zynaddsubfx/Synth/LFO.h View File

@@ -24,8 +24,9 @@
#define LFO_H #define LFO_H


#include "../globals.h" #include "../globals.h"
#include "../Misc/Time.h"


/**Class for creating Low Frequency Ocillators*/
/**Class for creating Low Frequency Oscillators*/
class LFO class LFO
{ {
public: public:
@@ -34,24 +35,36 @@ class LFO
* @param lfopars pointer to a LFOParams object * @param lfopars pointer to a LFOParams object
* @param basefreq base frequency of LFO * @param basefreq base frequency of LFO
*/ */
LFO(const LFOParams &lfopars, float basefreq, float dt);
/**Deconstructor*/
LFO(const LFOParams &lfopars, float basefreq, const AbsTime &t);
~LFO(); ~LFO();

float lfoout(); float lfoout();
float amplfoout(); float amplfoout();
private: private:
float x;
float incx, incrnd, nextincrnd;
float amp1, amp2; // used for randomness
float baseOut(const char waveShape, const float phase) const;
//Phase of Oscillator
float phase;
//Phase Increment Per Frame
float phaseInc;
//Frequency Randomness
float incrnd, nextincrnd;
//Amplitude Randomness
float amp1, amp2;

//Intensity of the wave
float lfointensity; float lfointensity;
//Amount Randomness
float lfornd, lfofreqrnd; float lfornd, lfofreqrnd;
float lfodelay;
const float dt;
/**\todo see if an enum would be better here*/
char lfotype;
int freqrndenabled;


void computenextincrnd();
//Delay before starting
RelTime delayTime;

char waveShape;

//If After initialization there are no calls to random number gen.
bool deterministic;

void computeNextFreqRnd(void);
}; };


#endif #endif

+ 112
- 71
source/native-plugins/zynaddsubfx/Synth/OscilGen.cpp View File

@@ -44,38 +44,96 @@ pthread_t main_thread;
const rtosc::Ports OscilGen::ports = { const rtosc::Ports OscilGen::ports = {
rSelf(OscilGen), rSelf(OscilGen),
rPaste, rPaste,
PC(hmagtype),
PC(currentbasefunc),
PC(basefuncpar),
PC(basefuncmodulation),
PC(basefuncmodulationpar1),
PC(basefuncmodulationpar2),
PC(basefuncmodulationpar3),
PC(waveshaping),
PC(waveshapingfunction),
PC(filtertype),
//TODO ensure min/max
rOption(Phmagtype,
rOptions(linear,dB scale (-40),
dB scale (-60), dB scale (-80),
dB scale (-100)),
"Type of magnitude for harmonics"),
rOption(Pcurrentbasefunc,
rOptions(sine, triangle,
pulse,
saw,
power,
gauss,
diode,
abssine,
pulsesine,
stretchsine,
chirp,
absstretchsine,
chebyshev,
sqr,
spike,
circle), rOpt(127,use-as-base waveform),
"Base Waveform for harmonics"),
rParamZyn(Pbasefuncpar,
"Morph between possible base function shapes "
"(e.g. rising sawtooth vs a falling sawtooth)"),
rOption(Pbasefuncmodulation,
rOptions(None, Rev, Sine, Power),
"Modulation applied to Base function spectra"),
rParamZyn(Pbasefuncmodulationpar1,
"Base function modulation parameter"),
rParamZyn(Pbasefuncmodulationpar2,
"Base function modulation parameter"),
rParamZyn(Pbasefuncmodulationpar3,
"Base function modulation parameter"),
rParamZyn(Pwaveshaping, "Degree Of Waveshaping"),
rOption(Pwaveshapingfunction,
rOptions(Undistorted,
Arctangent,
Asymmetric,
Pow,
Sine,
Quantisize,
Zigzag,
Limiter,
Upper Limiter,
Lower Limiter,
Inverse Limiter,
Clip,
Asym2,
Pow2,
sigmoid), "Shape of distortion to be applied"),
rOption(Pfiltertype, rOptions(No Filter,
lp, hp1, hp1b, bp1, bs1, lp2, hp2, bp2, bs2,
cos, sin, low_shelf, s), "Harmonic Filter"),
PC(filterpar1), PC(filterpar1),
PC(filterpar2), PC(filterpar2),
PC(filterbeforews),
rToggle(Pfilterbeforews, "Filter before waveshaping spectra;"
"When enabled oscilfilter(freqs); then waveshape(freqs);, "
"otherwise waveshape(freqs); then oscilfilter(freqs);"),
PC(satype), PC(satype),
PC(sapar),
rParamZyn(Psapar, "Spectral Adjustment Parameter"),
rParamI(Pharmonicshift, "Amount of shift on harmonics"), rParamI(Pharmonicshift, "Amount of shift on harmonics"),
rToggle(Pharmonicshiftfirst, "If harmonics are shifted before waveshaping/filtering"), rToggle(Pharmonicshiftfirst, "If harmonics are shifted before waveshaping/filtering"),
PC(modulation),
PC(modulationpar1),
PC(modulationpar2),
PC(modulationpar3),
rOption(Pmodulation, rOptions(None, Rev, Sine, Power),
"Frequency Modulation To Combined Spectra"),
rParamZyn(Pmodulationpar1,
"modulation parameter"),
rParamZyn(Pmodulationpar2,
"modulation parameter"),
rParamZyn(Pmodulationpar3,
"modulation parameter"),
//FIXME realtime parameters lurking below //FIXME realtime parameters lurking below
PC(rand), PC(rand),
PC(amprandpower),
PC(amprandtype),
PC(adaptiveharmonics),
PC(adaptiveharmonicsbasefreq),
PC(adaptiveharmonicspower),
PC(adaptiveharmonicspar),
rParamZyn(Pamprandpower,
"Variance of harmonic randomness"),
rOption(Pamprandtype, rOptions(None, Pow, Sin),
"Harmonic random distribution to select from"),
rOption(Padaptiveharmonics,
rOptions(OFF, ON, Square, 2xSub, 2xAdd, 3xSub, 3xAdd, 4xSub, 4xAdd),
"Adaptive Harmonics Mode"),
rParamI(Padaptiveharmonicsbasefreq, rLinear(0,255),
"Base frequency of adaptive harmonic (30..3000Hz)"),
rParamI(Padaptiveharmonicspower,rLinear(0,200),
"Adaptive Harmonic Strength"),
rParamZyn(Padaptiveharmonicspar,
"Adaptive Harmonics Postprocessing Power"),


//TODO update to rArray and test //TODO update to rArray and test
{"phase#128::c", rDoc("Sets harmonic phase"),
{"phase#128::c", rProp(parameter) rDoc("Sets harmonic phase"),
NULL, [](const char *m, rtosc::RtData &d) { NULL, [](const char *m, rtosc::RtData &d) {
const char *mm = m; const char *mm = m;
while(*mm && !isdigit(*mm)) ++mm; while(*mm && !isdigit(*mm)) ++mm;
@@ -86,7 +144,7 @@ const rtosc::Ports OscilGen::ports = {
phase = rtosc_argument(m,0).i; phase = rtosc_argument(m,0).i;
}}, }},
//TODO update to rArray and test //TODO update to rArray and test
{"magnitude#128::c", rDoc("Sets harmonic magnitude"),
{"magnitude#128::c", rProp(parameter) rDoc("Sets harmonic magnitude"),
NULL, [](const char *m, rtosc::RtData &d) { NULL, [](const char *m, rtosc::RtData &d) {
//printf("I'm at '%s'\n", d.loc); //printf("I'm at '%s'\n", d.loc);
const char *mm = m; const char *mm = m;
@@ -153,6 +211,10 @@ const rtosc::Ports OscilGen::ports = {
NULL, [](const char *, rtosc::RtData &d) { NULL, [](const char *, rtosc::RtData &d) {
((OscilGen*)d.obj)->convert2sine(); ((OscilGen*)d.obj)->convert2sine();
}}, }},
{"use-as-base:", rProp(non-realtime) rDoc("Translates current waveform into base"),
NULL, [](const char *, rtosc::RtData &d) {
((OscilGen*)d.obj)->useasbase();
}},
{"prepare:b", rProp(internal) rProp(non-realtime) rProp(pointer) rDoc("Sets prepared fft data"), {"prepare:b", rProp(internal) rProp(non-realtime) rProp(pointer) rDoc("Sets prepared fft data"),
NULL, [](const char *m, rtosc::RtData &d) { NULL, [](const char *m, rtosc::RtData &d) {
//fprintf(stderr, "prepare:b got a message from '%s'\n", m); //fprintf(stderr, "prepare:b got a message from '%s'\n", m);
@@ -385,64 +447,45 @@ void OscilGen::convert2sine()
*/ */
void OscilGen::getbasefunction(float *smps) void OscilGen::getbasefunction(float *smps)
{ {
int i;
float par = (Pbasefuncpar + 0.5f) / 128.0f; float par = (Pbasefuncpar + 0.5f) / 128.0f;
if(Pbasefuncpar == 64) if(Pbasefuncpar == 64)
par = 0.5f; par = 0.5f;


float basefuncmodulationpar1 = Pbasefuncmodulationpar1 / 127.0f,
basefuncmodulationpar2 = Pbasefuncmodulationpar2 / 127.0f,
basefuncmodulationpar3 = Pbasefuncmodulationpar3 / 127.0f;
float p1 = Pbasefuncmodulationpar1 / 127.0f,
p2 = Pbasefuncmodulationpar2 / 127.0f,
p3 = Pbasefuncmodulationpar3 / 127.0f;


switch(Pbasefuncmodulation) { switch(Pbasefuncmodulation) {
case 1: case 1:
basefuncmodulationpar1 =
(powf(2, basefuncmodulationpar1 * 5.0f) - 1.0f) / 10.0f;
basefuncmodulationpar3 =
floor((powf(2, basefuncmodulationpar3 * 5.0f) - 1.0f));
if(basefuncmodulationpar3 < 0.9999f)
basefuncmodulationpar3 = -1.0f;
p1 = (powf(2, p1 * 5.0f) - 1.0f) / 10.0f;
p3 = floor(powf(2, p3 * 5.0f) - 1.0f);
if(p3 < 0.9999f)
p3 = -1.0f;
break; break;
case 2: case 2:
basefuncmodulationpar1 =
(powf(2, basefuncmodulationpar1 * 5.0f) - 1.0f) / 10.0f;
basefuncmodulationpar3 = 1.0f
+ floor((powf(2, basefuncmodulationpar3
* 5.0f) - 1.0f));
p1 = (powf(2, p1 * 5.0f) - 1.0f) / 10.0f;
p3 = 1.0f + floor(powf(2, p3 * 5.0f) - 1.0f);
break; break;
case 3: case 3:
basefuncmodulationpar1 =
(powf(2, basefuncmodulationpar1 * 7.0f) - 1.0f) / 10.0f;
basefuncmodulationpar3 = 0.01f
+ (powf(2, basefuncmodulationpar3
* 16.0f) - 1.0f) / 10.0f;
p1 = (powf(2, p1 * 7.0f) - 1.0f) / 10.0f;
p3 = 0.01f + (powf(2, p3 * 16.0f) - 1.0f) / 10.0f;
break; break;
} }


base_func func = getBaseFunction(Pcurrentbasefunc); base_func func = getBaseFunction(Pcurrentbasefunc);


for(i = 0; i < synth.oscilsize; ++i) {
for(int i = 0; i < synth.oscilsize; ++i) {
float t = i * 1.0f / synth.oscilsize; float t = i * 1.0f / synth.oscilsize;


switch(Pbasefuncmodulation) { switch(Pbasefuncmodulation) {
case 1:
t = t * basefuncmodulationpar3 + sinf(
(t
+ basefuncmodulationpar2) * 2.0f
* PI) * basefuncmodulationpar1; //rev
case 1: //rev
t = t * p3 + sinf((t + p2) * 2.0f * PI) * p1;
break; break;
case 2:
t = t + sinf(
(t * basefuncmodulationpar3
+ basefuncmodulationpar2) * 2.0f
* PI) * basefuncmodulationpar1; //sine
case 2: //sine
t += sinf( (t * p3 + p2) * 2.0f * PI) * p1;
break; break;
case 3:
t = t + powf((1.0f - cosf(
(t
+ basefuncmodulationpar2) * 2.0f
* PI)) * 0.5f,
basefuncmodulationpar3) * basefuncmodulationpar1; //power
case 3: //power
t += powf((1.0f - cosf((t + p2) * 2.0f * PI)) * 0.5f, p3) * p1;
break; break;
} }


@@ -652,12 +695,11 @@ void OscilGen::spectrumadjust(fft_t *freqs)
break; break;
} }



normalize(freqs, synth.oscilsize); normalize(freqs, synth.oscilsize);


for(int i = 0; i < synth.oscilsize / 2; ++i) { for(int i = 0; i < synth.oscilsize / 2; ++i) {
float mag = abs(oscilFFTfreqs, i);
float phase = M_PI_2 - arg(oscilFFTfreqs, i);
float mag = abs(freqs, i);
float phase = M_PI_2 - arg(freqs, i);


switch(Psatype) { switch(Psatype) {
case 1: case 1:
@@ -783,13 +825,12 @@ void OscilGen::prepare(fft_t *freqs)
if(Pharmonicshiftfirst != 0) if(Pharmonicshiftfirst != 0)
shiftharmonics(freqs); shiftharmonics(freqs);


if(Pfilterbeforews == 0) {
waveshape(freqs);
oscilfilter(freqs);
}
else {
if(Pfilterbeforews) {
oscilfilter(freqs); oscilfilter(freqs);
waveshape(freqs); waveshape(freqs);
} else {
waveshape(freqs);
oscilfilter(freqs);
} }


modulation(freqs); modulation(freqs);
@@ -876,9 +917,9 @@ void OscilGen::adaptiveharmonicpostprocess(fft_t *f, int size)
if(Padaptiveharmonics == 2) { //2n+1 if(Padaptiveharmonics == 2) { //2n+1
for(int i = 0; i < size; ++i) for(int i = 0; i < size; ++i)
if((i % 2) == 0) if((i % 2) == 0)
f[i] += inf[i]; //i=0 pt prima armonica,etc.
f[i] += inf[i]; //i=0 first harmonic,etc.
} }
else { //celelalte moduri
else { //other ways
int nh = (Padaptiveharmonics - 3) / 2 + 2; int nh = (Padaptiveharmonics - 3) / 2 + 2;
int sub_vs_add = (Padaptiveharmonics - 3) % 2; int sub_vs_add = (Padaptiveharmonics - 3) % 2;
if(sub_vs_add == 0) { if(sub_vs_add == 0) {


+ 1
- 1
source/native-plugins/zynaddsubfx/Synth/OscilGen.h View File

@@ -84,7 +84,7 @@ class OscilGen:public Presets


unsigned char Pwaveshaping, Pwaveshapingfunction; unsigned char Pwaveshaping, Pwaveshapingfunction;
unsigned char Pfiltertype, Pfilterpar1, Pfilterpar2; unsigned char Pfiltertype, Pfilterpar1, Pfilterpar2;
unsigned char Pfilterbeforews;
bool Pfilterbeforews;
unsigned char Psatype, Psapar; //spectrum adjust unsigned char Psatype, Psapar; //spectrum adjust


int Pharmonicshift; //how the harmonics are shifted int Pharmonicshift; //how the harmonics are shifted


+ 13
- 6
source/native-plugins/zynaddsubfx/Synth/PADnote.cpp View File

@@ -28,7 +28,7 @@
#include "../Params/FilterParams.h" #include "../Params/FilterParams.h"
#include "../Misc/Util.h" #include "../Misc/Util.h"


PADnote::PADnote(PADnoteParameters *parameters,
PADnote::PADnote(const PADnoteParameters *parameters,
SynthParams pars, const int& interpolation) SynthParams pars, const int& interpolation)
:SynthNote(pars), pars(*parameters), interpolation(interpolation) :SynthNote(pars), pars(*parameters), interpolation(interpolation)
{ {
@@ -121,9 +121,9 @@ void PADnote::setup(float freq,
((powf(10, 1.5f * pars.PPunchStrength / 127.0f) - 1.0f) ((powf(10, 1.5f * pars.PPunchStrength / 127.0f) - 1.0f)
* VelF(velocity, * VelF(velocity,
pars.PPunchVelocitySensing)); pars.PPunchVelocitySensing));
float time =
const float time =
powf(10, 3.0f * pars.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms powf(10, 3.0f * pars.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms
float stretch = powf(440.0f / freq, pars.PPunchStretch / 64.0f);
const float stretch = powf(440.0f / freq, pars.PPunchStretch / 64.0f);
NoteGlobalPar.Punch.dt = 1.0f NoteGlobalPar.Punch.dt = 1.0f
/ (time * synth.samplerate_f * stretch); / (time * synth.samplerate_f * stretch);
} }
@@ -131,10 +131,10 @@ void PADnote::setup(float freq,
NoteGlobalPar.Punch.Enabled = 0; NoteGlobalPar.Punch.Enabled = 0;


NoteGlobalPar.FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq, synth.dt()); NoteGlobalPar.FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq, synth.dt());
NoteGlobalPar.FreqLfo = memory.alloc<LFO>(*pars.FreqLfo, basefreq, synth.dt());
NoteGlobalPar.FreqLfo = memory.alloc<LFO>(*pars.FreqLfo, basefreq, time);


NoteGlobalPar.AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq, synth.dt()); NoteGlobalPar.AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq, synth.dt());
NoteGlobalPar.AmpLfo = memory.alloc<LFO>(*pars.AmpLfo, basefreq, synth.dt());
NoteGlobalPar.AmpLfo = memory.alloc<LFO>(*pars.AmpLfo, basefreq, time);
} }


NoteGlobalPar.Volume = 4.0f NoteGlobalPar.Volume = 4.0f
@@ -154,7 +154,7 @@ void PADnote::setup(float freq,
synth.samplerate, synth.buffersize); synth.samplerate, synth.buffersize);


NoteGlobalPar.FilterEnvelope = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq, synth.dt()); NoteGlobalPar.FilterEnvelope = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq, synth.dt());
NoteGlobalPar.FilterLfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq, synth.dt());
NoteGlobalPar.FilterLfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq, time);
} }
NoteGlobalPar.FilterQ = pars.GlobalFilter->getq(); NoteGlobalPar.FilterQ = pars.GlobalFilter->getq();
NoteGlobalPar.FilterFreqTracking = pars.GlobalFilter->getfreqtracking( NoteGlobalPar.FilterFreqTracking = pars.GlobalFilter->getfreqtracking(
@@ -166,6 +166,13 @@ void PADnote::setup(float freq,
} }
} }


SynthNote *PADnote::cloneLegato(void)
{
SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
(bool)portamento, legato.param.midinote, true};
return memory.alloc<PADnote>(&pars, sp, interpolation);
}

void PADnote::legatonote(LegatoParams pars) void PADnote::legatonote(LegatoParams pars)
{ {
// Manage legato stuff // Manage legato stuff


+ 2
- 1
source/native-plugins/zynaddsubfx/Synth/PADnote.h View File

@@ -30,10 +30,11 @@
class PADnote:public SynthNote class PADnote:public SynthNote
{ {
public: public:
PADnote(PADnoteParameters *parameters, SynthParams pars,
PADnote(const PADnoteParameters *parameters, SynthParams pars,
const int &interpolation); const int &interpolation);
~PADnote(); ~PADnote();


SynthNote *cloneLegato(void);
void legatonote(LegatoParams pars); void legatonote(LegatoParams pars);


int noteout(float *outl, float *outr); int noteout(float *outl, float *outr);


+ 1
- 1
source/native-plugins/zynaddsubfx/Synth/Resonance.cpp View File

@@ -44,7 +44,7 @@ const rtosc::Ports Resonance::ports = {
rAction(smooth, "Smooth out frequency response"), rAction(smooth, "Smooth out frequency response"),
rAction(zero, "Reset frequency response"), rAction(zero, "Reset frequency response"),
//UI Value listeners //UI Value listeners
{"centerfreq:", rDoc("Get center frequency"), NULL,
{"centerfreq:", rDoc("Get center frequency") rMap(unit, Hz), NULL,
[](const char *, RtData &d) [](const char *, RtData &d)
{d.reply(d.loc, "f", ((rObject*)d.obj)->getcenterfreq());}}, {d.reply(d.loc, "f", ((rObject*)d.obj)->getcenterfreq());}},
{"octavesfreq:", rDoc("Get center freq of graph"), NULL, {"octavesfreq:", rDoc("Get center freq of graph"), NULL,


+ 9
- 1
source/native-plugins/zynaddsubfx/Synth/SUBnote.cpp View File

@@ -33,7 +33,7 @@
#include "../Misc/Util.h" #include "../Misc/Util.h"
#include "../Misc/Allocator.h" #include "../Misc/Allocator.h"


SUBnote::SUBnote(SUBnoteParameters *parameters, SynthParams &spars)
SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars)
:SynthNote(spars), pars(*parameters) :SynthNote(spars), pars(*parameters)
{ {
NoteEnabled = ON; NoteEnabled = ON;
@@ -46,6 +46,7 @@ void SUBnote::setup(float freq,
int midinote, int midinote,
bool legato) bool legato)
{ {
this->velocity = velocity;
portamento = portamento_; portamento = portamento_;
NoteEnabled = ON; NoteEnabled = ON;
volume = powf(0.1f, 3.0f * (1.0f - pars.PVolume / 96.0f)); //-60 dB .. 0 dB volume = powf(0.1f, 3.0f * (1.0f - pars.PVolume / 96.0f)); //-60 dB .. 0 dB
@@ -210,6 +211,13 @@ void SUBnote::setup(float freq,
oldamplitude = newamplitude; oldamplitude = newamplitude;
} }


SynthNote *SUBnote::cloneLegato(void)
{
SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
(bool)portamento, legato.param.midinote, true};
return memory.alloc<SUBnote>(&pars, sp);
}

void SUBnote::legatonote(LegatoParams pars) void SUBnote::legatonote(LegatoParams pars)
{ {
// Manage legato stuff // Manage legato stuff


+ 3
- 1
source/native-plugins/zynaddsubfx/Synth/SUBnote.h View File

@@ -30,9 +30,10 @@
class SUBnote:public SynthNote class SUBnote:public SynthNote
{ {
public: public:
SUBnote(SUBnoteParameters *parameters, SynthParams &pars);
SUBnote(const SUBnoteParameters *parameters, SynthParams &pars);
~SUBnote(); ~SUBnote();


SynthNote *cloneLegato(void);
void legatonote(LegatoParams pars); void legatonote(LegatoParams pars);


int noteout(float *outl, float *outr); //note output,return 0 if the note is finished int noteout(float *outl, float *outr); //note output,return 0 if the note is finished
@@ -100,6 +101,7 @@ class SUBnote:public SynthNote


int oldpitchwheel, oldbandwidth; int oldpitchwheel, oldbandwidth;
float globalfiltercenterq; float globalfiltercenterq;
float velocity;
}; };


#endif #endif

+ 3
- 3
source/native-plugins/zynaddsubfx/Synth/SynthNote.cpp View File

@@ -3,9 +3,9 @@
#include <cstring> #include <cstring>


SynthNote::SynthNote(SynthParams &pars) SynthNote::SynthNote(SynthParams &pars)
:legato(pars.synth, pars.frequency, pars.velocity, pars.portamento,
pars.note, pars.quiet),
memory(pars.memory), ctl(pars.ctl), synth(pars.synth)
:memory(pars.memory),
legato(pars.synth, pars.frequency, pars.velocity, pars.portamento,
pars.note, pars.quiet), ctl(pars.ctl), synth(pars.synth), time(pars.time)
{} {}


SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port, SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port,


+ 10
- 3
source/native-plugins/zynaddsubfx/Synth/SynthNote.h View File

@@ -28,8 +28,9 @@ class Controller;
struct SynthParams struct SynthParams
{ {
Allocator &memory; //Memory Allocator for the Note to use Allocator &memory; //Memory Allocator for the Note to use
Controller &ctl;
const Controller &ctl;
const SYNTH_T &synth; const SYNTH_T &synth;
const AbsTime &time;
float frequency; //Note base frequency float frequency; //Note base frequency
float velocity; //Velocity of the Note float velocity; //Velocity of the Note
bool portamento;//True if portamento is used for this note bool portamento;//True if portamento is used for this note
@@ -65,8 +66,14 @@ class SynthNote
virtual int finished() const = 0; virtual int finished() const = 0;


virtual void legatonote(LegatoParams pars) = 0; virtual void legatonote(LegatoParams pars) = 0;

virtual SynthNote *cloneLegato(void) = 0;

/* For polyphonic aftertouch needed */ /* For polyphonic aftertouch needed */
void setVelocity(float velocity_); void setVelocity(float velocity_);

//Realtime Safe Memory Allocator For notes
class Allocator &memory;
protected: protected:
// Legato transitions // Legato transitions
class Legato class Legato
@@ -87,6 +94,7 @@ class SynthNote
int length; int length;
float m, step; float m, step;
} fade; } fade;
public:
struct { // Note parameters struct { // Note parameters
float freq, vel; float freq, vel;
bool portamento; bool portamento;
@@ -103,10 +111,9 @@ class SynthNote
void setDecounter(int decounter_) {decounter = decounter_; } void setDecounter(int decounter_) {decounter = decounter_; }
} legato; } legato;


//Realtime Safe Memory Allocator For notes
class Allocator &memory;
const Controller &ctl; const Controller &ctl;
const SYNTH_T &synth; const SYNTH_T &synth;
const AbsTime &time;
}; };


#endif #endif

+ 120
- 59
source/native-plugins/zynaddsubfx/UI/ADnoteUI.fl View File

@@ -70,12 +70,21 @@ decl {\#include "OscilGenUI.h"} {public local
decl {\#include "PresetsUI.h"} {public local decl {\#include "PresetsUI.h"} {public local
} }


decl {\#include "PartUI.h"} {private local
}

decl {\#include "MasterUI.h"} {private local
}

decl {extern class MasterUI *ui;} {private local
}

class ADvoicelistitem {open : {public Fl_Osc_Group} class ADvoicelistitem {open : {public Fl_Osc_Group}
} { } {
Function {make_window()} {open private Function {make_window()} {open private
} { } {
Fl_Window ADnoteVoiceListItem {open Fl_Window ADnoteVoiceListItem {open
private xywh {346 881 615 100} type Double box UP_FRAME
private xywh {117 90 670 100} type Double box NO_BOX
class Fl_Osc_Group visible class Fl_Osc_Group visible
} { } {
Fl_Box {} { Fl_Box {} {
@@ -83,61 +92,61 @@ class ADvoicelistitem {open : {public Fl_Osc_Group}
code0 {ADnoteVoiceListItem->base = loc;} code0 {ADnoteVoiceListItem->base = loc;}
} }
Fl_Group voicelistitemgroup {open Fl_Group voicelistitemgroup {open
private xywh {50 0 570 25}
private xywh {0 0 670 25}
class Fl_Osc_Group class Fl_Osc_Group
} { } {
Fl_Value_Slider voicevolume { Fl_Value_Slider voicevolume {
tooltip Volume xywh {90 5 115 20} type {Horz Knob} box NO_BOX labelsize 8 align 5 maximum 127 step 1
tooltip Volume xywh {132 5 115 20} type {Horz Knob} box NO_BOX labelsize 8 align 5 maximum 127 step 1
code1 {o->init("PVolume");} code1 {o->init("PVolume");}
class Fl_Osc_VSlider class Fl_Osc_VSlider
} }
Fl_Check_Button voiceresonanceenabled { Fl_Check_Button voiceresonanceenabled {
tooltip {Resonance On/Off} xywh {245 7 15 17} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 11 align 4
tooltip {Resonance On/Off} xywh {287 7 15 17} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 11 align 4
code0 {o->init("Presonance");} code0 {o->init("Presonance");}
class Fl_Osc_Check class Fl_Osc_Check
} }
Fl_Value_Slider voicelfofreq { Fl_Value_Slider voicelfofreq {
tooltip {Frequency LFO amount} xywh {500 5 115 20} type {Horz Knob} box NO_BOX labelsize 8 align 5 maximum 127 step 1
tooltip {Frequency LFO amount} xywh {542 5 115 20} type {Horz Knob} box NO_BOX labelsize 8 align 5 maximum 127 step 1
code0 {o->init("FreqLfo/Pintensity", 'i');} code0 {o->init("FreqLfo/Pintensity", 'i');}
class Fl_Osc_Slider
class Fl_Osc_VSlider
} }
Fl_Dial voicepanning { Fl_Dial voicepanning {
tooltip {Panning (leftmost is Random)} xywh {215 5 20 20} box ROUND_UP_BOX labelsize 10 align 4 maximum 127 step 1
tooltip {Panning (leftmost is Random)} xywh {257 5 20 20} box ROUND_UP_BOX labelsize 10 align 4 maximum 127 step 1
code0 {o->init("PPanning");} code0 {o->init("PPanning");}
class Fl_Osc_Dial class Fl_Osc_Dial
} }
Fl_Group voiceoscil {open Fl_Group voiceoscil {open
xywh {60 5 30 20} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179
xywh {102 5 30 20} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179
code0 {voiceoscil->ext = "OscilSmp/";} code0 {voiceoscil->ext = "OscilSmp/";}
code1 {oscil=new Fl_Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} code1 {oscil=new Fl_Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");}
code2 {oscil->init(false);} code2 {oscil->init(false);}
class Fl_Osc_Group class Fl_Osc_Group
} {} } {}
Fl_Value_Output detunevalueoutput { Fl_Value_Output detunevalueoutput {
xywh {265 5 45 20} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10
xywh {307 5 45 20} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10
code0 {o->init("detunevalue");} code0 {o->init("detunevalue");}
class Fl_Osc_Output class Fl_Osc_Output
} }
Fl_Slider voicedetune { Fl_Slider voicedetune {
callback {detunevalueoutput->update();} callback {detunevalueoutput->update();}
tooltip {Fine Detune (cents)} xywh {315 5 185 20} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
tooltip {Fine Detune (cents)} xywh {357 5 185 20} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
code0 {o->init("PDetune",'i');} code0 {o->init("PDetune",'i');}
class Fl_Osc_Slider class Fl_Osc_Slider
} }
Fl_Box noiselabel {
Fl_Box whitenoiselabel {
label N label N
xywh {65 5 20 20} labelfont 1 labelsize 13 labelcolor 7
xywh {107 5 20 20} labelfont 1 labelsize 13 labelcolor 7
} }
Fl_Check_Button noisehack { Fl_Check_Button noisehack {
callback {if (o->value()==0) { callback {if (o->value()==0) {
noiselabel->hide();
whitenoiselabel->hide();
voiceresonanceenabled->activate(); voiceresonanceenabled->activate();
detunevalueoutput->activate(); detunevalueoutput->activate();
voicedetune->activate(); voicedetune->activate();
voicelfofreq->activate(); voicelfofreq->activate();
voiceoscil->activate(); voiceoscil->activate();
} else { } else {
noiselabel->show();
whitenoiselabel->show();
voiceresonanceenabled->deactivate(); voiceresonanceenabled->deactivate();
detunevalueoutput->deactivate(); detunevalueoutput->deactivate();
voicedetune->deactivate(); voicedetune->deactivate();
@@ -159,6 +168,21 @@ o->redraw();}
code1 {o->init("Enabled");} code1 {o->init("Enabled");}
class Fl_Osc_Check class Fl_Osc_Check
} }
Fl_Button {} {
label edit
callback {
class ADnoteUI *adnoteui = ui->partui->adnoteui;
adnoteui->ADnoteVoice->show();
adnoteui->currentvoicecounter->value(nvoice+1);
adnoteui->currentvoicecounter->do_callback();
class ADvoiceUI *advoice = adnoteui->advoice;
if (advoice->mod_type->value() == 0)
advoice->voiceFMparametersgroup->deactivate();
else
advoice->voiceFMparametersgroup->activate();
}
xywh {53 6 40 15} box THIN_UP_BOX labelsize 11
}
} }
} }
Function {ADvoicelistitem(int x,int y, int w, int h, const char *label=0):Fl_Osc_Group(x,y,w,h,label)} {open Function {ADvoicelistitem(int x,int y, int w, int h, const char *label=0):Fl_Osc_Group(x,y,w,h,label)} {open
@@ -281,7 +305,7 @@ o->redraw();}
label Vol label Vol
tooltip Volume xywh {540 80 160 15} type {Horz Knob} box NO_BOX labelsize 11 align 8 maximum 127 step 1 tooltip Volume xywh {540 80 160 15} type {Horz Knob} box NO_BOX labelsize 11 align 8 maximum 127 step 1
code0 {o->init("PFMVolume", 'i');} code0 {o->init("PFMVolume", 'i');}
class Fl_Osc_Slider
class Fl_Osc_VSlider
} }
Fl_Value_Slider {} { Fl_Value_Slider {} {
label {V.Sns} label {V.Sns}
@@ -309,7 +333,7 @@ o->redraw();}
label {F.Damp} label {F.Damp}
tooltip {Modulator Damp at Higher frequency} xywh {540 120 160 15} type {Horz Knob} box NO_BOX labelsize 11 align 8 minimum -64 maximum 63 step 1 tooltip {Modulator Damp at Higher frequency} xywh {540 120 160 15} type {Horz Knob} box NO_BOX labelsize 11 align 8 minimum -64 maximum 63 step 1
code0 {o->init("PFMVolumeDamp",'i');} code0 {o->init("PFMVolumeDamp",'i');}
class Fl_Osc_Slider
class Fl_Osc_VSlider
} }
} }
Fl_Group modoscil {open Fl_Group modoscil {open
@@ -361,11 +385,11 @@ voiceFMparametersgroup->redraw();} open
xywh {560 410 75 20} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10 xywh {560 410 75 20} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10
code0 {o->add("Internal");} code0 {o->add("Internal");}
code1 {char tmp[50]; for (int i=0;i<nvoice;i++) {sprintf(tmp,"ExtM.%2d",i+1);o->add(tmp);};} code1 {char tmp[50]; for (int i=0;i<nvoice;i++) {sprintf(tmp,"ExtM.%2d",i+1);o->add(tmp);};}
code3 {o->init("PextFMoscil",1);}
code3 {o->init("PextFMoscil",-1);}
class Fl_Osc_Choice class Fl_Osc_Choice
} {} } {}
} }
Fl_Choice {} {
Fl_Choice extMod {
label {External Mod.} label {External Mod.}
callback {if ((int) o->value() != 0) { callback {if ((int) o->value() != 0) {
modoscil->deactivate(); modoscil->deactivate();
@@ -383,7 +407,7 @@ voiceFMparametersgroup->redraw();} open
class Fl_Osc_Choice class Fl_Osc_Choice
} {} } {}
} }
Fl_Choice {} {
Fl_Choice mod_type {
label {Type:} label {Type:}
callback {if (o->value()==0) voiceFMparametersgroup->deactivate(); callback {if (o->value()==0) voiceFMparametersgroup->deactivate();
else voiceFMparametersgroup->activate(); else voiceFMparametersgroup->activate();
@@ -551,25 +575,12 @@ voiceonbutton->redraw();} open
xywh {5 470 65 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 xywh {5 470 65 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10
code0 {o->add("Internal");} code0 {o->add("Internal");}
code1 {char tmp[50]; for (int i=0;i<nvoice;i++) {sprintf(tmp,"Ext.%2d",i+1);o->add(tmp);};} code1 {char tmp[50]; for (int i=0;i<nvoice;i++) {sprintf(tmp,"Ext.%2d",i+1);o->add(tmp);};}
code3 {o->init("Pextoscil",1);}
code3 {o->init("Pextoscil",-1);}
class Fl_Osc_Choice class Fl_Osc_Choice
} {} } {}
Fl_Group {} {open Fl_Group {} {open
xywh {5 540 520 50} box UP_FRAME xywh {5 540 520 50} box UP_FRAME
} { } {
Fl_Dial {} {
label Stereo
tooltip {Stereo Spread} xywh {322 555 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1
code0 {o->init("Unison_stereo_spread");}
class Fl_Osc_Dial
}
Fl_Choice {} {
label Unison
tooltip {Unison size} xywh {10 560 75 20} down_box BORDER_BOX labelfont 1 align 5 textfont 1 textsize 10
code0 {o->add("OFF");char tmp[100];for (int i=1;ADnote_unison_sizes[i];i++){snprintf(tmp,100,"size %d",ADnote_unison_sizes[i]);o->add(tmp);};}
code1 {o->init("Unison_size");}
class Fl_Osc_Choice
} {}
Fl_Dial {} { Fl_Dial {} {
label Vibrato label Vibrato
tooltip Vibrato xywh {364 555 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 tooltip Vibrato xywh {364 555 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1
@@ -718,8 +729,11 @@ o->redraw();}
code0 {char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp));} code0 {char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp));}
} {} } {}
Fl_Choice {} { Fl_Choice {} {
callback {if (o->value()==0){ voicemodegroup->activate(); noiselabel->hide();}
else{ voicemodegroup->deactivate(); noiselabel->show();}}
callback {switch (o->value()) {
case 0: voicemodegroup->activate(); whitenoiselabel->hide(); pinknoiselabel->hide(); break;
case 1: voicemodegroup->deactivate(); whitenoiselabel->show(); pinknoiselabel->hide(); break;
default: voicemodegroup->deactivate(); whitenoiselabel->hide(); pinknoiselabel->show(); break;
}} open
tooltip {Oscillator Type (sound/noise)} xywh {5 515 65 20} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10 tooltip {Oscillator Type (sound/noise)} xywh {5 515 65 20} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10
code0 {o->init("Type");} code0 {o->init("Type");}
class Fl_Osc_Choice class Fl_Osc_Choice
@@ -729,8 +743,12 @@ o->redraw();}
xywh {5 5 100 20} labelfont 1 labelsize 11 xywh {5 5 100 20} labelfont 1 labelsize 11
} }
MenuItem {} { MenuItem {} {
label NOISE
xywh {15 15 100 20} labelfont 1 labelsize 11 labelcolor 1
label White
xywh {15 15 100 20} labelfont 1 labelsize 11 labelcolor 55
}
MenuItem {} {
label Pink
xywh {25 25 100 20} labelfont 1 labelsize 11 labelcolor 211
} }
} }
Fl_Check_Button bypassfiltercheckbutton { Fl_Check_Button bypassfiltercheckbutton {
@@ -759,10 +777,27 @@ bypassfiltercheckbutton->redraw();}
code0 {o->init("PFilterEnabled");} code0 {o->init("PFilterEnabled");}
class Fl_Osc_Check class Fl_Osc_Check
} }
Fl_Box noiselabel {
Fl_Box whitenoiselabel {
label {White Noise} label {White Noise}
xywh {150 430 300 65} labelfont 1 labelsize 50 labelcolor 53 hide xywh {150 430 300 65} labelfont 1 labelsize 50 labelcolor 53 hide
} }
Fl_Box pinknoiselabel {
label {Pink Noise}
xywh {150 430 300 65} labelfont 1 labelsize 50 labelcolor 212 hide
}
Fl_Dial {} {
label Stereo
tooltip {Stereo Spread} xywh {327 560 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1
code0 {o->init("Unison_stereo_spread");}
class Fl_Osc_Dial
}
Fl_Counter {} {
label Unison selected
tooltip {Unison size} xywh {20 568 65 18} labelfont 1 align 5 minimum 1 maximum 64 step 1 value 1 textfont 1 textsize 11
code0 {o->init("Unison_size", 1);}
code1 {o->lstep(5);}
class Fl_Osc_Counter
}
} }
Fl_Check_Button voiceonbutton { Fl_Check_Button voiceonbutton {
label On label On
@@ -802,9 +837,29 @@ delete(oscedit);
} { } {
code {nvoice = nvoice_; code {nvoice = nvoice_;
loc = base+"VoicePar"+to_s(nvoice)+"/"; loc = base+"VoicePar"+to_s(nvoice)+"/";
char tmp[10];snprintf(tmp,10,"%d",nvoice+1);
char tmp[50];snprintf(tmp,10,"%d",nvoice+1);
activeVoiceID->label(strdup(tmp)); activeVoiceID->label(strdup(tmp));
ADnoteVoiceParameters->rebase(base+"VoicePar"+to_s(nvoice)+"/");} {selected
extoscil->clear();
extoscil->add("Internal");
for (int i=0;i<nvoice;i++) {
sprintf(tmp,"Ext.%2d",i+1);
extoscil->add(tmp);
};

extFMoscil->clear();
extFMoscil->add("Internal");
for (int i=0;i<nvoice;i++) {
sprintf(tmp,"ExtM.%2d",i+1);
extFMoscil->add(tmp);
}
extMod->clear();
extMod->add("OFF");
for (int i=0;i<nvoice;i++) {
sprintf(tmp,"ExtMod.%2d",i+1);
extMod->add(tmp);
}
ADnoteVoiceParameters->rebase(base+"VoicePar"+to_s(nvoice)+"/");} {selected
} }
} }
decl {int nvoice;} {private local decl {int nvoice;} {private local
@@ -834,7 +889,7 @@ class ADnoteUI {open : {public PresetsUI_}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {ADnoteGlobalParameters->base = loc + "GlobalPar/"; ADnoteGlobalParameters->osc = osc;}
code0 {ADnoteGlobalParameters->init(osc, loc + "GlobalPar/");}
} }
Fl_Group {} { Fl_Group {} {
label FREQUENCY open label FREQUENCY open
@@ -879,7 +934,10 @@ class ADnoteUI {open : {public PresetsUI_}
} }
Fl_Choice detunetype { Fl_Choice detunetype {
label {Detune Type} label {Detune Type}
callback {detunevalueoutput->update();} open
callback {detunevalueoutput->update();
ui->partui->adnoteui->advoice->detunevalueoutput->update();
ui->partui->adnoteui->advoice->fmdetunevalueoutput->update();
} open
xywh {455 340 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 xywh {455 340 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10
code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");}
code1 {o->init("PDetuneType",1);} code1 {o->init("PDetuneType",1);}
@@ -1000,7 +1058,12 @@ ADnoteVoiceList->show();}
} }
Fl_Button {} { Fl_Button {} {
label {Show Voice Parameters} label {Show Voice Parameters}
callback {ADnoteVoice->show();}
callback {
if (advoice->mod_type->value() == 0)
advoice->voiceFMparametersgroup->deactivate();
else
advoice->voiceFMparametersgroup->activate();
ADnoteVoice->show();}
xywh {5 400 170 25} labelsize 12 xywh {5 400 170 25} labelsize 12
} }
Fl_Button {} { Fl_Button {} {
@@ -1032,8 +1095,7 @@ resui->resonancewindow->show();}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {ADnoteVoice->base = loc;}
code1 {ADnoteVoice->osc = osc;}
code0 {ADnoteVoice->init(osc,loc);}
} }
Fl_Group advoice {open Fl_Group advoice {open
xywh {0 0 765 595} xywh {0 0 765 595}
@@ -1066,49 +1128,48 @@ advoice->change_voice(nvoice);}
} }
Fl_Window ADnoteVoiceList { Fl_Window ADnoteVoiceList {
label {ADsynth Voices list} open label {ADsynth Voices list} open
xywh {32 266 650 260} type Double hide
xywh {6 263 670 260} type Double hide
class Fl_Osc_Window class Fl_Osc_Window
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {ADnoteVoiceList->base = loc;}
code1 {ADnoteVoiceList->osc = osc;}
code0 {ADnoteVoiceList->init(osc, loc);}
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label {No.} label {No.}
xywh {10 15 30 10} box NO_BOX labelfont 1 labelsize 11
xywh {17 15 30 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label Vol label Vol
xywh {145 15 30 10} box NO_BOX labelfont 1 labelsize 11
xywh {190 15 30 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label Detune label Detune
xywh {384 15 25 10} box NO_BOX labelfont 1 labelsize 11
xywh {431 15 25 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label Pan label Pan
xywh {210 15 30 10} box NO_BOX labelfont 1 labelsize 11
xywh {253 15 30 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label {Vib. Depth}
xywh {560 15 30 10} box NO_BOX labelfont 1 labelsize 11
label {Vib. Depth} selected
xywh {600 15 30 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Text_Display {} { Fl_Text_Display {} {
label {R.} label {R.}
xywh {245 15 25 10} box NO_BOX labelfont 1 labelsize 11
xywh {285 15 25 10} box NO_BOX labelfont 1 labelsize 11
} }
Fl_Button {} { Fl_Button {} {
label {Hide Voice List} label {Hide Voice List}
callback {ADnoteVoiceList->hide();} callback {ADnoteVoiceList->hide();}
xywh {255 237 125 20}
xywh {271 237 125 20}
} }
Fl_Scroll {} {open Fl_Scroll {} {open
xywh {0 15 640 220} type VERTICAL box THIN_UP_BOX
xywh {0 15 670 220} type VERTICAL box THIN_UP_BOX
} { } {
Fl_Pack {} {open Fl_Pack {} {open
xywh {0 20 620 210}
code0 {o->begin();for (int i=0;i<NUM_VOICES;i++){voicelistitem[i]=new ADvoicelistitem(0,0,620,25,"");voicelistitem[i]->init(i,loc+"VoicePar"+to_s(i)+"/",osc);}o->end();}
xywh {0 20 670 210}
code0 {o->begin();for (int i=0;i<NUM_VOICES;i++){voicelistitem[i]=new ADvoicelistitem(0,0,670,25,"");voicelistitem[i]->init(i,loc+"VoicePar"+to_s(i)+"/",osc);}o->end();}
} {} } {}
} }
} }


+ 4
- 2
source/native-plugins/zynaddsubfx/UI/BankUI.fl View File

@@ -29,6 +29,9 @@ decl {\#include "Fl_Osc_Interface.h"} {public local
decl {\#include "Fl_Osc_Check.H"} {public local decl {\#include "Fl_Osc_Check.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include "../Misc/Util.h"} {public local decl {\#include "../Misc/Util.h"} {public local
} }


@@ -46,8 +49,7 @@ class BankUI {open
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {bankuiwindow->osc = osc;}
code1 {bankuiwindow->base = "/";}
code0 {bankuiwindow->init(osc, "/");}
} }
Fl_Button {} { Fl_Button {} {
label Close label Close


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/BankView.cpp View File

@@ -21,7 +21,7 @@ void BankList::init(std::string path)


void BankList::OSC_raw(const char *msg) void BankList::OSC_raw(const char *msg)
{ {
if(!strcmp(msg, "/bank-list")) {
if(!strcmp(msg, "/bank-list") && !strcmp(rtosc_argument_string(msg),"iss")) {


const int pos = rtosc_argument(msg, 0).i; const int pos = rtosc_argument(msg, 0).i;
const char *path = rtosc_argument(msg, 1).s; const char *path = rtosc_argument(msg, 1).s;
@@ -33,7 +33,7 @@ void BankList::OSC_raw(const char *msg)
this->add(path); this->add(path);
osc->write("/loadbank"); osc->write("/loadbank");
} }
if(!strcmp(msg, "/loadbank")) {
if(!strcmp(msg, "/loadbank")&& !strcmp(rtosc_argument_string(msg),"i")) {
value(rtosc_argument(msg, 0).i); value(rtosc_argument(msg, 0).i);
} }
} }


+ 5
- 3
source/native-plugins/zynaddsubfx/UI/ConfigUI.fl View File

@@ -44,6 +44,9 @@ decl {\#include "Fl_Osc_Numeric_Input.H"} {public local
decl {\#include "Fl_Osc_ListView.H"} {public local decl {\#include "Fl_Osc_ListView.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include "../globals.h"} {public local decl {\#include "../globals.h"} {public local
} }


@@ -60,8 +63,7 @@ class ConfigUI {} {
} { } {
Fl_Box dummy { Fl_Box dummy {
xywh {25 25 25 25} xywh {25 25 25 25}
code0 {configwindow->osc = osc;}
code1 {configwindow->base = "/config/";}
code0 {configwindow->init(osc, "/config/");}
} }
Fl_Tabs {} { Fl_Tabs {} {
xywh {5 5 500 330} xywh {5 5 500 330}
@@ -291,7 +293,7 @@ activatebutton_presetdir(true);}
oscilsize->callback = [this](int i){ oscilsize->callback = [this](int i){
oscilsize_widget->value(i-7); oscilsize_widget->value(i-7);
}; };
oscilsize->update("/config/cfg.OscilPower");
oscilsize->doUpdate("/config/cfg.OscilPower");
} {} } {}
} }


+ 5
- 1
source/native-plugins/zynaddsubfx/UI/Connection.cpp View File

@@ -345,14 +345,18 @@ class UI_Interface:public Fl_Osc_Interface
{ {
#ifndef NO_UI #ifndef NO_UI
printf("\n\nDamage(\"%s\")\n", path); printf("\n\nDamage(\"%s\")\n", path);
std::set<Fl_Osc_Widget*> to_update;
for(auto pair:map) { for(auto pair:map) {
if(strstr(pair.first.c_str(), path)) { if(strstr(pair.first.c_str(), path)) {
auto *tmp = dynamic_cast<Fl_Widget*>(pair.second); auto *tmp = dynamic_cast<Fl_Widget*>(pair.second);
if(!tmp || tmp->visible_r()) { if(!tmp || tmp->visible_r()) {
pair.second->update();
to_update.insert(pair.second);
} }
} }
} }

for(auto elm:to_update)
elm->update();
#endif #endif
} }




+ 1
- 1
source/native-plugins/zynaddsubfx/UI/ConnectionDummy.cpp View File

@@ -1,7 +1,7 @@
#include "Connection.h" #include "Connection.h"
#include <unistd.h> #include <unistd.h>
namespace GUI { namespace GUI {
ui_handle_t createUi(Fl_Osc_Interface*, void *exit)
ui_handle_t createUi(Fl_Osc_Interface*, void *)
{ {
return 0; return 0;
} }


+ 4
- 1
source/native-plugins/zynaddsubfx/UI/EffUI.fl View File

@@ -29,6 +29,9 @@ decl {\#include "Fl_Osc_Check.H"} {public local
decl {\#include "Fl_EQGraph.H"} {public local decl {\#include "Fl_EQGraph.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include "EnvelopeUI.h"} {public local decl {\#include "EnvelopeUI.h"} {public local
} }


@@ -150,7 +153,7 @@ if (filterwindow!=NULL){
label Type label Type
callback {if(o->value()==2) revp12->activate(); callback {if(o->value()==2) revp12->activate();
else revp12->deactivate();} else revp12->deactivate();}
xywh {110 15 85 15} down_box BORDER_BOX color 14 selection_color 7 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10
xywh {110 15 85 15} box UP_BOX down_box BORDER_BOX color 14 selection_color 7 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10
code0 {o->init("parameter10");} code0 {o->init("parameter10");}
class Fl_Osc_Choice class Fl_Osc_Choice
} { } {


+ 117
- 47
source/native-plugins/zynaddsubfx/UI/EnvelopeFreeEdit.cpp View File

@@ -21,6 +21,12 @@ void EnvelopeFreeEdit::init(void)
oscRegister("Penvdt"); oscRegister("Penvdt");
oscRegister("Penvval"); oscRegister("Penvval");
oscRegister("Penvsustain"); oscRegister("Penvsustain");

//register for non-bulk types
for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
osc->createLink(loc+string("Penvdt") + to_s(i), this);
osc->createLink(loc+string("Penvval") + to_s(i), this);
}
} }


void EnvelopeFreeEdit::OSC_raw(const char *msg) void EnvelopeFreeEdit::OSC_raw(const char *msg)
@@ -36,6 +42,16 @@ void EnvelopeFreeEdit::OSC_raw(const char *msg)
rtosc_blob_t b = rtosc_argument(msg, 0).b; rtosc_blob_t b = rtosc_argument(msg, 0).b;
assert(b.len == MAX_ENVELOPE_POINTS); assert(b.len == MAX_ENVELOPE_POINTS);
memcpy(Penvval, b.data, MAX_ENVELOPE_POINTS); memcpy(Penvval, b.data, MAX_ENVELOPE_POINTS);
} else if(strstr(msg, "Penvval") && !strcmp(args, "c")) {
const char *str = strstr(msg, "Penvval");
int id = atoi(str+7);
assert(0 <= id && id < MAX_ENVELOPE_POINTS);
Penvval[id] = rtosc_argument(msg, 0).i;
} else if(strstr(msg, "Penvdt") && !strcmp(args, "c")) {
const char *str = strstr(msg, "Penvdt");
int id = atoi(str+6);
assert(0 <= id && id < MAX_ENVELOPE_POINTS);
Penvdt[id] = rtosc_argument(msg, 0).i;
} else if(strstr(msg,"Penvsustain") && !strcmp(args, "i")) { } else if(strstr(msg,"Penvsustain") && !strcmp(args, "i")) {
Penvsustain = rtosc_argument(msg, 0).i; Penvsustain = rtosc_argument(msg, 0).i;
} }
@@ -98,6 +114,8 @@ float EnvelopeFreeEdit::getdt(int i) const
return dt(Penvdt[i]); return dt(Penvdt[i]);
} }


static bool ctrldown;

void EnvelopeFreeEdit::draw(void) void EnvelopeFreeEdit::draw(void)
{ {
int ox=x(),oy=y(),lx=w(),ly=h(); int ox=x(),oy=y(),lx=w(),ly=h();
@@ -129,8 +147,10 @@ void EnvelopeFreeEdit::draw(void)
for (int i=1; i<npoints; ++i){ for (int i=1; i<npoints; ++i){
oldxx=xx;oldyy=yy; oldxx=xx;oldyy=yy;
xx=getpointx(i);yy=getpointy(i); xx=getpointx(i);yy=getpointy(i);
if (i==currentpoint) fl_color(FL_RED);
else fl_color(alb);
if (i==currentpoint || (ctrldown && i==lastpoint))
fl_color(FL_RED);
else
fl_color(alb);
fl_line(ox+oldxx,oy+oldyy,ox+xx,oy+yy); fl_line(ox+oldxx,oy+oldyy,ox+xx,oy+yy);
fl_rectf(ox+xx-3,oy+yy-3,6,6); fl_rectf(ox+xx-3,oy+yy-3,6,6);
} }
@@ -151,13 +171,13 @@ void EnvelopeFreeEdit::draw(void)
//Show the envelope duration and the current line duration //Show the envelope duration and the current line duration
fl_font(FL_HELVETICA|FL_BOLD,10); fl_font(FL_HELVETICA|FL_BOLD,10);
float time=0.0; float time=0.0;
if (currentpoint<=0){
if (currentpoint<=0 && (!ctrldown||lastpoint <= 0)){
fl_color(alb); fl_color(alb);
for(int i=1; i<npoints; ++i) for(int i=1; i<npoints; ++i)
time+=getdt(i); time+=getdt(i);
} else { } else {
fl_color(255,0,0);
time=getdt(currentpoint);
fl_color(FL_RED);
time=getdt(lastpoint);
} }
char tmpstr[20]; char tmpstr[20];
if (time<1000.0) if (time<1000.0)
@@ -165,55 +185,99 @@ void EnvelopeFreeEdit::draw(void)
else else
snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0); snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0);
fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0); fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0);
if (lastpoint>=0){
snprintf((char *)&tmpstr,20,"%d", Penvval[lastpoint]);
fl_draw(tmpstr,ox+lx-20,oy+ly-23,20,10,FL_ALIGN_RIGHT,NULL,0);
}
} }


int EnvelopeFreeEdit::handle(int event) int EnvelopeFreeEdit::handle(int event)
{ {
const int x_=Fl::event_x()-x(); const int x_=Fl::event_x()-x();
const int y_=Fl::event_y()-y(); const int y_=Fl::event_y()-y();

if (event==FL_PUSH) {
currentpoint=getnearest(x_,y_);
cpx=x_;
cpdt=Penvdt[currentpoint];
lastpoint=currentpoint;
redraw();
if (pair)
pair->redraw();
}

if (event==FL_RELEASE){
currentpoint=-1;
redraw();
if (pair)
pair->redraw();
}

if (event==FL_DRAG && currentpoint>=0){
int ny=limit(127-(int) (y_*127.0/h()), 0, 127);

Penvval[currentpoint]=ny;

const int dx=(int)((x_-cpx)*0.1);
const int newdt=limit(cpdt+dx,0,127);

if(currentpoint!=0)
Penvdt[currentpoint]=newdt;
else
Penvdt[currentpoint]=0;

oscWrite(to_s("Penvval")+to_s(currentpoint), "c", ny);
oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
oscWrite("Penvdt","");
oscWrite("Penvval","");
redraw();

if(pair)
pair->redraw();
static Fl_Widget *old_focus;
int key;

switch(event) {
case FL_ENTER:
old_focus=Fl::focus();
Fl::focus(this);
// Otherwise the underlying window seems to regrab focus,
// and I can't see the KEYDOWN action.
return 1;
case FL_LEAVE:
Fl::focus(old_focus);
break;
case FL_KEYDOWN:
case FL_KEYUP:
key = Fl::event_key();
if (key==FL_Control_L || key==FL_Control_R){
ctrldown = (event==FL_KEYDOWN);
redraw();
if (pair!=NULL) pair->redraw();
}
break;
case FL_PUSH:
currentpoint=getnearest(x_,y_);
cpx=x_;
cpdt=Penvdt[currentpoint];
lastpoint=currentpoint;
redraw();
if (pair)
pair->redraw();
return 1;
case FL_RELEASE:
currentpoint=-1;
redraw();
if (pair)
pair->redraw();
return 1;
case FL_MOUSEWHEEL:
if (lastpoint>=0) {
if (!ctrldown) {
int ny = Penvval[lastpoint] - Fl::event_dy();
ny = ny < 0 ? 0 : ny > 127 ? 127 : ny;
Penvval[lastpoint] = ny;
oscWrite(to_s("Penvval")+to_s(lastpoint), "c", ny);
oscWrite("Penvval","");
} else if (lastpoint > 0) {
int newdt = Fl::event_dy() + Penvdt[lastpoint];
newdt = newdt < 0 ? 0 : newdt > 127 ? 127 : newdt;
Penvdt[lastpoint] = newdt;
oscWrite(to_s("Penvdt")+to_s(lastpoint), "c", newdt);
oscWrite("Penvdt","");
}
redraw();
if (pair!=NULL) pair->redraw();
return 1;
}
case FL_DRAG:
if (currentpoint>=0){
int ny=limit(127-(int) (y_*127.0/h()), 0, 127);

Penvval[currentpoint]=ny;

const int dx=(int)((x_-cpx)*0.1);
const int newdt=limit(cpdt+dx,0,127);

if(currentpoint!=0)
Penvdt[currentpoint]=newdt;
else
Penvdt[currentpoint]=0;

oscWrite(to_s("Penvval")+to_s(currentpoint), "c", ny);
oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
oscWrite("Penvdt","");
oscWrite("Penvval","");
redraw();

if(pair)
pair->redraw();
return 1;
}
} }


return 1;
// Needed to propagate undo/redo keys.
return 0;
} }


void EnvelopeFreeEdit::update(void) void EnvelopeFreeEdit::update(void)
@@ -230,6 +294,12 @@ void EnvelopeFreeEdit::rebase(std::string new_base)
osc->renameLink(loc+"Penvdt", new_base+"Penvdt", this); osc->renameLink(loc+"Penvdt", new_base+"Penvdt", this);
osc->renameLink(loc+"Penvval", new_base+"Penvval", this); osc->renameLink(loc+"Penvval", new_base+"Penvval", this);
osc->renameLink(loc+"Penvsustain", new_base+"Penvsustain", this); osc->renameLink(loc+"Penvsustain", new_base+"Penvsustain", this);
for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
string dt = string("Penvdt") + to_s(i);
string val = string("Penvval") + to_s(i);
osc->renameLink(loc+dt, new_base+dt, this);
osc->renameLink(loc+val, new_base+val, this);
}
loc = new_base; loc = new_base;
update(); update();
} }

+ 94
- 106
source/native-plugins/zynaddsubfx/UI/EnvelopeUI.fl View File

@@ -20,6 +20,9 @@ decl {\#include "Fl_Osc_Button.H"} {public local
decl {\#include "Fl_Osc_Counter.H"} {public local decl {\#include "Fl_Osc_Counter.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include <stdio.h>} {public local decl {\#include <stdio.h>} {public local
} }


@@ -53,6 +56,21 @@ decl {\#include "common.H"} {public local
decl {\#include "EnvelopeFreeEdit.h"} {public local decl {\#include "EnvelopeFreeEdit.h"} {public local
} }


class PointButton {open : {public Fl_Button, public Fl_Osc_Widget}}
{
Function {PointButton(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label),Fl_Osc_Widget(this)} {open
} {
code {} {}
}
Function {rebase(std::string new_base)} {open
} {
code {loc = new_base;} {}
}
Function {init(std::string path_)} {open
} {
code {ext = path_;} {}
}
}
class EnvelopeUI {open : {public Fl_Osc_Group,PresetsUI_} class EnvelopeUI {open : {public Fl_Osc_Group,PresetsUI_}
} { } {
Function {EnvelopeUI(int x,int y, int w, int h, const char *label=0):Fl_Osc_Group(x,y,w,h,label)} {} { Function {EnvelopeUI(int x,int y, int w, int h, const char *label=0):Fl_Osc_Group(x,y,w,h,label)} {} {
@@ -79,13 +97,13 @@ delete (freemodeeditwindow);} {}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(freemodeeditwindow->loc());} callback {presetsui->copy(freemodeeditwindow->loc());}
xywh {465 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
code0 {freemodeeditwindow->osc = osc; freemodeeditwindow->base = loc();}
xywh {465 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
code0 {freemodeeditwindow->init(osc, loc());}
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(freemodeeditwindow->loc(),this);} callback {presetsui->paste(freemodeeditwindow->loc(),this);}
xywh {482 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {482 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Button addpoint { Fl_Button addpoint {
label {Add point} label {Add point}
@@ -101,8 +119,8 @@ sustaincounter->update();
//sustaincounter->value(Penvsustain); //sustaincounter->value(Penvsustain);
//sustaincounter->maximum(Penvpoints-2);} //sustaincounter->maximum(Penvpoints-2);}
xywh {115 155 80 20} box THIN_UP_BOX labelsize 11 xywh {115 155 80 20} box THIN_UP_BOX labelsize 11
code0 {(void)o;//if (Pfreemode==0) o->hide();}
class Fl_Osc_Button
code0 {(void)o->init("addPoint");}
class PointButton
} }
Fl_Box freeedit { Fl_Box freeedit {
label Envelope label Envelope
@@ -121,20 +139,8 @@ sustaincounter->update();
//sustaincounter->value(Penvsustain); //sustaincounter->value(Penvsustain);
//sustaincounter->maximum(Penvpoints-2);} //sustaincounter->maximum(Penvpoints-2);}
xywh {200 155 80 20} box THIN_UP_BOX labelsize 11 xywh {200 155 80 20} box THIN_UP_BOX labelsize 11
code0 {(void)o;//if (Pfreemode==0) o->hide();}
class Fl_Osc_Button
}
Fl_Check_Button freemodebutton {
label FreeMode
callback {
o->oscWrite("Pfreemode", o->value() ? "T" : "F");
reinit(o->value());

freeedit->lastpoint=-1;
freeedit->redraw();}
tooltip {Enable or disable the freemode} xywh {10 155 95 20} labelsize 11
code0{o->init("Pfreemode");}
class Fl_Osc_Check
code0 {(void)o->init("delPoint");}
class PointButton
} }
Fl_Check_Button forcedreleasecheck { Fl_Check_Button forcedreleasecheck {
label frcR label frcR
@@ -170,6 +176,18 @@ envfree->redraw();}
code3 {o->init("Penvsustain");} code3 {o->init("Penvsustain");}
class Fl_Osc_Counter class Fl_Osc_Counter
} }
Fl_Check_Button freemodehack {
xywh {0 0 0 0} down_box DOWN_BOX
callback{refresh_display();}
code0 {o->init("Pfreemode");o->hide();}
class Fl_Osc_Check
}
Fl_Button {} {
label {Cancel Freemode}
callback {disable_freemode();}
xywh {5 155 105 20} box THIN_UP_BOX labelsize 11 labelcolor 1
class Fl_Osc_Button
}
} }
} }
Function {make_ADSR_window()} {} { Function {make_ADSR_window()} {} {
@@ -185,12 +203,12 @@ envfree->redraw();}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(envADSR->loc());} callback {presetsui->copy(envADSR->loc());}
xywh {150 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {150 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(envADSR->loc(),this);} callback {presetsui->paste(envADSR->loc(),this);}
xywh {167 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {167 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Dial e1adt { Fl_Dial e1adt {
label {A.dt} label {A.dt}
@@ -234,8 +252,9 @@ envfree->redraw();}
} }
Fl_Button {} { Fl_Button {} {
label E label E
callback {freemodeeditwindow->show();}
callback {open_as_freemode();}
tooltip {Envelope window} xywh {185 5 15 15} labelfont 1 labelsize 10 tooltip {Envelope window} xywh {185 5 15 15} labelfont 1 labelsize 10
class Fl_Osc_Button
} }
Fl_Check_Button e1linearenvelope { Fl_Check_Button e1linearenvelope {
label L label L
@@ -259,12 +278,12 @@ envfree->redraw();}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(envASR->loc());} callback {presetsui->copy(envASR->loc());}
xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(envASR->loc(),this);} callback {presetsui->paste(envASR->loc(),this);}
xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Dial e2aval { Fl_Dial e2aval {
label {A.val} label {A.val}
@@ -309,8 +328,9 @@ envfree->redraw();}
} }
Fl_Button {} { Fl_Button {} {
label E label E
callback {freemodeeditwindow->show();}
callback {open_as_freemode();}
tooltip {Envelope window} xywh {190 5 15 15} labelfont 1 labelsize 10 tooltip {Envelope window} xywh {190 5 15 15} labelfont 1 labelsize 10
class Fl_Osc_Button
} }
} }
} }
@@ -327,12 +347,12 @@ envfree->redraw();}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(envADSRfilter->loc());} callback {presetsui->copy(envADSRfilter->loc());}
xywh {220 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {220 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(envADSRfilter->loc(),this);} callback {presetsui->paste(envADSRfilter->loc(),this);}
xywh {237 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {237 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Dial e3aval { Fl_Dial e3aval {
label {A.val} label {A.val}
@@ -390,8 +410,9 @@ envfree->redraw();}
} }
Fl_Button {} { Fl_Button {} {
label E label E
callback {freemodeeditwindow->show();}
callback {open_as_freemode();}
xywh {255 5 15 15} labelfont 1 labelsize 10 xywh {255 5 15 15} labelfont 1 labelsize 10
class Fl_Osc_Button
} }
} }
} }
@@ -410,12 +431,12 @@ envfree->redraw();}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(envASRbw->loc());} callback {presetsui->copy(envASRbw->loc());}
xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(envASRbw->loc(),this);} callback {presetsui->paste(envASRbw->loc(),this);}
xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7
xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 55
} }
Fl_Dial e4aval { Fl_Dial e4aval {
label {A.val} label {A.val}
@@ -460,8 +481,9 @@ envfree->redraw();}
} }
Fl_Button {} { Fl_Button {} {
label E label E
callback {freemodeeditwindow->show();}
callback {open_as_freemode();}
xywh {190 5 15 15} labelfont 1 labelsize 10 xywh {190 5 15 15} labelfont 1 labelsize 10
class Fl_Osc_Button
} }
} }
} }
@@ -478,8 +500,9 @@ envfree->redraw();}
} { } {
Fl_Button {} { Fl_Button {} {
label E label E
callback {freemodeeditwindow->show();}
callback {open_as_freemode();}
xywh {185 5 15 15} labelfont 1 labelsize 10 xywh {185 5 15 15} labelfont 1 labelsize 10
class Fl_Osc_Button
} }
Fl_Box freeeditsmall { Fl_Box freeeditsmall {
label Envelope label Envelope
@@ -501,6 +524,18 @@ envfree->redraw();}
} }
} }
} }
Function {open_as_freemode()} {open
} {
code {
if (!freemodehack->value() &&
fl_choice("Convert envelope to free mode data?","No","Yes",NULL)==0)
return;
freemodehack->oscWrite("Pfreemode", "T");
freeedit->update();
freemodeeditwindow->show();
freemodeeditwindow->position(Fl::event_x_root()-20, Fl::event_y_root()+20);
} {}
}
Function {init(int env_type, Fl_Osc_Interface *osc_, std::string base_, std::string ext_)} {open Function {init(int env_type, Fl_Osc_Interface *osc_, std::string base_, std::string ext_)} {open
} { } {
code {osc = osc_; code {osc = osc_;
@@ -533,113 +568,68 @@ freeeditsmall->setpair(freeedit);
freeedit->setpair(freeeditsmall); freeedit->setpair(freeeditsmall);




refresh();} {}
refresh_display();} {}
} }
Function {rebase(std::string new_base)} {open Function {rebase(std::string new_base)} {open
} { } {
code {Fl_Osc_Group::rebase(new_base); code {Fl_Osc_Group::rebase(new_base);
freemodeeditwindow->rebase(new_base+ext);} {} freemodeeditwindow->rebase(new_base+ext);} {}
} }
Function {reinit(bool Pfreemode)} {open
Function {disable_freemode()} {open
} { } {
code {
//if(!Pfreemode){
// int answer=fl_choice("Disable the free mode of the Envelope?","No","Yes",NULL);
// freemodebutton->value(Pfreemode);
// if (answer==0)
// return;
//};
freeedit->update();
code {if (fl_choice("Discard free mode data?","No","Yes",NULL)==0)
return;


hide(); hide();
const int winx=freemodeeditwindow->x();
const int winy=freemodeeditwindow->y();
bool reshow = freemodeeditwindow->visible();
int winx = Fl::event_x_root()-10;
int winy = Fl::event_y_root()-155;
winx = winx < 1 ? 1 : winx;
winy = winy < 1 ? 1 : winy;
freemodeeditwindow->hide(); freemodeeditwindow->hide();


envwindow->hide(); envwindow->hide();
Fl_Group *par=envwindow->parent(); Fl_Group *par=envwindow->parent();
par->hide(); par->hide();


refresh();
freemodehack->oscWrite("Pfreemode", "F");
freeedit->update();
envwindow->show(); envwindow->show();
par->redraw(); par->redraw();


par->show(); par->show();
show(); show();
freemodeeditwindow->position(winx,winy);
if(reshow)
freemodeeditwindow->show();

if (Pfreemode) {
freemodebutton->value(1);
addpoint->show();
deletepoint->show();
forcedreleasecheck->show();
sustaincounter->show();
envstretchdial->show();
} else{
freemodebutton->value(0);
addpoint->hide();
deletepoint->hide();
forcedreleasecheck->hide();
sustaincounter->hide();
envstretchdial->hide();
};
} {selected
}
freemodeeditwindow->position(winx,winy);} {}
}
Function {refresh()} { open }
{ code {
freemodehack->oscWrite("Pfreemode");
} {}
} }
Function {refresh()} {open
Function {refresh_display()} {open
} { } {
code { code {

sustaincounter->value(Penvsustain); sustaincounter->value(Penvsustain);
sustaincounter->maximum(Penvpoints-2); sustaincounter->maximum(Penvpoints-2);


envstretchdial->value(Penvstretch); envstretchdial->value(Penvstretch);


linearenvelopecheck->value(Plinearenvelope);

//Conditionally display widgets
if(freemodebutton->value()) {
freemodebutton->value(1);
addpoint->show();
deletepoint->show();
forcedreleasecheck->show();
sustaincounter->show();
envstretchdial->show();
} else {
freemodebutton->value(0);
addpoint->hide();
deletepoint->hide();
forcedreleasecheck->hide();
sustaincounter->hide();
envstretchdial->hide();
}

if(freemodebutton->value() || Envmode>2)
linearenvelopecheck->hide();
else
linearenvelopecheck->show();
linearenvelopecheck->value(Plinearenvelope);
linearenvelopecheck->show();


forcedreleasecheck->value(Pforcedrelease); forcedreleasecheck->value(Pforcedrelease);


if (freemodebutton->value()==0){
addpoint->hide();
deletepoint->hide();
} else {
addpoint->show();
deletepoint->show();
}

envADSR->hide(); envADSR->hide();
envASR->hide(); envASR->hide();
envADSRfilter->hide(); envADSRfilter->hide();
envASRbw->hide(); envASRbw->hide();
envfree->hide(); envfree->hide();


if (freemodebutton->value()==0){
if (freemodehack->value()) {
envwindow=envfree;
freeedit->update();
} else {
freemodeeditwindow->hide();
switch(Envmode){ switch(Envmode){
case 1: case 1:
case 2: case 2:
@@ -656,10 +646,8 @@ if (freemodebutton->value()==0){
break; break;
default: default:
break; break;
};
}else{
envwindow=envfree;
};
}
}


assert(envwindow); assert(envwindow);
envwindow->resize(this->x(),this->y(),this->w(),this->h()); envwindow->resize(this->x(),this->y(),this->w(),this->h());


+ 3
- 0
source/native-plugins/zynaddsubfx/UI/FilterUI.fl View File

@@ -26,6 +26,9 @@ decl {\#include "Fl_Osc_Output.H"} {public local
decl {\#include "Fl_Osc_Slider.H"} {public local decl {\#include "Fl_Osc_Slider.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include <cmath>} {private local decl {\#include <cmath>} {private local
} }




+ 1
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_DialF.cpp View File

@@ -39,6 +39,7 @@ void Fl_Osc_DialF::init(const char *path)
ext = path; ext = path;
loc = pane->base; loc = pane->base;
oscRegister(path); oscRegister(path);
integer_step = false;
}; };


Fl_Osc_DialF::~Fl_Osc_DialF(void) Fl_Osc_DialF::~Fl_Osc_DialF(void)


+ 3
- 2
source/native-plugins/zynaddsubfx/UI/Fl_Osc_ListView.cpp View File

@@ -1,4 +1,5 @@
#include "Fl_Osc_ListView.H" #include "Fl_Osc_ListView.H"
#include "Fl_Osc_Pane.H"
#include <cstdio> #include <cstdio>
#include <rtosc/rtosc.h> #include <rtosc/rtosc.h>


@@ -21,7 +22,7 @@ void Fl_Osc_ListView::init(const char *path_)
path = path_; path = path_;
data = new Osc_SimpleListModel(osc); data = new Osc_SimpleListModel(osc);
data->callback = [this](Osc_SimpleListModel::list_t l){this->doUpdate(l);}; data->callback = [this](Osc_SimpleListModel::list_t l){this->doUpdate(l);};
data->update(loc+path_);
data->doUpdate(loc+path_);
} }


void Fl_Osc_ListView::doUpdate(Osc_SimpleListModel::list_t l) void Fl_Osc_ListView::doUpdate(Osc_SimpleListModel::list_t l)
@@ -33,7 +34,7 @@ void Fl_Osc_ListView::doUpdate(Osc_SimpleListModel::list_t l)
} }
void Fl_Osc_ListView::update(void) void Fl_Osc_ListView::update(void)
{ {
data->update(loc+path);
data->doUpdate(loc+path);
} }


void Fl_Osc_ListView::insert(std::string s, int offset) void Fl_Osc_ListView::insert(std::string s, int offset)


+ 1
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Numeric_Input.cpp View File

@@ -1,3 +1,4 @@
#include <stdlib.h>
#include "Fl_Osc_Numeric_Input.H" #include "Fl_Osc_Numeric_Input.H"


Fl_Osc_Numeric_Input::Fl_Osc_Numeric_Input(int X, int Y, int W, int H, const char *label) Fl_Osc_Numeric_Input::Fl_Osc_Numeric_Input(int X, int Y, int W, int H, const char *label)


+ 5
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Pane.H View File

@@ -3,6 +3,7 @@
#include <FL/Fl_Group.H> #include <FL/Fl_Group.H>
#include <FL/Fl_Double_Window.H> #include <FL/Fl_Double_Window.H>
#include <string> #include <string>
#include "Osc_DataModel.h"


class Fl_Osc_Pane class Fl_Osc_Pane
{ {
@@ -16,8 +17,12 @@ class Fl_Osc_Pane


class Fl_Osc_Window:public Fl_Double_Window, public Fl_Osc_Pane class Fl_Osc_Window:public Fl_Double_Window, public Fl_Osc_Pane
{ {
Osc_DataModel *title_ext;
std::string title_orig;
std::string title_new;
public: public:
Fl_Osc_Window(int w, int h, const char *L=0); Fl_Osc_Window(int w, int h, const char *L=0);
~Fl_Osc_Window(void);


void init(Fl_Osc_Interface *osc_, std::string loc_); void init(Fl_Osc_Interface *osc_, std::string loc_);
virtual std::string loc(void) const; virtual std::string loc(void) const;


+ 29
- 2
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Pane.cpp View File

@@ -9,15 +9,42 @@ Fl_Osc_Pane::Fl_Osc_Pane(void)




Fl_Osc_Window::Fl_Osc_Window(int w, int h, const char *L) Fl_Osc_Window::Fl_Osc_Window(int w, int h, const char *L)
:Fl_Double_Window(w,h,L)
:Fl_Double_Window(w,h,L), title_ext(NULL)
{} {}
void Fl_Osc_Window::init(Fl_Osc_Interface *osc_, std::string loc_) void Fl_Osc_Window::init(Fl_Osc_Interface *osc_, std::string loc_)
{ {
title_ext = new Osc_DataModel(osc_);
title_ext->doUpdate("/ui/title");
title_ext->callback = [this](string next) {
//printf("old: %s\n", title_orig.c_str());
const char *orig = title_orig.c_str();
// 12345678901
const char *sub = strstr(orig, "zynaddsubfx");
if(!sub)
sub = strstr(orig, "ZynAddSubFX");
title_new = "";
while(*orig) {
if(orig == sub) {
title_new += next;
orig += 11;
} else
title_new += *orig++;
}
//title_new = title_orig + next;
this->label(title_new.c_str());
};
title_orig = label();

osc = osc_; osc = osc_;
base = loc_; base = loc_;
} }


Fl_Osc_Window::~Fl_Osc_Window(void)
{
delete title_ext;
}

std::string Fl_Osc_Window::loc(void) const std::string Fl_Osc_Window::loc(void) const
{ {
return base; return base;


+ 3
- 2
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Slider.H View File

@@ -5,7 +5,6 @@


class Fl_Osc_Slider:public Fl_Slider, public Fl_Osc_Widget class Fl_Osc_Slider:public Fl_Slider, public Fl_Osc_Widget
{ {

public: public:
Fl_Osc_Slider(int X, int Y, int W, int H, const char *label = NULL); Fl_Osc_Slider(int X, int Y, int W, int H, const char *label = NULL);
// string name, // string name,
@@ -22,10 +21,12 @@ class Fl_Osc_Slider:public Fl_Slider, public Fl_Osc_Widget
void callback(Fl_Callback *cb, void *p = NULL); void callback(Fl_Callback *cb, void *p = NULL);
//MIDI Learn //MIDI Learn
int handle(int);
int handle(int ev, int X, int Y, int W, int H);
int handle(int ev);


void cb(void); void cb(void);
static void _cb(Fl_Widget *w, void *); static void _cb(Fl_Widget *w, void *);
float reset_value;
private: private:
char osc_type; char osc_type;
std::pair<Fl_Callback*, void*> cb_data; std::pair<Fl_Callback*, void*> cb_data;


+ 68
- 3
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Slider.cpp View File

@@ -7,6 +7,7 @@
#include <cmath> #include <cmath>
#include <cassert> #include <cassert>
#include <sstream> #include <sstream>
#include "../Misc/Util.h"


static double min__(double a, double b) static double min__(double a, double b)
{ {
@@ -14,7 +15,8 @@ static double min__(double a, double b)
} }


Fl_Osc_Slider::Fl_Osc_Slider(int X, int Y, int W, int H, const char *label) Fl_Osc_Slider::Fl_Osc_Slider(int X, int Y, int W, int H, const char *label)
:Fl_Slider(X,Y,W,H,label), Fl_Osc_Widget(this), cb_data(NULL, NULL)
:Fl_Slider(X,Y,W,H,label), Fl_Osc_Widget(this), reset_value(0),
cb_data(NULL, NULL)
{ {
//bounds(0.0f,1.0f); //bounds(0.0f,1.0f);
Fl_Slider::callback(Fl_Osc_Slider::_cb); Fl_Slider::callback(Fl_Osc_Slider::_cb);
@@ -72,7 +74,7 @@ void Fl_Osc_Slider::callback(Fl_Callback *cb, void *p)
cb_data.second = p; cb_data.second = p;
} }


int Fl_Osc_Slider::handle(int ev)
int Fl_Osc_Slider::handle(int ev, int X, int Y, int W, int H)
{ {
bool middle_mouse = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift()); bool middle_mouse = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift());
bool ctl_click = (ev == FL_PUSH && Fl::event_state(FL_BUTTON1) && Fl::event_ctrl()); bool ctl_click = (ev == FL_PUSH && Fl::event_state(FL_BUTTON1) && Fl::event_ctrl());
@@ -85,7 +87,70 @@ int Fl_Osc_Slider::handle(int ev)
osc->write("/unlearn", "s", (loc+ext).c_str()); osc->write("/unlearn", "s", (loc+ext).c_str());
return 1; return 1;
} }
return Fl_Slider::handle(ev);

int handled, rounded;
bool reset_requested = false;
switch (ev) {
case FL_MOUSEWHEEL:
if (this == Fl::belowmouse() && Fl::e_dy != 0) {
int step = 1, divisor = 16;
switch (Fl::event_state() & ( FL_CTRL | FL_SHIFT)) {
case FL_SHIFT:
step = 8;
case FL_SHIFT | FL_CTRL:
break;
case FL_CTRL:
divisor = 128;
default:
step = (fabs(maximum() - minimum()) + 1) / divisor;
if (step < 1)
step = 1;
}
int dy = minimum() <= maximum() ? Fl::e_dy : -Fl::e_dy;
handle_drag(clamp(value() + step * dy));
}
return 1;
case FL_RELEASE:
rounded = value() + 0.5;
value(clamp((double)rounded));
if (Fl::event_clicks() == 1) {
Fl::event_clicks(0);
reset_requested = true;
}
}
if (!Fl::event_shift()) {
handled = Fl_Slider::handle(ev, X, Y, W, H);
if (reset_requested) {
value(reset_value);
value_damage();
if (this->when() != 0)
do_callback();
}
return handled;
}

// Slow down the drag.
// Handy if the slider has a large delta bigger than a mouse quantum.
// Somewhat tricky to use with OSC feedback.
// To change direction of movement, one must reclick the handle.
int old_value = value();
handled = Fl_Slider::handle(ev, X, Y, W, H);
int delta = value() - old_value;
if (ev == FL_DRAG && (delta < -1 || delta > 1)) {
value(clamp((old_value + (delta > 0 ? 1 : -1))));
value_damage();
do_callback();
}
return handled;
}

int Fl_Osc_Slider::handle(int ev) {
return handle(ev,
x()+Fl::box_dx(box()),
y()+Fl::box_dy(box()),
w()-Fl::box_dw(box()),
h()-Fl::box_dh(box()));
} }


void Fl_Osc_Slider::update(void) void Fl_Osc_Slider::update(void)


+ 21
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_TSlider.H View File

@@ -0,0 +1,21 @@
#ifndef FL_OSC_TSLIDER_H
#define FL_OSC_TSLIDER_H
#include "Fl_Osc_Slider.H"
#include "TipWin.h"


class Fl_Osc_TSlider:public Fl_Osc_Slider
{
public:
Fl_Osc_TSlider(int x, int y, int w, int h, const char *label = 0);
~Fl_Osc_TSlider();
int handle(int event);
void set_transform(float scale = 1.0, float offset = 0.0);
float transform(float x);
void setRounding(unsigned int digits = 0);
private:
class TipWin * tipwin;
float value_offset;
float value_scale;
};
#endif

+ 65
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_TSlider.cpp View File

@@ -0,0 +1,65 @@
#include <cmath>
#include "Fl_Osc_TSlider.H"
//Copyright (c) 2015 Christopher Oliver
//License: GNU GPL version 2 or later


Fl_Osc_TSlider::Fl_Osc_TSlider(int x, int y, int w, int h, const char *label)
:Fl_Osc_Slider(x, y, w, h, label), value_offset(0.0), value_scale(1.0)
{
Fl_Group *save = Fl_Group::current();
tipwin = new TipWin();
tipwin->hide();
Fl_Group::current(save);
tipwin->setRounding();
}

Fl_Osc_TSlider::~Fl_Osc_TSlider()
{
if (tipwin)
delete tipwin;
}

void Fl_Osc_TSlider::setRounding(unsigned int digits)
{
tipwin->setRounding(digits);
}


int Fl_Osc_TSlider::handle(int event)
{
int super = 1;

super = Fl_Osc_Slider::handle(event);

switch(event) {
case FL_PUSH:
case FL_MOUSEWHEEL:
if (!Fl::event_inside(x(),y(),w(),h()))
return(1);
tipwin->position(Fl::event_x_root()-Fl::event_x()+x(),
Fl::event_y_root()-Fl::event_y()+h()+y()+5);
case FL_DRAG:
tipwin->showValue(transform(value()));
break;
case FL_RELEASE:
case FL_HIDE:
case FL_LEAVE:
if (tipwin)
tipwin->hide();
return 1;
}
return super;
}

void Fl_Osc_TSlider::set_transform(float scale, float offset)
{
value_offset = offset;
value_scale = scale;
}

float Fl_Osc_TSlider::transform(float x)
{
return value_scale * x + value_offset;
}

+ 16
- 10
source/native-plugins/zynaddsubfx/UI/Fl_Osc_VSlider.H View File

@@ -1,29 +1,35 @@
#pragma once #pragma once
#include <FL/Fl_Value_Slider.H> #include <FL/Fl_Value_Slider.H>
#include "Fl_Osc_Widget.H"
#include "Fl_Osc_Slider.H"
#include <string> #include <string>


class Fl_Osc_VSlider:public Fl_Value_Slider, public Fl_Osc_Widget
class Fl_Osc_VSlider:public Fl_Osc_Slider
{ {


public: public:
Fl_Osc_VSlider(int X, int Y, int W, int H, const char *label = NULL); Fl_Osc_VSlider(int X, int Y, int W, int H, const char *label = NULL);


virtual ~Fl_Osc_VSlider(void); virtual ~Fl_Osc_VSlider(void);
void OSC_value(char);
void OSC_value(int);
void OSC_value(float);
void init(std::string, char type = 'i');
Fl_Font textfont_;
Fl_Fontsize textsize_;
Fl_Color textcolor_;


void init(std::string, char type = 'i');
//Refetch parameter information //Refetch parameter information
void update(void);
void callback(Fl_Callback *cb, void *p = NULL);
//MIDI Learn //MIDI Learn
int handle(int); int handle(int);


void cb(void);
static void _cb(Fl_Widget *w, void *);
// Value Slider add-ins.
Fl_Font textfont() const {return textfont_;}
void textfont(Fl_Font s) {textfont_ = s;}
Fl_Fontsize textsize() const {return textsize_;}
void textsize(Fl_Fontsize s) {textsize_ = s;}
Fl_Color textcolor() const {return textcolor_;}
void textcolor(Fl_Color s) {textcolor_ = s;}

protected:
void draw(void);
private: private:
char osc_type; char osc_type;
std::pair<Fl_Callback*, void*> cb_data; std::pair<Fl_Callback*, void*> cb_data;


+ 40
- 61
source/native-plugins/zynaddsubfx/UI/Fl_Osc_VSlider.cpp View File

@@ -1,4 +1,5 @@
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/fl_draw.H>
#include "Fl_Osc_VSlider.H" #include "Fl_Osc_VSlider.H"
#include "Fl_Osc_Interface.h" #include "Fl_Osc_Interface.h"
#include "Fl_Osc_Pane.H" #include "Fl_Osc_Pane.H"
@@ -9,82 +10,60 @@
#include <sstream> #include <sstream>


Fl_Osc_VSlider::Fl_Osc_VSlider(int X, int Y, int W, int H, const char *label) Fl_Osc_VSlider::Fl_Osc_VSlider(int X, int Y, int W, int H, const char *label)
:Fl_Value_Slider(X,Y,W,H,label), Fl_Osc_Widget(this), cb_data(NULL, NULL)
:Fl_Osc_Slider(X,Y,W,H,label), cb_data(NULL, NULL)
{ {
//bounds(0.0f,1.0f); //bounds(0.0f,1.0f);
Fl_Slider::callback(Fl_Osc_VSlider::_cb);
}

void Fl_Osc_VSlider::init(std::string path_, char type_)
{
osc_type = type_;
ext = path_;
oscRegister(ext.c_str());
Fl_Slider::callback(Fl_Osc_Slider::_cb);
textfont_ = FL_HELVETICA;
textsize_ = 10;
textcolor_ = FL_FOREGROUND_COLOR;
} }


Fl_Osc_VSlider::~Fl_Osc_VSlider(void) Fl_Osc_VSlider::~Fl_Osc_VSlider(void)
{} {}


void Fl_Osc_VSlider::OSC_value(char v)
{
Fl_Slider::value(v+minimum()+fmodf(value(), 1.0f));
}
void Fl_Osc_VSlider::OSC_value(int v)
{
Fl_Slider::value(v+minimum()+fmodf(value(), 1.0f));
}

void Fl_Osc_VSlider::OSC_value(float v)
void Fl_Osc_VSlider::init(std::string path_, char type_)
{ {
Fl_Slider::value(v+minimum());
Fl_Osc_Slider::init(path_, type_);
} }


void Fl_Osc_VSlider::cb(void)
{
const float val = Fl_Slider::value();
if(osc_type == 'f')
oscWrite(ext, "f", val-minimum());
else if(osc_type == 'i')
oscWrite(ext, "i", (int)(val-minimum()));
else {
fprintf(stderr, "invalid `c' from vslider %s%s, using `i'\n", loc.c_str(), ext.c_str());
oscWrite(ext, "i", (int)(val-minimum()));
void Fl_Osc_VSlider::draw() {
int sxx = x(), syy = y(), sww = w(), shh = h();
int bxx = x(), byy = y(), bww = w(), bhh = h();
if (horizontal()) {
bww = 35; sxx += 35; sww -= 35;
} else {
syy += 25; bhh = 25; shh -= 25;
} }
//OSC_value(val);
if(cb_data.first)
cb_data.first(this, cb_data.second);
}

void Fl_Osc_VSlider::callback(Fl_Callback *cb, void *p)
{
cb_data.first = cb;
cb_data.second = p;
if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color());
Fl_Osc_Slider::draw(sxx+Fl::box_dx(box()),
syy+Fl::box_dy(box()),
sww-Fl::box_dw(box()),
shh-Fl::box_dh(box()));
draw_box(box(),bxx,byy,bww,bhh,color());
char buf[128];
format(buf);
fl_font(textfont(), textsize());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP);
} }


int Fl_Osc_VSlider::handle(int ev) int Fl_Osc_VSlider::handle(int ev)
{ {
bool middle_mouse = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift());
bool ctl_click = (ev == FL_PUSH && Fl::event_state(FL_BUTTON1) && Fl::event_ctrl());
bool shift_middle = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && Fl::event_shift());
if(middle_mouse || ctl_click) {
printf("Trying to learn...\n");
osc->write("/learn", "s", (loc+ext).c_str());
return 1;
} else if(shift_middle) {
osc->write("/unlearn", "s", (loc+ext).c_str());
return 1;
if (ev == FL_PUSH && Fl::visible_focus()) {
Fl::focus(this);
redraw();
}
int sxx = x(), syy = y(), sww = w(), shh = h();
if (horizontal()) {
sxx += 35; sww -= 35;
} else {
syy += 25; shh -= 25;
} }
return Fl_Value_Slider::handle(ev);
}

void Fl_Osc_VSlider::update(void)
{
oscWrite(ext, "");
}


void Fl_Osc_VSlider::_cb(Fl_Widget *w, void *)
{
static_cast<Fl_Osc_VSlider*>(w)->cb();
return Fl_Osc_Slider::handle(ev,
sxx+Fl::box_dx(box()),
syy+Fl::box_dy(box()),
sww-Fl::box_dw(box()),
shh-Fl::box_dh(box()));
} }

+ 1
- 2
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Widget.H View File

@@ -4,7 +4,6 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include "Fl_Osc_Interface.h" #include "Fl_Osc_Interface.h"
#include "Fl_Osc_Pane.H"
#include <FL/Fl_Group.H> #include <FL/Fl_Group.H>


class Fl_Osc_Widget class Fl_Osc_Widget
@@ -54,5 +53,5 @@ class Fl_Osc_Widget
std::string ext; std::string ext;
Fl_Osc_Interface *osc; Fl_Osc_Interface *osc;
protected: protected:
Fl_Osc_Pane *fetch_osc_pane(Fl_Widget *w);
class Fl_Osc_Pane *fetch_osc_pane(Fl_Widget *w);
}; };

+ 1
- 0
source/native-plugins/zynaddsubfx/UI/Fl_Osc_Widget.cpp View File

@@ -1,4 +1,5 @@
#include "Fl_Osc_Widget.H" #include "Fl_Osc_Widget.H"
#include "Fl_Osc_Pane.H"
#include <rtosc/rtosc.h> #include <rtosc/rtosc.h>


Fl_Osc_Widget::Fl_Osc_Widget(void) //Deprecated Fl_Osc_Widget::Fl_Osc_Widget(void) //Deprecated


+ 3
- 0
source/native-plugins/zynaddsubfx/UI/LFOUI.fl View File

@@ -20,6 +20,9 @@ decl {\#include "Fl_Osc_Choice.H"} {public local
decl {\#include "Fl_Osc_Check.H"} {public local decl {\#include "Fl_Osc_Check.H"} {public local
} }


decl {\#include "Fl_Osc_Pane.H"} {public local
}

decl {\#include "../globals.h"} {private global decl {\#include "../globals.h"} {private global
} }




+ 71
- 8
source/native-plugins/zynaddsubfx/UI/MasterUI.fl View File

@@ -61,6 +61,9 @@ decl {\#include "VuPartMeter.h"} {public local
decl {\#include "Fl_Osc_Dial.H"} {private local decl {\#include "Fl_Osc_Dial.H"} {private local
} }


decl {\#include "Osc_DataModel.h"} {private local
}

decl {\#include "VuMasterMeter.h"} {public local decl {\#include "VuMasterMeter.h"} {public local
} }


@@ -241,7 +244,13 @@ class MasterUI {open
close(); close();
};} open };} open
xywh {330 365 390 525} type Double xclass zynaddsubfx visible xywh {330 365 390 525} type Double xclass zynaddsubfx visible
class Fl_Osc_Window
} { } {
Fl_Box dummy_again {
xywh {25 25 25 25}
code0 {masterwindow->init(osc, "");}
}

Fl_Group win_root {open Fl_Group win_root {open
xywh {0 0 390 525} xywh {0 0 390 525}
class Fl_Osc_Group class Fl_Osc_Group
@@ -258,6 +267,11 @@ class MasterUI {open
callback {do_new_master();} callback {do_new_master();}
xywh {25 25 100 20} xywh {25 25 100 20}
} }
MenuItem {} {
label {&Revert changes...}
callback {do_revert_changes();}
xywh {25 25 100 20}
}
MenuItem {} { MenuItem {} {
label {&Open Parameters...} label {&Open Parameters...}
callback {\#if USE_NSM callback {\#if USE_NSM
@@ -568,7 +582,7 @@ syseffectui->refresh();}
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy("/sysefx"+to_s(nsyseff)+"/");} callback {presetsui->copy("/sysefx"+to_s(nsyseff)+"/");}
xywh {180 187 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7
xywh {180 187 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
@@ -855,8 +869,7 @@ GNU General Public License for details.}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {syseffsendwindow->osc = osc; assert(osc);}
code1 {syseffsendwindow->base = "";}
code0 {syseffsendwindow->init(osc,"");}
} }
Fl_Scroll syseffscroll {open Fl_Scroll syseffscroll {open
xywh {0 45 120 170} box FLAT_BOX resizable xywh {0 45 120 170} box FLAT_BOX resizable
@@ -880,8 +893,7 @@ GNU General Public License for details.}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {panelwindow->osc = osc;}
code1 {panelwindow->base = "/";}
code0 {panelwindow->init(osc,"/");}
} }
Fl_Scroll {} {open Fl_Scroll {} {open
xywh {0 5 570 310} type HORIZONTAL box THIN_UP_BOX xywh {0 5 570 310} type HORIZONTAL box THIN_UP_BOX
@@ -924,8 +936,7 @@ if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL))
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {simplemasterwindow->osc = osc;}
code1 {simplemasterwindow->base = "/";}
code0 {simplemasterwindow->init(osc, "/");}
} }
Fl_Menu_Bar simplemastermenu { Fl_Menu_Bar simplemastermenu {
xywh {0 0 600 25} xywh {0 0 600 25}
@@ -939,6 +950,11 @@ if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL))
callback {do_new_master();} callback {do_new_master();}
xywh {30 30 100 20} xywh {30 30 100 20}
} }
MenuItem {} {
label {&Revert changes...}
callback {do_revert_changes();}
xywh {30 30 100 20}
}
MenuItem {} { MenuItem {} {
label {&Open Parameters...} label {&Open Parameters...}
callback {do_load_master();} callback {do_load_master();}
@@ -1427,6 +1443,7 @@ virkeys->take_focus();}
label {User Interface mode} label {User Interface mode}
callback {*exitprogram=1;} callback {*exitprogram=1;}
xywh {342 246 430 250} type Double hide non_modal xywh {342 246 430 250} type Double hide non_modal
class Fl_Osc_Window
} { } {
Fl_Box {} { Fl_Box {} {
label {Welcome to ZynAddSubFX} label {Welcome to ZynAddSubFX}
@@ -1489,6 +1506,25 @@ osc=osc_;
ninseff=0; ninseff=0;
nsyseff=0; nsyseff=0;
npart=0; npart=0;
last_loaded[0]=0;
loading_next[0]=0;
last_xmz = new Osc_DataModel(osc);
last_xmz->callback = [this](std::string filestr) {
const char *filename = filestr.c_str();
if (filename[0] != 0)
strncpy(last_loaded, filename, XMZ_PATH_MAX);
else if (loading_next[0] != 0) {
strncpy(last_loaded, loading_next, XMZ_PATH_MAX);
loading_next[0] = 0;
} else
last_loaded[0] = 0;
last_loaded[XMZ_PATH_MAX - 1] = 0;
char *label = last_loaded[0] == 0 ? NULL
: ((label = strrchr(last_loaded, '/'))) ? label+1
: last_loaded;
setfilelabel(label);
};
last_xmz->doUpdate("/last_xmz");


for (int i=0;i<NUM_SYS_EFX;i++) for (int i=0;i<NUM_SYS_EFX;i++)
for (int j=0;j<NUM_SYS_EFX;j++) for (int j=0;j<NUM_SYS_EFX;j++)
@@ -1556,6 +1592,7 @@ simplelistitemgroup->redraw();} {}
microtonalui=new MicrotonalUI(osc, "/microtonal/"); microtonalui=new MicrotonalUI(osc, "/microtonal/");


osc->write("/reset_master"); osc->write("/reset_master");
osc->write("/last_xmz");
npartcounter->value(1); npartcounter->value(1);
refresh_master_ui(); refresh_master_ui();
updatepanel();} {} updatepanel();} {}
@@ -1565,9 +1602,29 @@ microtonalui=new MicrotonalUI(osc, "/microtonal/");
do_new_master_unconditional(); do_new_master_unconditional();
}} {} }} {}
} }
Function {do_revert_changes_unconditional()} {return_type int
} {
code {strncpy(loading_next, last_loaded, XMZ_PATH_MAX);
osc->write("/load_xmz", "s", last_loaded);
osc->write("/last_xmz");
refresh_master_ui();
updatepanel();

return 1;} {}
}
Function {do_revert_changes()} {} {
code {if (last_loaded[0] == 0)
do_new_master();
else
if (fl_choice("Revert *ALL* the parameters ?","No","Yes",NULL)){
do_revert_changes_unconditional();
}} {}
}
Function {do_load_master_unconditional(const char *filename, const char *display_name)} {return_type int Function {do_load_master_unconditional(const char *filename, const char *display_name)} {return_type int
} { } {
code {osc->write("/load_xmz", "s", filename);
code {strncpy(loading_next, filename, XMZ_PATH_MAX);
osc->write("/load_xmz", "s", filename);
osc->write("/last_xmz");
refresh_master_ui(); refresh_master_ui();
updatepanel(); updatepanel();


@@ -1648,6 +1705,8 @@ simpleinseffnocounter->do_callback();


simplerefresh(); simplerefresh();
bankui->hide();} {} bankui->hide();} {}
}
decl {class Osc_DataModel *last_xmz;} {public local
} }
decl {MicrotonalUI *microtonalui;} {private local decl {MicrotonalUI *microtonalui;} {private local
} }
@@ -1675,6 +1734,10 @@ bankui->hide();} {}
} }
decl {class Fl_Osc_Interface *osc;} {public local decl {class Fl_Osc_Interface *osc;} {public local
} }
decl {char last_loaded[XMZ_PATH_MAX];} {public local
}
decl {char loading_next[XMZ_PATH_MAX];} {public local
}
Function {close()} {open return_type void Function {close()} {open return_type void
} { } {
code {*exitprogram=1;} {} code {*exitprogram=1;} {}


+ 1
- 2
source/native-plugins/zynaddsubfx/UI/MicrotonalUI.fl View File

@@ -51,8 +51,7 @@ class MicrotonalUI {} {
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {microtonaluiwindow->osc = osc;}
code1 {microtonaluiwindow->base = base;}
code0 {microtonaluiwindow->init(osc, base);}
} }
Fl_Group {} { Fl_Group {} {
tooltip {Center where the note's freqs. are turned upside-down} xywh {249 2 155 45} box ENGRAVED_FRAME tooltip {Center where the note's freqs. are turned upside-down} xywh {249 2 155 45} box ENGRAVED_FRAME


+ 9
- 9
source/native-plugins/zynaddsubfx/UI/NioUI.cpp View File

@@ -11,6 +11,7 @@
#include <FL/Fl_Group.H> #include <FL/Fl_Group.H>
#include <FL/Fl_Text_Display.H> #include <FL/Fl_Text_Display.H>
#include "Osc_SimpleListModel.h" #include "Osc_SimpleListModel.h"
#include "Fl_Osc_Pane.H"


using namespace std; using namespace std;


@@ -56,7 +57,7 @@ class Fl_Osc_StrChoice:public Fl_Choice, public Fl_Osc_Widget
cb_data.first = cb; cb_data.first = cb;
cb_data.second = p; cb_data.second = p;
} }
void cb(void) void cb(void)
{ {
assert(osc); assert(osc);
@@ -66,7 +67,6 @@ class Fl_Osc_StrChoice:public Fl_Choice, public Fl_Osc_Widget
cb_data.first(this, cb_data.second); cb_data.first(this, cb_data.second);
} }
private: private:
int min;
std::pair<Fl_Callback*, void*> cb_data; std::pair<Fl_Callback*, void*> cb_data;
}; };
static void callback_fn_choice_nio(Fl_Widget *w, void *) static void callback_fn_choice_nio(Fl_Widget *w, void *)
@@ -110,9 +110,9 @@ NioUI::NioUI(Fl_Osc_Interface *osc)
for(auto io:list) for(auto io:list)
audio->add(io.c_str()); audio->add(io.c_str());
}; };
midi_opt->update("/io/source-list");
audio_opt->update("/io/sink-list");
midi_opt->doUpdate("/io/source-list");
audio_opt->doUpdate("/io/sink-list");


resizable(this); resizable(this);
size_range(400, 300); size_range(400, 300);
@@ -123,19 +123,19 @@ NioUI::~NioUI()


void NioUI::refresh() void NioUI::refresh()
{ {
midi_opt->update("/io/source-list");
audio_opt->update("/io/sink-list");
midi_opt->doUpdate("/io/source-list");
audio_opt->doUpdate("/io/sink-list");
midi->update(); midi->update();
audio->update(); audio->update();
} }


void NioUI::midiCallback(Fl_Widget *c)
void NioUI::midiCallback(Fl_Widget *)
{ {
//bool good = Nio::setSource(static_cast<Fl_Choice *>(c)->text()); //bool good = Nio::setSource(static_cast<Fl_Choice *>(c)->text());
//static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255 * !good, 0, 0)); //static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255 * !good, 0, 0));
} }


void NioUI::audioCallback(Fl_Widget *c)
void NioUI::audioCallback(Fl_Widget *)
{ {
//bool good = Nio::setSink(static_cast<Fl_Choice *>(c)->text()); //bool good = Nio::setSink(static_cast<Fl_Choice *>(c)->text());
//static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255 * !good, 0, 0)); //static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255 * !good, 0, 0));


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/Osc_DataModel.h View File

@@ -17,7 +17,7 @@ class Osc_DataModel:public Fl_Osc_Widget
value_t value; value_t value;
std::function<void(value_t)> callback; std::function<void(value_t)> callback;


void update(std::string url)
void doUpdate(std::string url)
{ {
if(!ext.empty()) if(!ext.empty())
osc->removeLink(this); osc->removeLink(this);
@@ -26,7 +26,7 @@ class Osc_DataModel:public Fl_Osc_Widget


oscRegister(ext.c_str()); oscRegister(ext.c_str());
} }
//Raw messages //Raw messages
virtual void OSC_raw(const char *msg) virtual void OSC_raw(const char *msg)
{ {


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/Osc_IntModel.h View File

@@ -23,7 +23,7 @@ class Osc_IntModel:public Fl_Osc_Widget
oscWrite(ext, "i", v); oscWrite(ext, "i", v);
} }


void update(std::string url)
void doUpdate(std::string url)
{ {
if(!ext.empty()) if(!ext.empty())
osc->removeLink(this); osc->removeLink(this);
@@ -31,7 +31,7 @@ class Osc_IntModel:public Fl_Osc_Widget


oscRegister(ext.c_str()); oscRegister(ext.c_str());
} }
//Raw messages //Raw messages
virtual void OSC_raw(const char *msg) virtual void OSC_raw(const char *msg)
{ {


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/Osc_ListModel.h View File

@@ -18,7 +18,7 @@ class Osc_ListModel:public Fl_Osc_Widget
std::function<void(list_t)> callback; std::function<void(list_t)> callback;
unsigned list_size; unsigned list_size;


void update(std::string url)
void doUpdate(std::string url)
{ {
if(!ext.empty()) if(!ext.empty())
osc->removeLink(this); osc->removeLink(this);
@@ -26,7 +26,7 @@ class Osc_ListModel:public Fl_Osc_Widget


oscRegister(ext.c_str()); oscRegister(ext.c_str());
} }
//Raw messages //Raw messages
virtual void OSC_raw(const char *msg) virtual void OSC_raw(const char *msg)
{ {


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/Osc_SimpleListModel.h View File

@@ -18,7 +18,7 @@ class Osc_SimpleListModel:public Fl_Osc_Widget
std::function<void(list_t)> callback; std::function<void(list_t)> callback;
unsigned list_size; unsigned list_size;


void update(std::string url)
void doUpdate(std::string url)
{ {
if(!ext.empty()) if(!ext.empty())
osc->removeLink(this); osc->removeLink(this);
@@ -47,7 +47,7 @@ class Osc_SimpleListModel:public Fl_Osc_Widget
rtosc_amessage(buffer, sizeof(buffer), ext.c_str(), types, args); rtosc_amessage(buffer, sizeof(buffer), ext.c_str(), types, args);
osc->writeRaw(buffer); osc->writeRaw(buffer);
} }
//Raw messages //Raw messages
virtual void OSC_raw(const char *msg) virtual void OSC_raw(const char *msg)
{ {


+ 10
- 10
source/native-plugins/zynaddsubfx/UI/OscilGenUI.fl View File

@@ -346,7 +346,7 @@ oscildisplaygroup->redraw();}
code1 {oscilo_base->parent(o);oscilo_base->init(true);} code1 {oscilo_base->parent(o);oscilo_base->init(true);}
} {} } {}
Fl_Dial bfslider { Fl_Dial bfslider {
callback {redrawoscil();}
callback {redrawoscil(); bfparval->value(o->value());}
tooltip {Base Function Parameter} xywh {525 285 20 20} minimum -64 maximum 63 step 1 tooltip {Base Function Parameter} xywh {525 285 20 20} minimum -64 maximum 63 step 1
code0 {o->init("Pbasefuncpar");} code0 {o->init("Pbasefuncpar");}
class Fl_Osc_Dial class Fl_Osc_Dial
@@ -492,9 +492,9 @@ redrawoscil();}
} }
Fl_Button {} { Fl_Button {} {
label {Use as base} label {Use as base}
callback {//oscil->useasbase();
callback {osc->requestValue(loc+"use-as-base");
if (autoclearbutton->value()){ if (autoclearbutton->value()){
for (int i=0;i<MAX_AD_HARMONICS;i++){
for (int i=0;i<(MAX_AD_HARMONICS - 1);i++){
h[i]->mag->value(64); h[i]->mag->value(64);
h[i]->mag->do_callback(); h[i]->mag->do_callback();
h[i]->phase->value(64); h[i]->phase->value(64);
@@ -528,7 +528,7 @@ redrawoscil();}
label Clear label Clear
callback {if (!fl_choice("Clear the harmonics settings?","No","Yes",NULL)) return; callback {if (!fl_choice("Clear the harmonics settings?","No","Yes",NULL)) return;


for (int i=0;i<MAX_AD_HARMONICS;i++){
for (int i=0;i<(MAX_AD_HARMONICS - 1);i++){
h[i]->mag->value(64); h[i]->mag->value(64);
h[i]->mag->do_callback(); h[i]->mag->do_callback();
h[i]->phase->value(64); h[i]->phase->value(64);
@@ -537,7 +537,7 @@ for (int i=0;i<MAX_AD_HARMONICS;i++){
h[0]->mag->value(0); h[0]->mag->value(0);
h[0]->mag->do_callback(); h[0]->mag->do_callback();


//for (int i=0;i<MAX_AD_HARMONICS;i++){
//for (int i=0;i<(MAX_AD_HARMONICS - 1);i++){
// if (oscil->Phmag[i]==64) h[i]->mag->selection_color(0); // if (oscil->Phmag[i]==64) h[i]->mag->selection_color(0);
// else h[i]->mag->selection_color(222); // else h[i]->mag->selection_color(222);
//}; //};
@@ -620,7 +620,7 @@ redrawoscil();}
} }
} }
Fl_Dial wshpar { Fl_Dial wshpar {
callback {redrawoscil();}
callback {redrawoscil(); wsparval->value(o->value());}
tooltip {Waveshaping Parameter} xywh {265 318 20 20} minimum -64 maximum 63 step 1 tooltip {Waveshaping Parameter} xywh {265 318 20 20} minimum -64 maximum 63 step 1
code0 {o->init("Pwaveshaping");} code0 {o->init("Pwaveshaping");}
class Fl_Osc_Dial class Fl_Osc_Dial
@@ -916,7 +916,7 @@ refresh();}
} { } {
Fl_Pack harmonics {open Fl_Pack harmonics {open
xywh {15 350 650 225} type HORIZONTAL xywh {15 350 650 225} type HORIZONTAL
code0 {for (int i=0;i<MAX_AD_HARMONICS;i++){h[i]=new Oscilharmonic(0,0,20,o->h(),"");h[i]->init(i,oscildisplaygroup,loc,osc);}}
code0 {for (int i=0;i<(MAX_AD_HARMONICS - 1);i++){h[i]=new Oscilharmonic(0,0,20,o->h(),"");h[i]->init(i,oscildisplaygroup,loc,osc);}}
} {} } {}
} }
} }
@@ -958,7 +958,7 @@ osceditUI->show();} {}
Function {~OscilEditor()} {open Function {~OscilEditor()} {open
} { } {
code {osceditUI->hide(); code {osceditUI->hide();
for (int i=0; i<MAX_AD_HARMONICS; ++i)
for (int i=0; i<(MAX_AD_HARMONICS - 1); ++i)
delete h[i]; delete h[i];


delete oscilo; delete oscilo;
@@ -970,7 +970,7 @@ delete osceditUI;} {}
Function {refresh()} {} { Function {refresh()} {} {
code {magtype->update(); code {magtype->update();


for (int i=0;i<MAX_AD_HARMONICS;i++) h[i]->refresh();
for (int i=0;i<(MAX_AD_HARMONICS - 1);i++) h[i]->refresh();


osc->requestValue(loc+"prepare"); osc->requestValue(loc+"prepare");


@@ -989,7 +989,7 @@ oscils->update();
oscilo_base->update(); oscilo_base->update();
oscils_base->update();} {} oscils_base->update();} {}
} }
decl {Oscilharmonic *h[MAX_AD_HARMONICS];} {private local
decl {Oscilharmonic *h[(MAX_AD_HARMONICS - 1)];} {private local
} }
decl {std::string loc;} {private local decl {std::string loc;} {private local
} }


+ 1
- 2
source/native-plugins/zynaddsubfx/UI/PADnoteUI.fl View File

@@ -84,8 +84,7 @@ initialized = true;} {selected
} { } {


Fl_Box dummy { Fl_Box dummy {
code0 {padnotewindow->osc = osc_i; padnotewindow->base = location;}
code1 {puts("dummy setup done...");}
code0 {padnotewindow->init(osc_i, location);}
} }
Fl_Tabs {} { Fl_Tabs {} {
callback {if (o->value()!=harmonicstructuregroup) applybutton->hide(); callback {if (o->value()!=harmonicstructuregroup) applybutton->hide();


+ 7
- 11
source/native-plugins/zynaddsubfx/UI/PartUI.fl View File

@@ -418,8 +418,7 @@ if (event==FL_RIGHT_MOUSE){
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {ctlwindow->osc = osc;}
code1 {ctlwindow->base = "/part"+to_s(npart)+"/ctl/";}
code0 {ctlwindow->init(osc,"/part"+to_s(npart)+"/ctl/");}
} }
Fl_Check_Button {} { Fl_Check_Button {} {
label Expr label Expr
@@ -610,8 +609,7 @@ else {propta->deactivate();proptb->deactivate();}}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {partfx->osc = osc;}
code1 {partfx->base = part_path;}
code0 {partfx->init(osc, part_path);}
} }
Fl_Counter inseffnocounter { Fl_Counter inseffnocounter {
label {FX No.} label {FX No.}
@@ -726,12 +724,12 @@ if (x==2) part->partefx[ninseff]->setdryonly(true);
} }
Fl_Button {} { Fl_Button {} {
label C label C
callback {presetsui->copy(partfx->loc());}
callback {presetsui->copy(partfx->loc()+"partefx"+to_s(ninseff)+"/");}
xywh {90 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 55 xywh {90 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 55
} }
Fl_Button {} { Fl_Button {} {
label P label P
callback {presetsui->paste(partfx->loc(),inseffectui);}
callback {presetsui->paste(partfx->loc()+"partefx"+to_s(ninseff)+"/",inseffectui);}
xywh {120 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 55 xywh {120 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 55
} }
} }
@@ -742,8 +740,7 @@ if (x==2) part->partefx[ninseff]->setdryonly(true);
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {instrumentkitlist->osc = osc;}
code1 {instrumentkitlist->base = "/part"+to_s(npart)+"/";}
code0 {instrumentkitlist->init(osc, "/part"+to_s(npart)+"/");}
} }
Fl_Button {} { Fl_Button {} {
label {Close Window} label {Close Window}
@@ -824,8 +821,7 @@ if (x==2) part->partefx[ninseff]->setdryonly(true);
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} xywh {0 0 0 0}
code0 {instrumenteditwindow->osc = osc;}
code1 {instrumenteditwindow->base = "/part"+to_s(npart)+"/";}
code0 {instrumenteditwindow->init(osc, "/part"+to_s(npart)+"/");}
} }
Fl_Group editgroup { Fl_Group editgroup {
xywh {0 220 395 110} box UP_FRAME xywh {0 220 395 110} box UP_FRAME
@@ -1093,7 +1089,7 @@ delete(instrumenteditwindow);} {}
} }
decl {BankUI *bankui;} {private local decl {BankUI *bankui;} {private local
} }
decl {ADnoteUI *adnoteui;} {private local
decl {ADnoteUI *adnoteui;} {selected public local
} }
decl {SUBnoteUI *subnoteui;} {private local decl {SUBnoteUI *subnoteui;} {private local
} }


+ 2
- 2
source/native-plugins/zynaddsubfx/UI/PresetsUI.fl View File

@@ -60,7 +60,7 @@ class PresetsUI {} {
printf("Value = %s\\n", val.c_str()); printf("Value = %s\\n", val.c_str());
copytypetext->label(val.c_str()); copytypetext->label(val.c_str());
pastetypetext->label(val.c_str()); pastetypetext->label(val.c_str());
listmodel.update("/presets/scan-for-presets");
listmodel.doUpdate("/presets/scan-for-presets");
}; };
} {} } {}
@@ -268,7 +268,7 @@ class PresetsUI {} {
pastebrowse->clear(); pastebrowse->clear();


printf("Datamodel Update..."); printf("Datamodel Update...");
datamodel.update(url+"preset-type");
datamodel.doUpdate(url+"preset-type");
} {} } {}
} }
decl {std::string url;} {public local decl {std::string url;} {public local


+ 1
- 1
source/native-plugins/zynaddsubfx/UI/SUBnoteUI.fl View File

@@ -184,7 +184,7 @@ class SUBnoteUI {open : {public PresetsUI_}
} { } {
Fl_Box {} { Fl_Box {} {
xywh {0 0 0 0} box FLAT_BOX color 45 xywh {0 0 0 0} box FLAT_BOX color 45
code0 {SUBparameters->osc = osc; SUBparameters->base = loc;}
code0 {SUBparameters->init(osc, loc);}
} }
Fl_Scroll {} { Fl_Scroll {} {
label scroll open label scroll open


+ 75
- 0
source/native-plugins/zynaddsubfx/UI/TipWin.cpp View File

@@ -0,0 +1,75 @@
#include <cstdio>
#include <cmath>
#include <FL/Fl_Tooltip.H>
#include <FL/fl_draw.H>
#include "TipWin.h"

TipWin::TipWin(void):Fl_Menu_Window(1, 1)
{
strcpy(format, "%0.2f");
set_override();
end();
}

void TipWin::setRounding(unsigned int digits)
{
format[3] = "0123456789"[digits < 9 ? digits : 9];
}

void TipWin::draw()
{
//setup window
draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Color(175));
fl_color(Fl_Tooltip::textcolor());
fl_font(labelfont(), labelsize());

//Draw the current string
fl_draw(getStr(), 3, 3, w() - 6, h() - 6,
Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_WRAP));
}

void TipWin::showValue(float f)
{
//convert the value to a string
char tmp[10];
snprintf(tmp, 9, format, f);
tip = tmp;

textmode = false;
redraw();
show();
}

void TipWin::setText(const char *c)
{
text = c;
textmode = true;
redraw();
}

void TipWin::showText()
{
if(!text.empty()) {
textmode = true;
redraw();
show();
}
}

void TipWin::redraw()
{
// Recalc size of window
fl_font(labelfont(), labelsize());
int W = 0, H = 0;
fl_measure(getStr(), W, H, 0);
//provide a bit of extra space
W += 8;
H += 4;
size(W, H);
Fl_Menu_Window::redraw();
}

const char *TipWin::getStr() const
{
return (textmode ? text : tip).c_str();
}

+ 25
- 0
source/native-plugins/zynaddsubfx/UI/TipWin.h View File

@@ -0,0 +1,25 @@
#ifndef TIPWIN_H
#include <string>
#include <FL/Fl_Menu_Window.H>
#include <FL/Fl_Tooltip.H>
#define TIPWIN_H
using namespace std;

class TipWin:public Fl_Menu_Window
{
public:
TipWin();
void draw();
void showValue(float f);
void setText(const char *c);
void showText();
void setRounding(unsigned int digits = 0);
private:
void redraw();
const char *getStr() const;
string tip;
string text;
bool textmode;
char format[6];
};
#endif

+ 71
- 108
source/native-plugins/zynaddsubfx/UI/WidgetPDial.cpp View File

@@ -1,104 +1,19 @@
// generated by Fast Light User Interface Designer (fluid) version 1.0107f // generated by Fast Light User Interface Designer (fluid) version 1.0107f


#include "WidgetPDial.h"
#include <cstdio>
#include <iostream>
#include <cmath> #include <cmath>
#include <string>
#include <FL/Fl_Tooltip.H>
#include <FL/fl_draw.H> #include <FL/fl_draw.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Menu_Window.H>
#include "../Misc/Util.h" #include "../Misc/Util.h"
#include "WidgetPDial.h"
//Copyright (c) 2003-2005 Nasca Octavian Paul //Copyright (c) 2003-2005 Nasca Octavian Paul
//License: GNU GPL version 2 or later //License: GNU GPL version 2 or later


using namespace std;

class TipWin:public Fl_Menu_Window
{
public:
TipWin();
void draw();
void showValue(float f);
void setText(const char *c);
void showText();
private:
void redraw();
const char *getStr() const;
string tip;
string text;
bool textmode;
};

TipWin::TipWin():Fl_Menu_Window(1, 1)
{
set_override();
end();
}

void TipWin::draw()
{
//setup window
draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Color(175));
fl_color(Fl_Tooltip::textcolor());
fl_font(labelfont(), labelsize());

//Draw the current string
fl_draw(getStr(), 3, 3, w() - 6, h() - 6,
Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_WRAP));
}

void TipWin::showValue(float f)
{
//convert the value to a string
char tmp[10];
snprintf(tmp, 9, "%.2f", f);
tip = tmp;

textmode = false;
redraw();
show();
}

void TipWin::setText(const char *c)
{
text = c;
textmode = true;
redraw();
}

void TipWin::showText()
{
if(!text.empty()) {
textmode = true;
redraw();
show();
}
}

void TipWin::redraw()
{
// Recalc size of window
fl_font(labelfont(), labelsize());
int W = 0, H = 0;
fl_measure(getStr(), W, H, 0);
//provide a bit of extra space
W += 8;
H += 4;
size(W, H);
Fl_Menu_Window::redraw();
}

const char *TipWin::getStr() const
{
return (textmode ? text : tip).c_str();
}


//static int numobj = 0; //static int numobj = 0;


WidgetPDial::WidgetPDial(int x, int y, int w, int h, const char *label) WidgetPDial::WidgetPDial(int x, int y, int w, int h, const char *label)
:Fl_Dial(x, y, w, h, label), oldvalue(0.0f), pos(false), textset(false)
:Fl_Dial(x, y, w, h, label), reset_value(0), integer_step(true),
oldvalue(0.0f), pos(false), textset(false), value_offset(0.0),
value_scale(1.0)
{ {
//cout << "[" << label << "] There are now " << ++numobj << endl; //cout << "[" << label << "] There are now " << ++numobj << endl;
Fl_Group *save = Fl_Group::current(); Fl_Group *save = Fl_Group::current();
@@ -113,27 +28,46 @@ WidgetPDial::~WidgetPDial()
delete tipwin; delete tipwin;
} }


void WidgetPDial::setRounding(unsigned int digits)
{
tipwin->setRounding(digits);
}

int WidgetPDial::handle(int event) int WidgetPDial::handle(int event)
{ {
//#ifdef NTK_GUI
// return Fl_Dial::handle( event );
//#else
double dragsize, min = minimum(), max = maximum();
int my;
double dragsize, min = minimum(), max = maximum(), result;
int dy;


if (event == FL_RELEASE && Fl::event_clicks() == 1) {
Fl::event_clicks(0);
value(reset_value);
value_damage();
if (this->when() != 0)
do_callback();
return 1;
}
switch(event) { switch(event) {
case FL_PUSH: case FL_PUSH:
if (integer_step)
setRounding(0);
else if (Fl::event_shift())
setRounding(4);
else
setRounding(Fl::event_button1() ? 2 : 3);
oldvalue = value(); oldvalue = value();
old_y = Fl::event_y();
case FL_DRAG: case FL_DRAG:
getPos(); getPos();
my = -(Fl::event_y() - y() - h() / 2);
dy = old_y - Fl::event_y();


dragsize = 200.0f;
if(Fl::event_state(FL_BUTTON1) == 0)
dragsize *= 10;
if (Fl::event_shift())
dragsize = 20000.0f;
else
dragsize = Fl::event_button1() ? 200.0f : 2000.0f;


value(limit(oldvalue + my / dragsize * (max - min), min, max));
tipwin->showValue(value());
value(clamp(oldvalue + dy / dragsize * (max - min)));
tipwin->showValue(transform(value()));
value_damage(); value_damage();
if(this->when() != 0) if(this->when() != 0)
do_callback(); do_callback();
@@ -141,14 +75,28 @@ int WidgetPDial::handle(int event)
case FL_MOUSEWHEEL: case FL_MOUSEWHEEL:
if (Fl::belowmouse() != this) if (Fl::belowmouse() != this)
return 1; return 1;
my = - Fl::event_dy();

dragsize = 200.0f;
if(Fl::event_state(FL_CTRL) != 0)
dragsize *= 10;

value(limit(value() + my / dragsize * (max - min), min, max));
tipwin->showValue(value());
dy = - Fl::event_dy();

if (integer_step) {
setRounding(0);
result = (int)(value() + dy * (Fl::event_ctrl() ? 1 : 8));
} else {
float dragsize;
if (Fl::event_shift()) {
dragsize = 10000.0;
setRounding(4);
} else if (Fl::event_ctrl()) {
dragsize = 1000.0;
setRounding(3);
} else {
dragsize = 100.0;
setRounding(2);
}
result = value() + dy / dragsize * (max - min);
}
value(clamp(result));

tipwin->showValue(transform(value()));
value_damage(); value_damage();
if(this->when() != 0) if(this->when() != 0)
do_callback(); do_callback();
@@ -163,6 +111,10 @@ int WidgetPDial::handle(int event)
resetPos(); resetPos();
break; break;
case FL_RELEASE: case FL_RELEASE:
if (integer_step) {
int rounded = value() + 0.5;
value(clamp(rounded));
}
tipwin->hide(); tipwin->hide();
resetPos(); resetPos();
if(this->when() == 0) if(this->when() == 0)
@@ -262,3 +214,14 @@ void WidgetPDial::resetPos()
{ {
pos = false; pos = false;
} }

void WidgetPDial::set_transform(float scale, float offset)
{
value_offset = offset;
value_scale = scale;
}

float WidgetPDial::transform(float x)
{
return value_scale * x + value_offset;
}

+ 10
- 0
source/native-plugins/zynaddsubfx/UI/WidgetPDial.h View File

@@ -3,6 +3,7 @@
#ifndef WIDGETPDIAL_h #ifndef WIDGETPDIAL_h
#define WIDGETPDIAL_h #define WIDGETPDIAL_h
#include <FL/Fl_Dial.H> #include <FL/Fl_Dial.H>
#include "TipWin.h"




class WidgetPDial:public Fl_Dial class WidgetPDial:public Fl_Dial
@@ -14,12 +15,21 @@ class WidgetPDial:public Fl_Dial
void draw(); void draw();
void pdialcolor(int r, int g, int b); void pdialcolor(int r, int g, int b);
void tooltip(const char *c); void tooltip(const char *c);
void set_transform(float scale = 1.0, float offset = 0.0);
float transform(float x);
void setRounding(unsigned int digits = 0);
float reset_value;
protected:
bool integer_step;
private: private:
void getPos(); void getPos();
void resetPos(); void resetPos();
double oldvalue; double oldvalue;
int old_y;
bool pos; bool pos;
bool textset; bool textset;
class TipWin * tipwin; class TipWin * tipwin;
float value_offset;
float value_scale;
}; };
#endif #endif

+ 1
- 0
source/native-plugins/zynaddsubfx/UI/guimain.cpp View File

@@ -541,6 +541,7 @@ int main(int argc, char *argv[])
lo_server_add_method(server, NULL, NULL, handler_function, 0); lo_server_add_method(server, NULL, NULL, handler_function, 0);
sendtourl = argv[1]; sendtourl = argv[1];
} }
fprintf(stderr, "ext client running on %d\n", lo_server_get_port(server));
gui = GUI::createUi(new UI_Interface(), &Pexitprogram); gui = GUI::createUi(new UI_Interface(), &Pexitprogram);




+ 5
- 2
source/native-plugins/zynaddsubfx/globals.cpp View File

@@ -24,7 +24,7 @@
#include "Misc/Util.h" #include "Misc/Util.h"
#include "globals.h" #include "globals.h"


void SYNTH_T::alias()
void SYNTH_T::alias(bool randomize)
{ {
halfsamplerate_f = (samplerate_f = samplerate) / 2.0f; halfsamplerate_f = (samplerate_f = samplerate) / 2.0f;
buffersize_f = buffersize; buffersize_f = buffersize;
@@ -36,5 +36,8 @@ void SYNTH_T::alias()
// for deleting the buffers and also call it in the dtor // for deleting the buffers and also call it in the dtor
denormalkillbuf.resize(buffersize); denormalkillbuf.resize(buffersize);
for(int i = 0; i < buffersize; ++i) for(int i = 0; i < buffersize; ++i)
denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
if(randomize)
denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
else
denormalkillbuf[i] = 0;
} }

+ 14
- 4
source/native-plugins/zynaddsubfx/globals.h View File

@@ -43,6 +43,8 @@ class PADnoteParameters;
class SynthNote; class SynthNote;


class Allocator; class Allocator;
class AbsTime;
class RelTime;


class Microtonal; class Microtonal;
class XMLwrapper; class XMLwrapper;
@@ -142,6 +144,14 @@ typedef std::complex<fftw_real> fft_t;
*/ */
#define PART_MAX_NAME_LEN 30 #define PART_MAX_NAME_LEN 30


/*
* The maximum we allow for an XMZ path
*
* Note that this is an ugly hack. Finding a compile time path
* max portably is painful.
*/
#define XMZ_PATH_MAX 1024

/* /*
* The maximum number of bands of the equaliser * The maximum number of bands of the equaliser
*/ */
@@ -270,8 +280,8 @@ public:


operator T*() { return ptr; } operator T*() { return ptr; }
operator const T*() const { return ptr; } operator const T*() const { return ptr; }
T& operator[](unsigned idx) { return ptr[idx]; }
const T& operator[](unsigned idx) const { return ptr[idx]; }
//T& operator[](unsigned idx) { return ptr[idx]; }
//const T& operator[](unsigned idx) const { return ptr[idx]; }
}; };


//temporary include for synth->{samplerate/buffersize} members //temporary include for synth->{samplerate/buffersize} members
@@ -280,7 +290,7 @@ struct SYNTH_T {
SYNTH_T(void) SYNTH_T(void)
:samplerate(44100), buffersize(256), oscilsize(1024) :samplerate(44100), buffersize(256), oscilsize(1024)
{ {
alias();
alias(false);
} }


SYNTH_T(const SYNTH_T& ) = delete; SYNTH_T(const SYNTH_T& ) = delete;
@@ -320,7 +330,7 @@ struct SYNTH_T {
{ {
return buffersize_f / samplerate_f; return buffersize_f / samplerate_f;
} }
void alias(void);
void alias(bool randomize=true);
static float numRandom(void); //defined in Util.cpp for now static float numRandom(void); //defined in Util.cpp for now
}; };
#endif #endif

+ 25
- 4
source/native-plugins/zynaddsubfx/main.cpp View File

@@ -138,7 +138,7 @@ int main(int argc, char *argv[])
<< " Copyright (c) 2009-2014 Mark McCurry [active maintainer]" << " Copyright (c) 2009-2014 Mark McCurry [active maintainer]"
<< endl; << endl;
cerr << "Compiled: " << __DATE__ << " " << __TIME__ << endl; cerr << "Compiled: " << __DATE__ << " " << __TIME__ << endl;
cerr << "This program is free software (GNU GPL v.2 or later) and \n";
cerr << "This program is free software (GNU GPL v2 or later) and \n";
cerr << "it comes with ABSOLUTELY NO WARRANTY.\n" << endl; cerr << "it comes with ABSOLUTELY NO WARRANTY.\n" << endl;
if(argc == 1) if(argc == 1)
cerr << "Try 'zynaddsubfx --help' for command-line options." << endl; cerr << "Try 'zynaddsubfx --help' for command-line options." << endl;
@@ -211,6 +211,9 @@ int main(int argc, char *argv[])
{ {
"dump-oscdoc", 2, NULL, 'd' "dump-oscdoc", 2, NULL, 'd'
}, },
{
"ui-title", 1, NULL, 'u'
},
{ {
0, 0, 0, 0 0, 0, 0, 0
} }
@@ -219,7 +222,7 @@ int main(int argc, char *argv[])
int option_index = 0, opt, exitwithhelp = 0, exitwithversion = 0; int option_index = 0, opt, exitwithhelp = 0, exitwithversion = 0;
int prefered_port = -1; int prefered_port = -1;


string loadfile, loadinstrument, execAfterInit;
string loadfile, loadinstrument, execAfterInit, ui_title;


while(1) { while(1) {
int tmp = 0; int tmp = 0;
@@ -227,7 +230,7 @@ int main(int argc, char *argv[])
/**\todo check this process for a small memory leak*/ /**\todo check this process for a small memory leak*/
opt = getopt_long(argc, opt = getopt_long(argc,
argv, argv,
"l:L:r:b:o:I:O:N:e:P:hvapSDUY",
"l:L:r:b:o:I:O:N:e:P:u:hvapSDUY",
opts, opts,
&option_index); &option_index);
char *optarguments = optarg; char *optarguments = optarg;
@@ -335,6 +338,10 @@ int main(int argc, char *argv[])
outfile << s; outfile << s;
} }
break; break;
case 'u':
if(optarguments)
ui_title = optarguments;
break;
case '?': case '?':
cerr << "ERROR:Bad option or parameter.\n" << endl; cerr << "ERROR:Bad option or parameter.\n" << endl;
exitwithhelp = 1; exitwithhelp = 1;
@@ -370,6 +377,7 @@ int main(int argc, char *argv[])
<< " -I , --input\t\t\t\t Set Input Engine\n" << " -I , --input\t\t\t\t Set Input Engine\n"
<< " -e , --exec-after-init\t\t Run post-initialization script\n" << " -e , --exec-after-init\t\t Run post-initialization script\n"
<< " -d , --dump-oscdoc=FILE\t\t Dump oscdoc xml to file\n" << " -d , --dump-oscdoc=FILE\t\t Dump oscdoc xml to file\n"
<< " -u , --ui-title=TITLE\t\t Extend UI Window Titles\n"
<< endl; << endl;


return 0; return 0;
@@ -384,20 +392,26 @@ int main(int argc, char *argv[])


initprogram(std::move(synth), &config, prefered_port); initprogram(std::move(synth), &config, prefered_port);


bool altered_master = false;
if(!loadfile.empty()) { if(!loadfile.empty()) {
int tmp = master->loadXML(loadfile.c_str());
altered_master = true;
const char *filename = loadfile.c_str();
int tmp = master->loadXML(filename);
if(tmp < 0) { if(tmp < 0) {
cerr << "ERROR: Could not load master file " << loadfile cerr << "ERROR: Could not load master file " << loadfile
<< "." << endl; << "." << endl;
exit(1); exit(1);
} }
else { else {
strncpy(master->last_xmz, filename, XMZ_PATH_MAX);
master->last_xmz[XMZ_PATH_MAX-1] = 0;
master->applyparameters(); master->applyparameters();
cout << "Master file loaded." << endl; cout << "Master file loaded." << endl;
} }
} }


if(!loadinstrument.empty()) { if(!loadinstrument.empty()) {
altered_master = true;
int loadtopart = 0; int loadtopart = 0;
int tmp = master->part[loadtopart]->loadXMLinstrument( int tmp = master->part[loadtopart]->loadXMLinstrument(
loadinstrument.c_str()); loadinstrument.c_str());
@@ -413,6 +427,9 @@ int main(int argc, char *argv[])
} }
} }


if(altered_master)
middleware->updateResources(master);

//Run the Nio system //Run the Nio system
bool ioGood = Nio::start(); bool ioGood = Nio::start();


@@ -447,6 +464,10 @@ int main(int argc, char *argv[])
delete [] msg; delete [] msg;
} }


//set titles
if(!ui_title.empty())
GUI::raiseUi(gui, "/ui/title", "s", ui_title.c_str());

if(!noui) if(!noui)
{ {
GUI::raiseUi(gui, "/show", "i", config.cfg.UserInterfaceMode); GUI::raiseUi(gui, "/show", "i", config.cfg.UserInterfaceMode);


+ 2
- 2
source/native-plugins/zynaddsubfx/rtosc/cpp/midimapper.cpp View File

@@ -1,5 +1,5 @@


#include "ports.h"
#include <rtosc/ports.h>
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
#include <map> #include <map>
@@ -8,7 +8,7 @@
#include <utility> #include <utility>


#include <cassert> #include <cassert>
#include "miditable.h"
#include <rtosc/miditable.h>


using namespace rtosc; using namespace rtosc;
using std::string; using std::string;


+ 1
- 1
source/native-plugins/zynaddsubfx/rtosc/cpp/miditable.cpp View File

@@ -1,5 +1,5 @@
#include <math.h> #include <math.h>
#include "miditable.h"
#include <rtosc/miditable.h>


using namespace rtosc; using namespace rtosc;




+ 184
- 57
source/native-plugins/zynaddsubfx/rtosc/cpp/ports.cpp View File

@@ -1,4 +1,4 @@
#include "ports.h"
#include "../ports.h"
#include <ostream> #include <ostream>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
@@ -255,15 +255,15 @@ bool has(T &t, Z&z)
return false; return false;
} }


int rtosc_max(int a, int b) { return a<b?b:a;}
static int int_max(int a, int b) { return a<b?b:a;}


ivec_t find_pos(words_t &strs)
static ivec_t find_pos(words_t &strs)
{ {
ivec_t pos; ivec_t pos;
int current_dups = strs.size(); int current_dups = strs.size();
int N = 0; int N = 0;
for(auto w:strs) for(auto w:strs)
N = rtosc_max(N,w.length());
N = int_max(N,w.length());


int pos_best = -1; int pos_best = -1;
int pos_best_val = INT_MAX; int pos_best_val = INT_MAX;
@@ -294,7 +294,7 @@ ivec_t find_pos(words_t &strs)
return pos; return pos;
} }


ivec_t do_hash(const words_t &strs, const ivec_t &pos, const ivec_t &assoc)
static ivec_t do_hash(const words_t &strs, const ivec_t &pos, const ivec_t &assoc)
{ {
ivec_t ivec; ivec_t ivec;
ivec.reserve(strs.size()); ivec.reserve(strs.size());
@@ -308,7 +308,7 @@ ivec_t do_hash(const words_t &strs, const ivec_t &pos, const ivec_t &assoc)
return ivec; return ivec;
} }


ivec_t find_assoc(const words_t &strs, const ivec_t &pos)
static ivec_t find_assoc(const words_t &strs, const ivec_t &pos)
{ {
ivec_t assoc; ivec_t assoc;
int current_dups = strs.size(); int current_dups = strs.size();
@@ -354,7 +354,7 @@ ivec_t find_assoc(const words_t &strs, const ivec_t &pos)
return assoc; return assoc;
} }


ivec_t find_remap(words_t &strs, ivec_t &pos, ivec_t &assoc)
static ivec_t find_remap(words_t &strs, ivec_t &pos, ivec_t &assoc)
{ {
ivec_t remap; ivec_t remap;
auto hashed = do_hash(strs, pos, assoc); auto hashed = do_hash(strs, pos, assoc);
@@ -362,7 +362,7 @@ ivec_t find_remap(words_t &strs, ivec_t &pos, ivec_t &assoc)
// printf("%d) '%s'\n", hashed[i], strs[i].c_str()); // printf("%d) '%s'\n", hashed[i], strs[i].c_str());
int N = 0; int N = 0;
for(auto h:hashed) for(auto h:hashed)
N = rtosc_max(N,h+1);
N = int_max(N,h+1);
for(int i=0; i<N; ++i) for(int i=0; i<N; ++i)
remap.push_back(0); remap.push_back(0);
for(int i=0; i<(int)hashed.size(); ++i) for(int i=0; i<(int)hashed.size(); ++i)
@@ -371,7 +371,7 @@ ivec_t find_remap(words_t &strs, ivec_t &pos, ivec_t &assoc)
return remap; return remap;
} }


void generate_minimal_hash(std::vector<std::string> str, Port_Matcher &pm)
static void generate_minimal_hash(std::vector<std::string> str, Port_Matcher &pm)
{ {
pm.pos = find_pos(str); pm.pos = find_pos(str);
if(pm.pos.empty()) { if(pm.pos.empty()) {
@@ -382,7 +382,7 @@ void generate_minimal_hash(std::vector<std::string> str, Port_Matcher &pm)
pm.remap = find_remap(str, pm.pos, pm.assoc); pm.remap = find_remap(str, pm.pos, pm.assoc);
} }


void generate_minimal_hash(Ports &p, Port_Matcher &pm)
static void generate_minimal_hash(Ports &p, Port_Matcher &pm)
{ {
svec_t keys; svec_t keys;
cvec_t args; cvec_t args;
@@ -575,6 +575,71 @@ const Port *Ports::apropos(const char *path) const
return NULL; return NULL;
} }


static bool parent_path_p(char *read, char *start)
{
if(read-start<2)
return false;
return read[0]=='.' && read[-1]=='.' && read[-2]=='/';
}

static void read_path(char *&r, char *start)
{
while(1)
{
if(r<start)
break;
bool doBreak = *r=='/';
r--;
if(doBreak)
break;
}
}

static void move_path(char *&r, char *&w, char *start)
{
while(1)
{
if(r<start)
break;
bool doBreak = *r=='/';
*w-- = *r--;
if(doBreak)
break;
}
}


char *Ports::collapsePath(char *p)
{
//obtain the pointer to the last non-null char
char *p_end = p;
while(*p_end) p_end++;
p_end--;

//number of subpaths to consume
int consuming = 0;

char *write_pos = p_end;
char *read_pos = p_end;
while(read_pos >= p) {
//per path chunk either
//(1) find a parent ref and inc consuming
//(2) find a normal ref and consume
//(3) find a normal ref and write through
bool ppath = parent_path_p(read_pos, p);
if(ppath) {
read_path(read_pos, p);
consuming++;
} else if(consuming) {
read_path(read_pos, p);
consuming--;
} else
move_path(read_pos, write_pos, p);
}
//return last written location, not next to write
return write_pos+1;
};

void rtosc::walk_ports(const Ports *base, void rtosc::walk_ports(const Ports *base,
char *name_buffer, char *name_buffer,
size_t buffer_size, size_t buffer_size,
@@ -670,7 +735,7 @@ void walk_ports2(const rtosc::Ports *base,


//for(unsigned i=0; i<max; ++i) //for(unsigned i=0; i<max; ++i)
{ {
sprintf(pos,"[0,%d]",max);
sprintf(pos,"[0,%d]",max-1);


//Ensure the result is a path //Ensure the result is a path
if(strrchr(name_buffer, '/')[1] != '/') if(strrchr(name_buffer, '/')[1] != '/')
@@ -697,7 +762,7 @@ void walk_ports2(const rtosc::Ports *base,


//for(unsigned i=0; i<max; ++i) //for(unsigned i=0; i<max; ++i)
{ {
sprintf(pos,"[0,%d]",max);
sprintf(pos,"[0,%d]",max-1);


//Apply walker function //Apply walker function
walker(&p, name_buffer, data); walker(&p, name_buffer, data);
@@ -724,54 +789,110 @@ static void units(std::ostream &o, const char *u)
o << " units=\"" << u << "\""; o << " units=\"" << u << "\"";
} }


using std::ostream;
using std::string;
static ostream &dump_t_f_port(ostream &o, string name, string doc)
{
o << " <message_in pattern=\"" << name << "\" typetag=\"T\">\n";
o << " <desc>Enable " << doc << "</desc>\n";
o << " <param_T symbol=\"x\"/>\n";
o << " </message_in>\n";
o << " <message_in pattern=\"" << name << "\" typetag=\"F\">\n";
o << " <desc>Disable " << doc << "</desc>\n";
o << " <param_F symbol=\"x\"/>\n";
o << " </message_in>\n";
o << " <message_in pattern=\"" << name << "\" typetag=\"\">\n";
o << " <desc>Get state of " << doc << "</desc>\n";
o << " </message_in>\n";
o << " <message_out pattern=\"" << name << "\" typetag=\"T\">\n";
o << " <desc>Value of " << doc << "</desc>\n";
o << " <param_T symbol=\"x\"/>";
o << " </message_out>\n";
o << " <message_out pattern=\"" << name << "\" typetag=\"F\">\n";
o << " <desc>Value of " << doc << "</desc>\n";
o << " <param_F symbol=\"x\"/>";
o << " </message_out>\n";
return o;
}
static ostream &dump_any_port(ostream &o, string name, string doc)
{
o << " <message_in pattern=\"" << name << "\" typetag=\"*\">\n";
o << " <desc>" << doc << "</desc>\n";
o << " </message_in>\n";
return o;
}

static ostream &dump_generic_port(ostream &o, string name, string doc, string type)
{
const char *t = type.c_str();
string arg_names = "xyzabcdefghijklmnopqrstuvw";

//start out with argument separator
if(*t++ != ':')
return o;
//now real arguments (assume [] don't exist)
string args;
while(*t && *t != ':')
args += *t++;

o << " <message_in pattern=\"" << name << "\" typetag=\"" << args << "\">\n";
o << " <desc>" << doc << "</desc>\n";

assert(args.length()<arg_names.length());
for(unsigned i=0; i<args.length(); ++i)
o << " <param_" << args[i] << " symbol=\"" << arg_names[i] << "\"/>\n";
o << " </message_in>\n";

if(*t == ':')
return dump_generic_port(o, name, doc, t);
else
return o;
}

void dump_ports_cb(const rtosc::Port *p, const char *name, void *v) void dump_ports_cb(const rtosc::Port *p, const char *name, void *v)
{ {
std::ostream &o = *(std::ostream*)v;
auto meta = p->meta();
if(meta.find("parameter") != p->meta().end()) {
std::ostream &o = *(std::ostream*)v;
auto meta = p->meta();
const char *args = strchr(p->name, ':');
auto mparameter = meta.find("parameter");
auto mdoc = meta.find("documentation");
string doc;

if(mdoc != p->meta().end())
doc = mdoc.value;
if(meta.find("internal") != meta.end()) {
doc += "[INTERNAL]";
}

if(mparameter != p->meta().end()) {
char type = 0; char type = 0;
const char *foo = strchr(p->name, ':');
if(strchr(foo, 'f'))
type = 'f';
else if(strchr(foo, 'i'))
type = 'i';
else if(strchr(foo, 'c'))
type = 'c';
else if(strchr(foo, 'T'))
type = 't';
if(args) {
if(strchr(args, 'f'))
type = 'f';
else if(strchr(args, 'i'))
type = 'i';
else if(strchr(args, 'c'))
type = 'c';
else if(strchr(args, 'T'))
type = 't';
else if(strchr(args, 's'))
type = 's';
}

if(!type) { if(!type) {
fprintf(stderr, "rtosc port dumper: Cannot handle '%s'\n", p->name);
fprintf(stderr, "rtosc port dumper: Cannot handle '%s'\n", name);
fprintf(stderr, " args = <%s>\n", args);
return; return;
} }


if(type == 't')
{
o << " <message_in pattern=\"" << name << "\" typetag=\"T\">\n";
o << " <desc>Enable " << p->meta()["documentation"] << "</desc>\n";
o << " <param_T symbol=\"x\"/>\n";
o << " </message_in>\n";
o << " <message_in pattern=\"" << name << "\" typetag=\"F\">\n";
o << " <desc>Disable " << p->meta()["documentation"] << "</desc>\n";
o << " <param_F symbol=\"x\"/>\n";
o << " </message_in>\n";
o << " <message_in pattern=\"" << name << "\" typetag=\"\">\n";
o << " <desc>Get state of " << p->meta()["documentation"] << "</desc>\n";
o << " </message_in>\n";
o << " <message_out pattern=\"" << name << "\" typetag=\"T\">\n";
o << " <desc>Value of " << p->meta()["documentation"] << "</desc>\n";
o << " <param_T symbol=\"x\"/>";
o << " </message_out>\n";
o << " <message_out pattern=\"" << name << "\" typetag=\"F\">\n";
o << " <desc>Value of %s</desc>\n", p->meta()["documentation"];
o << " <param_F symbol=\"x\"/>";
o << " </message_out>\n";
if(type == 't') {
dump_t_f_port(o, name, doc);
return; return;
} }


o << " <message_in pattern=\"" << name << "\" typetag=\"" << type << "\">\n"; o << " <message_in pattern=\"" << name << "\" typetag=\"" << type << "\">\n";
o << " <desc>Set Value of " << p->meta()["documentation"] << "</desc>\n";
if(meta.find("min") != meta.end() && meta.find("max") != meta.end() && type != 'c')
{
o << " <desc>Set Value of " << doc << "</desc>\n";
if(meta.find("min") != meta.end() && meta.find("max") != meta.end() && type != 'c') {
o << " <param_" << type << " symbol=\"x\""; o << " <param_" << type << " symbol=\"x\"";
units(o, meta["unit"]); units(o, meta["unit"]);
o << ">\n"; o << ">\n";
@@ -785,12 +906,11 @@ void dump_ports_cb(const rtosc::Port *p, const char *name, void *v)
} }
o << " </message_in>\n"; o << " </message_in>\n";
o << " <message_in pattern=\"" << name << "\" typetag=\"\">\n"; o << " <message_in pattern=\"" << name << "\" typetag=\"\">\n";
o << " <desc>Get Value of " << p->meta()["documentation"] << "</desc>\n";
o << " <desc>Get Value of " << doc << "</desc>\n";
o << " </message_in>\n"; o << " </message_in>\n";
o << " <message_out pattern=\"" << name << "\" typetag=\"" << type << "\">\n"; o << " <message_out pattern=\"" << name << "\" typetag=\"" << type << "\">\n";
o << " <desc>Value of " << p->meta()["documentation"] << "</desc>\n";
if(meta.find("min") != meta.end() && meta.find("max") != meta.end() && type != 'c')
{
o << " <desc>Value of " << doc << "</desc>\n";
if(meta.find("min") != meta.end() && meta.find("max") != meta.end() && type != 'c') {
o << " <param_" << type << " symbol=\"x\""; o << " <param_" << type << " symbol=\"x\"";
units(o, meta["unit"]); units(o, meta["unit"]);
o << ">\n"; o << ">\n";
@@ -803,10 +923,17 @@ void dump_ports_cb(const rtosc::Port *p, const char *name, void *v)
o << "/>\n"; o << "/>\n";
} }
o << " </message_out>\n"; o << " </message_out>\n";
}// else if(meta.find("documentation") != meta.end())
// fprintf(stderr, "Skipping \"%s\"\n", name);
//else
// fprintf(stderr, "Skipping [UNDOCUMENTED] \"%s\"\n", name);
} else if(mdoc != meta.end() && (!args || args == std::string(""))) {
dump_any_port(o, name, doc);
} else if(mdoc != meta.end() && args) {
dump_generic_port(o, name, doc, args);
} else if(mdoc != meta.end()) {
fprintf(stderr, "Skipping \"%s\"\n", name);
if(args) {
fprintf(stderr, " type = %s\n", args);
}
} else
fprintf(stderr, "Skipping [UNDOCUMENTED] \"%s\"\n", name);
} }


std::ostream &rtosc::operator<<(std::ostream &o, rtosc::OscDocFormatter &formatter) std::ostream &rtosc::operator<<(std::ostream &o, rtosc::OscDocFormatter &formatter)


+ 12
- 4
source/native-plugins/zynaddsubfx/rtosc/cpp/subtree-serialize.cpp View File

@@ -1,12 +1,20 @@
#include "subtree-serialize.h"
#include "ports.h"
#include "rtosc.h"
#include <rtosc/subtree-serialize.h>
#include <rtosc/ports.h>
#include <rtosc/rtosc.h>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>




using namespace rtosc; using namespace rtosc;


static void emplace_uint32_cpp(uint8_t *buffer, uint32_t d)
{
buffer[0] = ((d>>24) & 0xff);
buffer[1] = ((d>>16) & 0xff);
buffer[2] = ((d>>8) & 0xff);
buffer[3] = ((d>>0) & 0xff);
}

/* /*
* Append another message onto a bundle if the space permits it. * Append another message onto a bundle if the space permits it.
* If insufficient space is available, then zero is returned and the buffer is * If insufficient space is available, then zero is returned and the buffer is
@@ -26,7 +34,7 @@ static size_t append_bundle(char *dst, const char *src,


if(max_len < dst_len + src_len + 4 || dst_len == 0 || src_len == 0) if(max_len < dst_len + src_len + 4 || dst_len == 0 || src_len == 0)
return 0; return 0;
*(int32_t*)(dst+dst_len) = (int32_t)src_len;
emplace_uint32_cpp((uint8_t*)(dst+dst_len), src_len);


memcpy(dst+dst_len+4, src, src_len); memcpy(dst+dst_len+4, src, src_len);




+ 1
- 4
source/native-plugins/zynaddsubfx/rtosc/cpp/thread-link.cpp View File

@@ -1,4 +1,4 @@
#include "thread-link.h"
#include "../thread-link.h"


namespace rtosc { namespace rtosc {
#ifdef off_t #ifdef off_t
@@ -17,7 +17,6 @@ struct internal_ringbuffer_t {
}; };


typedef internal_ringbuffer_t ringbuffer_t; typedef internal_ringbuffer_t ringbuffer_t;
#define static


static size_t ring_read_size(ringbuffer_t *ring) static size_t ring_read_size(ringbuffer_t *ring)
{ {
@@ -178,5 +177,3 @@ char *ThreadLink::buffer(void) {return write_buffer;}
size_t ThreadLink::buffer_size(void) const {return BufferSize;} size_t ThreadLink::buffer_size(void) const {return BufferSize;}


}; };

#undef static

+ 2
- 2
source/native-plugins/zynaddsubfx/rtosc/cpp/undo-history.cpp View File

@@ -3,8 +3,8 @@
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
#include <ctime> #include <ctime>
#include "rtosc.h"
#include "undo-history.h"
#include <rtosc/rtosc.h>
#include <rtosc/undo-history.h>


using std::pair; using std::pair;
using std::make_pair; using std::make_pair;


+ 211
- 1
source/native-plugins/zynaddsubfx/rtosc/dispatch.c View File

@@ -1,7 +1,13 @@
#include "rtosc.h"
#include <rtosc/rtosc.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h> #include <stdlib.h>



#include <stdio.h>

static bool rtosc_match_number(const char **pattern, const char **msg) static bool rtosc_match_number(const char **pattern, const char **msg)
{ {
//Verify both hold digits //Verify both hold digits
@@ -74,3 +80,207 @@ bool rtosc_match(const char *pattern, const char *msg)
return rtosc_match_args(arg_pattern, msg); return rtosc_match_args(arg_pattern, msg);
return true; return true;
} }



/*
* Special characters from the specification:
* ' ' space 32
* # number sign 35
* * asterisk 42
* , comma 44
* / forward slash 47
* ? question mark 63
* [ open bracket 91
* ] close bracket 93
* { open curly brace 123
* } close curly brace 125
*/

#if 0
QUOTE FROM OSC 1.0 SPEC

'?' in the OSC Address Pattern matches any single character
'*' in the OSC Address Pattern matches any sequence of zero or more characters
A string of characters in square brackets (e.g., "[string]") in the OSC Address Pattern matches any character in the string.
Inside square brackets, the minus sign (-) and exclamation point (!) have special meanings:
two characters separated by a minus sign indicate the range of characters between the given two
in ASCII collating sequence. (A minus sign at the end of the string has no special meaning.)
An exclamation point at the beginning of a bracketed string negates the sense of the list,
meaning that the list matches any character not in the list.
(An exclamation point anywhere besides the first character after the open bracket has no special meaning.)
A comma-separated list of strings enclosed in curly braces (e.g., "{foo,bar}") in the OSC Address Pattern
matches any of the strings in the list.
#endif




//for literal string X
//for X+?+[] Y
//for Y+single{} Z
//for numeric string N
//assume a is of the form X
//assume b is a pattern of the form:
//* (1)
//Y (2)
//Y* (3)
//*X* (4)
//Z (5)
//Z* (6)
//Y#N (7)
#define RTOSC_MATCH_ALL 1
#define RTOSC_MATCH_CHAR 2
#define RTOSC_MATCH_PARTIAL_CHAR 3
#define RTOSC_MATCH_SUBSTRING 4
#define RTOSC_MATCH_OPTIONS 5
#define RTOSC_MATCH_PARTIAL_OPTIONS 6
#define RTOSC_MATCH_ENUMERATED 7
static bool is_charwise(char c)
{
return (c>=0 && c<=0x7f) && c != ' ' && c != '#' &&
c != '/' && c != '{' && c != '}';
}

int rtosc_subpath_pat_type(const char *pattern)
{
int charwise_only = 1;
const char *last_star = rindex(pattern, '*');
const char *pound = index(pattern, '#');
if(!strcmp("*", pattern))
return RTOSC_MATCH_ALL;

for(const char *p = pattern;*p;++p)
charwise_only &= is_charwise(*p);
if(charwise_only && !last_star)
return RTOSC_MATCH_CHAR;
if(pound)
return RTOSC_MATCH_ENUMERATED;


return 2;
}

static bool rtosc_match_char(const char **path, const char **pattern)
{
//printf("rtosc_match_char('%s','%s')\n", *path, *pattern);
if(**path == **pattern && **path) {
++*path;
++*pattern;
return true;
} else if(**pattern == '?' && *path) {
++*path;
++*pattern;
return true;
} else if(**pattern == '[') {
bool matched = false;
bool negation = false;
char last_range = '\0';
char to_match = **path;
++*pattern;
if(**pattern == '!') {
negation = true;
++*pattern;
}
while(**pattern && **pattern != ']') {
last_range = **pattern;
if(**pattern == to_match) {
matched = true;
} else if(**pattern == '-') {//range
++*pattern;
char range_high = **pattern;
if(range_high == ']' || !range_high)
break;
if(to_match <= range_high && to_match >= last_range)
matched = true;
}
++*pattern;
}
if(**pattern == ']')
++*pattern;
++*path;
return negation ^ matched;
}
return false;
}

bool rtosc_match_partial(const char *a, const char *b)
{
//assume a is of the form X
//assume b is a pattern of the form: (1..6)
//This is done to avoid backtracking of any kind
//This is an OSC serialization library, not a regex
//implementation

char patternbuf[256];
(void) patternbuf;
int type = rtosc_subpath_pat_type(b);

if(type == RTOSC_MATCH_ALL)
return true;
else if(type == RTOSC_MATCH_CHAR || type == RTOSC_MATCH_PARTIAL_CHAR) {
while(rtosc_match_char(&a,&b));
if(!*a && !*b)
return true;
else if(*a && *b=='*' && b[1] == '\0')
return true;
else
return false;
} else if(type == 4) {
//extract substring
const char *sub=NULL;
return strstr(a,sub);
} else if(type == RTOSC_MATCH_OPTIONS || type == 6) {
} else if(type == RTOSC_MATCH_ENUMERATED) {
while(rtosc_match_char(&a,&b));
if(*a && *b=='#' && b[1] != '\0')
return atoi(a) < atoi(b+1);
return false;
} else
return 0;
assert(false);
}

int rtosc_matchable_path(const char *pattern)
{
(void) pattern;
return 0;

}

int chunk_path(const char *a, int b, const char *c)
{
(void) a;
(void) b;
(void) c;
return 0;
}
void advance_path(const char **a)
{
(void) a;
}

bool rtosc_match_full_path(const char *pattern, const char *message)
{
assert(false && "This API is a WIP");
char subpattern[256];
char submessage[256];
const char *p = pattern;
const char *m = message;

step:
if(*p != *m)
return 0;
if(chunk_path(subpattern, sizeof(subpattern), p))
return 0;
if(chunk_path(submessage, sizeof(submessage), m))
return 0;

advance_path(&p);
advance_path(&m);

if(*p == 0 && *m == 0)
return 1;
else
goto step;
}

+ 4
- 2
source/native-plugins/zynaddsubfx/rtosc/miditable.h View File

@@ -21,9 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ */
#ifndef RTOSC_MIDITABLE_H
#define RTOSC_MIDITABLE_H


#pragma once
#include "ports.h"
#include <rtosc/ports.h>
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <map> #include <map>
@@ -276,3 +277,4 @@ class MidiTable
}; };


}; };
#endif

+ 29
- 5
source/native-plugins/zynaddsubfx/rtosc/port-sugar.h View File

@@ -43,8 +43,8 @@ struct rtosc_hack_decltype_t
#define STRINGIFY(a) STRINGIFY2(a) #define STRINGIFY(a) STRINGIFY2(a)


//Helper for documenting varargs //Helper for documenting varargs
#define IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9, N, ...) N
#define LAST_IMP(...) IMPL(__VA_ARGS__,9,8,7,6,5,4,3,2,1,0,0,0,0)
#define IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,N, ...) N
#define LAST_IMP(...) IMPL(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0)
#define DOC_IMP9(a,b,c,d,e,f,g,h,i) a b c d e f g h rDoc(i) #define DOC_IMP9(a,b,c,d,e,f,g,h,i) a b c d e f g h rDoc(i)
#define DOC_IMP8(a,b,c,d,e,f,g,h) a b c d e f g rDoc(h) #define DOC_IMP8(a,b,c,d,e,f,g,h) a b c d e f g rDoc(h)
#define DOC_IMP7(a,b,c,d,e,f,g) a b c d e f rDoc(g) #define DOC_IMP7(a,b,c,d,e,f,g) a b c d e f rDoc(g)
@@ -75,6 +75,30 @@ struct rtosc_hack_decltype_t
#define MAC_EACH_I(mac, count, ...) MAC_EACH_IMP(mac, count, __VA_ARGS__) #define MAC_EACH_I(mac, count, ...) MAC_EACH_IMP(mac, count, __VA_ARGS__)
#define MAC_EACH(mac, ...) MAC_EACH_I(mac, LAST_IMP(__VA_ARGS__), __VA_ARGS__) #define MAC_EACH(mac, ...) MAC_EACH_I(mac, LAST_IMP(__VA_ARGS__), __VA_ARGS__)


// 1 2 3 4 5 6 7 8 910111213141516
#define OPTIONS_IMP16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
rOpt(14,o)rOpt(15,p)
#define OPTIONS_IMP15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
rOpt(14,o)
#define OPTIONS_IMP14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)
#define OPTIONS_IMP13(a,b,c,d,e,f,g,h,i,j,k,l,m) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)
#define OPTIONS_IMP12(a,b,c,d,e,f,g,h,i,j,k,l) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)
#define OPTIONS_IMP11(a,b,c,d,e,f,g,h,i,j,k) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)
#define OPTIONS_IMP10(a,b,c,d,e,f,g,h,i,j) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(9,j)
#define OPTIONS_IMP9(a,b,c,d,e,f,g,h,i) \ #define OPTIONS_IMP9(a,b,c,d,e,f,g,h,i) \
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \ rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
rOpt(7,h) rOpt(8,i) rOpt(7,h) rOpt(8,i)
@@ -137,7 +161,7 @@ struct rtosc_hack_decltype_t
//Alias operators //Alias operators
#define rParams(name, length, ...) \ #define rParams(name, length, ...) \
rArray(name, length, __VA_ARGS__), \ rArray(name, length, __VA_ARGS__), \
{STRINGIFY(name) ":", rProp(alias), NULL, rParamsCb(name, length)}
{STRINGIFY(name) ":", rProp(alias) rDoc("get all data from aliased array"), NULL, rParamsCb(name, length)}




template<class T> constexpr T spice(T*t) {return *t;} template<class T> constexpr T spice(T*t) {return *t;}
@@ -145,7 +169,7 @@ template<class T> constexpr T spice(T*t) {return *t;}
//Recursion [two ports in one for pointer manipulation] //Recursion [two ports in one for pointer manipulation]
#define rRecur(name, ...) \ #define rRecur(name, ...) \
{STRINGIFY(name) "/", DOC(__VA_ARGS__), &decltype(rObject::name)::ports, rRecurCb(name)}, \ {STRINGIFY(name) "/", DOC(__VA_ARGS__), &decltype(rObject::name)::ports, rRecurCb(name)}, \
{STRINGIFY(name) ":", rProp(internal), NULL, rRecurPtrCb(name)}
{STRINGIFY(name) ":", rProp(internal) rDoc("get obj pointer"), NULL, rRecurPtrCb(name)}


#define rRecurp(name, ...) \ #define rRecurp(name, ...) \
{STRINGIFY(name) "/", DOC(__VA_ARGS__), \ {STRINGIFY(name) "/", DOC(__VA_ARGS__), \
@@ -168,7 +192,7 @@ template<class T> constexpr T spice(T*t) {return *t;}
//Misc //Misc
#define rDummy(name, ...) {STRINIFY(name), rProp(dummy), NULL, [](msg_t, rtosc::RtData &){}} #define rDummy(name, ...) {STRINIFY(name), rProp(dummy), NULL, [](msg_t, rtosc::RtData &){}}
#define rString(name, len, ...) \ #define rString(name, len, ...) \
{STRINGIFY(name) "::s", rMap(length, len) DOC(__VA_ARGS__), NULL, rStringCb(name,len)}
{STRINGIFY(name) "::s", rMap(length, len) rProp(parameter) DOC(__VA_ARGS__), NULL, rStringCb(name,len)}


//General property operators //General property operators
#define rMap(name, value) ":" STRINGIFY(name) "\0=" STRINGIFY(value) "\0" #define rMap(name, value) ":" STRINGIFY(name) "\0=" STRINGIFY(value) "\0"


+ 8
- 1
source/native-plugins/zynaddsubfx/rtosc/ports.h View File

@@ -28,7 +28,7 @@
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>
#include "rtosc.h"
#include <rtosc/rtosc.h>
#include <cstring> #include <cstring>
#include <cctype> #include <cctype>
#include <cstdlib> #include <cstdlib>
@@ -180,6 +180,13 @@ struct Ports
*/ */
const Port *apropos(const char *path) const; const Port *apropos(const char *path) const;


/**
* Collapse path with parent path identifiers "/.."
*
* e.g. /foo/bar/../baz => /foo/baz
*/
static char *collapsePath(char *p);

private: private:
//Performance hacks //Performance hacks
class Port_Matcher *impl; class Port_Matcher *impl;


+ 166
- 58
source/native-plugins/zynaddsubfx/rtosc/rtosc.c View File

@@ -6,7 +6,7 @@
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>


#include "rtosc.h"
#include <rtosc/rtosc.h>


const char *rtosc_argument_string(const char *msg) const char *rtosc_argument_string(const char *msg)
{ {
@@ -78,6 +78,58 @@ char rtosc_type(const char *msg, unsigned nargument)
} }
} }


static unsigned arg_start(const char *msg_)
{
const uint8_t *msg = (const uint8_t*)msg_;
//Iterate to the right position
const uint8_t *args = (const uint8_t*) rtosc_argument_string(msg_);
const uint8_t *aligned_ptr = args-1;
const uint8_t *arg_pos = args;

while(*++arg_pos);
//Alignment
arg_pos += 4-(arg_pos-aligned_ptr)%4;
return arg_pos-msg;
}

static unsigned arg_size(const uint8_t *arg_mem, char type)
{
if(!has_reserved(type))
return 0;
const uint8_t *arg_pos=arg_mem;
uint32_t blob_length = 0;
switch(type)
{
case 'h':
case 't':
case 'd':
return 8;
case 'm':
case 'r':
case 'f':
case 'c':
case 'i':
return 4;
case 'S':
case 's':
while(*++arg_pos);
arg_pos += 4-(arg_pos-arg_mem)%4;
return arg_pos-arg_mem;
case 'b':
blob_length |= (*arg_pos++ << 24);
blob_length |= (*arg_pos++ << 16);
blob_length |= (*arg_pos++ << 8);
blob_length |= (*arg_pos++);
if(blob_length%4)
blob_length += 4-blob_length%4;
arg_pos += blob_length;
return arg_pos-arg_mem;
default:
assert("Invalid Type");
}
return -1;
}

static unsigned arg_off(const char *msg, unsigned idx) static unsigned arg_off(const char *msg, unsigned idx)
{ {
if(!has_reserved(rtosc_type(msg,idx))) if(!has_reserved(rtosc_type(msg,idx)))
@@ -97,45 +149,11 @@ static unsigned arg_off(const char *msg, unsigned idx)
++args; ++args;


while(idx--) { while(idx--) {
uint32_t bundle_length = 0;
switch(*args++)
{
case 'h':
case 't':
case 'd':
arg_pos +=8;
break;
case 'm':
case 'r':
case 'f':
case 'c':
case 'i':
arg_pos += 4;
break;
case 'S':
case 's':
while(*++arg_pos);
arg_pos += 4-(arg_pos-((uint8_t*)aligned_ptr))%4;
break;
case 'b':
bundle_length |= (*arg_pos++ << 24);
bundle_length |= (*arg_pos++ << 16);
bundle_length |= (*arg_pos++ << 8);
bundle_length |= (*arg_pos++);
if(bundle_length%4)
bundle_length += 4-bundle_length%4;
arg_pos += bundle_length;
break;
case '[':
case ']':
//completely ignore array chars
++idx;
break;
case 'T':
case 'F':
case 'I':
;
}
char type = *args++;
if(type == '[' || type == ']')
idx++;//not a valid arg idx
else
arg_pos += arg_size(arg_pos, type);
} }
return arg_pos-(uint8_t*)msg; return arg_pos-(uint8_t*)msg;
} }
@@ -385,10 +403,9 @@ size_t rtosc_amessage(char *buffer,
return pos; return pos;
} }


rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
static rtosc_arg_t extract_arg(const uint8_t *arg_pos, char type)
{ {
rtosc_arg_t result = {0}; rtosc_arg_t result = {0};
char type = rtosc_type(msg, idx);
//trivial case //trivial case
if(!has_reserved(type)) { if(!has_reserved(type)) {
switch(type) switch(type)
@@ -403,7 +420,6 @@ rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
; ;
} }
} else { } else {
const unsigned char *arg_pos = (const unsigned char*)msg+arg_off(msg,idx);
switch(type) switch(type)
{ {
case 'h': case 'h':
@@ -450,6 +466,52 @@ rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
return result; return result;
} }


static const char *advance_past_dummy_args(const char *args)
{
while(*args == '[' || *args == ']')
args++;
return args;
}

rtosc_arg_itr_t rtosc_itr_begin(const char *msg)
{
rtosc_arg_itr_t itr;
itr.type_pos = advance_past_dummy_args(rtosc_argument_string(msg));
itr.value_pos = (uint8_t*)(msg+arg_start(msg));

return itr;
}

rtosc_arg_val_t rtosc_itr_next(rtosc_arg_itr_t *itr)
{
//current position provides the value
rtosc_arg_val_t result = {0};
result.type = *itr->type_pos;
if(result.type)
result.val = extract_arg(itr->value_pos, result.type);

//advance
itr->type_pos = advance_past_dummy_args(itr->type_pos+1);
char type = result.type;
int size = arg_size(itr->value_pos, type);
itr->value_pos += size;


return result;
}

int rtosc_itr_end(rtosc_arg_itr_t itr)
{
return !itr.type_pos || !*itr.type_pos;
}

rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
{
char type = rtosc_type(msg, idx);
uint8_t *arg_mem = (uint8_t*)msg + arg_off(msg, idx);
return extract_arg(arg_mem, type);
}

static unsigned char deref(unsigned pos, ring_t *ring) static unsigned char deref(unsigned pos, ring_t *ring)
{ {
return pos<ring[0].len ? ring[0].data[pos] : return pos<ring[0].len ? ring[0].data[pos] :
@@ -461,10 +523,10 @@ static size_t bundle_ring_length(ring_t *ring)
unsigned pos = 8+8;//goto first length field unsigned pos = 8+8;//goto first length field
uint32_t advance = 0; uint32_t advance = 0;
do { do {
advance = deref(pos+0, ring) << (8*0) |
deref(pos+1, ring) << (8*1) |
deref(pos+2, ring) << (8*2) |
deref(pos+3, ring) << (8*3);
advance = deref(pos+0, ring) << (8*3) |
deref(pos+1, ring) << (8*2) |
deref(pos+2, ring) << (8*1) |
deref(pos+3, ring) << (8*0);
if(advance) if(advance)
pos += 4+advance; pos += 4+advance;
} while(advance); } while(advance);
@@ -598,6 +660,49 @@ bool rtosc_valid_message_p(const char *msg, size_t len)
size_t observed_length = rtosc_message_length(msg, len); size_t observed_length = rtosc_message_length(msg, len);
return observed_length == len; return observed_length == len;
} }
static uint64_t extract_uint64(const uint8_t *arg_pos)
{
uint64_t arg = 0;
arg |= (((uint64_t)*arg_pos++) << 56);
arg |= (((uint64_t)*arg_pos++) << 48);
arg |= (((uint64_t)*arg_pos++) << 40);
arg |= (((uint64_t)*arg_pos++) << 32);
arg |= (((uint64_t)*arg_pos++) << 24);
arg |= (((uint64_t)*arg_pos++) << 16);
arg |= (((uint64_t)*arg_pos++) << 8);
arg |= (((uint64_t)*arg_pos++));
return arg;
}

static uint32_t extract_uint32(const uint8_t *arg_pos)
{
uint32_t arg = 0;
arg |= (((uint32_t)*arg_pos++) << 24);
arg |= (((uint32_t)*arg_pos++) << 16);
arg |= (((uint32_t)*arg_pos++) << 8);
arg |= (((uint32_t)*arg_pos++));
return arg;
}

static void emplace_uint64(uint8_t *buffer, uint64_t d)
{
buffer[0] = ((d>>56) & 0xff);
buffer[1] = ((d>>48) & 0xff);
buffer[2] = ((d>>40) & 0xff);
buffer[3] = ((d>>32) & 0xff);
buffer[4] = ((d>>24) & 0xff);
buffer[5] = ((d>>16) & 0xff);
buffer[6] = ((d>>8) & 0xff);
buffer[7] = ((d>>0) & 0xff);
}

static void emplace_uint32(uint8_t *buffer, uint32_t d)
{
buffer[0] = ((d>>24) & 0xff);
buffer[1] = ((d>>16) & 0xff);
buffer[2] = ((d>>8) & 0xff);
buffer[3] = ((d>>0) & 0xff);
}


size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms, ...) size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms, ...)
{ {
@@ -605,15 +710,15 @@ size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms, ...)
memset(buffer, 0, len); memset(buffer, 0, len);
strcpy(buffer, "#bundle"); strcpy(buffer, "#bundle");
buffer += 8; buffer += 8;
(*(uint64_t*)buffer) = tt;
buffer +=8;
emplace_uint64((uint8_t*)buffer, tt);
buffer += 8;
va_list va; va_list va;
va_start(va, elms); va_start(va, elms);
for(int i=0; i<elms; ++i) { for(int i=0; i<elms; ++i) {
const char *msg = va_arg(va, const char*); const char *msg = va_arg(va, const char*);
//It is assumed that any passed message/bundle is valid //It is assumed that any passed message/bundle is valid
size_t size = rtosc_message_length(msg, -1); size_t size = rtosc_message_length(msg, -1);
*(uint32_t*)buffer = size;
emplace_uint32((uint8_t*)buffer, size);
buffer += 4; buffer += 4;
memcpy(buffer, msg, size); memcpy(buffer, msg, size);
buffer+=size; buffer+=size;
@@ -623,14 +728,14 @@ size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms, ...)
return buffer-_buffer; return buffer-_buffer;
} }



#define POS ((size_t)(((const char *)lengths) - buffer)) #define POS ((size_t)(((const char *)lengths) - buffer))
size_t rtosc_bundle_elements(const char *buffer, size_t len) size_t rtosc_bundle_elements(const char *buffer, size_t len)
{ {
const uint32_t *lengths = (const uint32_t*) (buffer+16); const uint32_t *lengths = (const uint32_t*) (buffer+16);
size_t elms = 0; size_t elms = 0;
//TODO
while(POS < len && *lengths) {
lengths += *lengths/4+1;
while(POS < len && extract_uint32((const uint8_t*)lengths)) {
lengths += extract_uint32((const uint8_t*)lengths)/4+1;


if(POS > len) if(POS > len)
break; break;
@@ -644,7 +749,10 @@ const char *rtosc_bundle_fetch(const char *buffer, unsigned elm)
{ {
const uint32_t *lengths = (const uint32_t*) (buffer+16); const uint32_t *lengths = (const uint32_t*) (buffer+16);
size_t elm_pos = 0; size_t elm_pos = 0;
while(elm_pos!=elm && *lengths) ++elm_pos, lengths+=*lengths/4+1;
while(elm_pos!=elm && extract_uint32((const uint8_t*)lengths)) {
++elm_pos;
lengths += extract_uint32((const uint8_t*)lengths)/4+1;
}


return (const char*) (elm==elm_pos?lengths+1:NULL); return (const char*) (elm==elm_pos?lengths+1:NULL);
} }
@@ -654,9 +762,9 @@ size_t rtosc_bundle_size(const char *buffer, unsigned elm)
const uint32_t *lengths = (const uint32_t*) (buffer+16); const uint32_t *lengths = (const uint32_t*) (buffer+16);
size_t elm_pos = 0; size_t elm_pos = 0;
size_t last_len = 0; size_t last_len = 0;
while(elm_pos!=elm && *lengths) {
last_len = *lengths;
++elm_pos, lengths+=*lengths/4+1;
while(elm_pos!=elm && extract_uint32((const uint8_t*)lengths)) {
last_len = extract_uint32((const uint8_t*)lengths);
++elm_pos, lengths+=extract_uint32((const uint8_t*)lengths)/4+1;
} }


return last_len; return last_len;
@@ -669,5 +777,5 @@ int rtosc_bundle_p(const char *msg)


uint64_t rtosc_bundle_timetag(const char *msg) uint64_t rtosc_bundle_timetag(const char *msg)
{ {
return *(uint64_t*)(msg+8);
return extract_uint64((const uint8_t*)msg+8);
} }

+ 31
- 0
source/native-plugins/zynaddsubfx/rtosc/rtosc.h View File

@@ -115,6 +115,37 @@ unsigned rtosc_narguments(const char *msg);
*/ */
char rtosc_type(const char *msg, unsigned i); char rtosc_type(const char *msg, unsigned i);


typedef struct {
const char *type_pos;
const uint8_t *value_pos;
} rtosc_arg_itr_t;

typedef struct {
char type;
rtosc_arg_t val;
} rtosc_arg_val_t;

/**
* Create an argument iterator for a message
* @param msg OSC message
* @returns an initialized iterator
*/
rtosc_arg_itr_t rtosc_itr_begin(const char *msg);

/**
* Gets the next argument in a message
* @param itr OSC message iterator
* @returns a type value pair from the message
*/
rtosc_arg_val_t rtosc_itr_next(rtosc_arg_itr_t *itr);

/**
* Determines if the iterator is at the end of the argument list
* @param itr OSC message iterator
* @returns 1 if there are no more elements, 0 otherwise
*/
int rtosc_itr_end(rtosc_arg_itr_t itr);

/** /**
* Blob data may be safely written to * Blob data may be safely written to
* @param msg OSC message * @param msg OSC message


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save