From e40fc849149dd97c248866a4a1d026dda5e57b62 Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Mon, 7 Mar 2011 19:01:11 +0000 Subject: clean3 --- attic/muse2-oom/muse2/synti/vam/CMakeLists.txt | 92 ++ attic/muse2-oom/muse2/synti/vam/COPYING | 340 ++++ attic/muse2-oom/muse2/synti/vam/ChangeLog | 16 + attic/muse2-oom/muse2/synti/vam/README | 42 + attic/muse2-oom/muse2/synti/vam/TODO | 3 + attic/muse2-oom/muse2/synti/vam/vam.cpp | 1055 +++++++++++++ attic/muse2-oom/muse2/synti/vam/vam.h | 38 + attic/muse2-oom/muse2/synti/vam/vamgui.cpp | 724 +++++++++ attic/muse2-oom/muse2/synti/vam/vamgui.h | 82 + attic/muse2-oom/muse2/synti/vam/vamguibase.ui | 1974 ++++++++++++++++++++++++ 10 files changed, 4366 insertions(+) create mode 100644 attic/muse2-oom/muse2/synti/vam/CMakeLists.txt create mode 100644 attic/muse2-oom/muse2/synti/vam/COPYING create mode 100644 attic/muse2-oom/muse2/synti/vam/ChangeLog create mode 100644 attic/muse2-oom/muse2/synti/vam/README create mode 100644 attic/muse2-oom/muse2/synti/vam/TODO create mode 100644 attic/muse2-oom/muse2/synti/vam/vam.cpp create mode 100644 attic/muse2-oom/muse2/synti/vam/vam.h create mode 100644 attic/muse2-oom/muse2/synti/vam/vamgui.cpp create mode 100644 attic/muse2-oom/muse2/synti/vam/vamgui.h create mode 100644 attic/muse2-oom/muse2/synti/vam/vamguibase.ui (limited to 'attic/muse2-oom/muse2/synti/vam') diff --git a/attic/muse2-oom/muse2/synti/vam/CMakeLists.txt b/attic/muse2-oom/muse2/synti/vam/CMakeLists.txt new file mode 100644 index 00000000..31f2a12a --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/CMakeLists.txt @@ -0,0 +1,92 @@ +#============================================================================= +# MusE +# Linux Music Editor +# $Id:$ +# +# Copyright (C) 2002-2006 by Werner Schweer and others +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#============================================================================= + +## +## Expand Qt macros in source files +## +QT4_WRAP_CPP ( vam_mocs + vamgui.h + ) + +## +## UI files +## +file (GLOB vam_ui_files + vamguibase.ui + ) +QT4_WRAP_UI ( vam_uis ${vam_ui_files} ) + +## +## List of source files to compile +## +file (GLOB vam_source_files + vam.cpp + vamgui.cpp + ) + +## +## Define target +## +add_library ( vam SHARED + ${vam_source_files} + ${vam_mocs} + ${vam_uis} + ) + +## +## Append to the list of translations +## +set (FILES_TO_TRANSLATE + ${FILES_TO_TRANSLATE} + ${vam_source_files} + ${vam_ui_files} + CACHE INTERNAL "" + ) + +## +## Compilation flags and target name +## +# - tell cmake to name target vam.so instead of +# libvam.so +# - use precompiled header files +# +set_target_properties ( vam + PROPERTIES PREFIX "" + COMPILE_FLAGS "-fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h" + ) + +## +## Linkage +## +target_link_libraries(vam + # al + synti + ${QT_LIBRARIES} + ) + +## +## Install location +## +install( TARGETS vam + DESTINATION ${MusE_SYNTHI_DIR} + ) +install( FILES ChangeLog COPYING README TODO + DESTINATION ${MusE_DOC_DIR}/vam + ) diff --git a/attic/muse2-oom/muse2/synti/vam/COPYING b/attic/muse2-oom/muse2/synti/vam/COPYING new file mode 100644 index 00000000..dc63aaca --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/COPYING @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/attic/muse2-oom/muse2/synti/vam/ChangeLog b/attic/muse2-oom/muse2/synti/vam/ChangeLog new file mode 100644 index 00000000..1a7e4258 --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/ChangeLog @@ -0,0 +1,16 @@ + +VAM-1.0beta2b (4/02 - 2002) + * Fix to prevent clicks on new notes + * Gui improvements (Thanks Werner and Bob) + +VAM-1.0beta2 (24/01 - 2002) + * Fix to make presets save and load correctly + * DSP improvements + * PW & PWM + * Some basic presets + * Small fixes + * Filter keytracking + * Load only preset meant for vam + +VAM-1.0beta1 (21/01 - 2002): + First release. \ No newline at end of file diff --git a/attic/muse2-oom/muse2/synti/vam/README b/attic/muse2-oom/muse2/synti/vam/README new file mode 100644 index 00000000..738ad657 --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/README @@ -0,0 +1,42 @@ +VAM: Virtual Analog for MusE + + by Josef Lindman Hörnlund + + +*** WARNING! VAM has at the time some significant problems +*** (esp. with the filter). Some parameters should not have +*** high values ( like the filter resonance, the filter +*** env mod or dco sustain ) + +* What's VAM?? + + VAM is a soft synth for MusE (http://muse.seh.de) emulating + an old monophonic two oscillator analog synthesizer. It has + a simple interface and a quite fast synthesis engine. + +* Installation + MusE version >= 0.5.0 required (I think) + ( and everything that MusE requires, like Qt3 ) + + Unpack VAM in $MUSESOURCEDIR/synthi and run from vam/ make; + make install. VAM won't compile automaticly if you run make + from $MUSESOURCEDIR. + $MUSESOURCEDIR is the directory you have the MusE source. + For optimizing add -march=(your arch) to the compiler arguments + in Makefile. + +* Using VAM: + + To have fun with VAM MusE really should be started with -R. + Otherwise VAM will produce mostly noise, like clicks. + If you're familiar with analog or virtual analog synthesizers + using VAM souldn't be a problem. + + If you add some cool LADSPA plugins like delay or chorus to VAM's + output, you'll get _much_ better sounds, playing without effects + is like eating beef without sauce. + +* Contact: + + Please mail me at jotsif@linux.nu if you're having any + problems, suggestions, bugs, ideas or other comments. diff --git a/attic/muse2-oom/muse2/synti/vam/TODO b/attic/muse2-oom/muse2/synti/vam/TODO new file mode 100644 index 00000000..370bb521 --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/TODO @@ -0,0 +1,3 @@ + +1. Make bandlimited wavetables!! +2. Split VAM into a polyphonic and a monophonic synth \ No newline at end of file diff --git a/attic/muse2-oom/muse2/synti/vam/vam.cpp b/attic/muse2-oom/muse2/synti/vam/vam.cpp new file mode 100644 index 00000000..6d9d181c --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/vam.cpp @@ -0,0 +1,1055 @@ +//========================================================= +// MusE +// Linux Music Editor +// +// Parts of this file taken from: +// The analogue oscillator from Steve Harris plugin collection. +// Werner Schweer's organ softsynth for MusE. +// The music-dsp source archive. +// +// (C) Copyright 2002 Jotsif Lindman H�nlund (jotsif@linux.nu) +// (C) Copyright 2005 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA or point your web browser to http://www.gnu.org. +//========================================================= + +#include +#include +#include +#include + +#include "libsynti/mess.h" +#include "muse/midi.h" +#include "muse/midictrl.h" + +#include "vam.h" +#include "vamgui.h" +#include "libsynti/mono.h" + +// Denormalise floats, only actually needed for PIII and very recent PowerPC +#define DENORMALISE(fv) (((*(unsigned int*)&(fv))&0x7f800000)==0)?0.0f:(fv) + +// A fast, truncating towards 0 modulo function. ANSI C doesn't define +// which % will do, most truncate towards -inf +#define MOD(v,m) (v<0?v+m:(v>m?v-m:v)) + +// Limit values +#define LIMIT(v,l,u) (vu?u:v)) + +#define PI M_PI + +//--------------------------------------------------------- +// Oscillator +//--------------------------------------------------------- + +struct Oscillator { +float phase; +float pitchmod; +float detune; +float freq; +float pwm; +float pw; +float fm; +int waveform; +bool on; +}; + +struct LPFilter { +float out[4]; +float in[4]; +}; + +//--------------------------------------------------------- +// Envelope +//--------------------------------------------------------- + +struct EnvelopeGenerator { +static const int onStates = 2; +static const int offStates = 1; + +struct Segment { + int ticks; + double incr; +}; +Segment segment[onStates + offStates]; + +int state; +double env; +int tick; + +int attack; +int decay; +float sustain; +int release; + +EnvelopeGenerator() { + segment[0].ticks = 441; + segment[0].incr = 1.0/441.0; + segment[1].ticks = 0; + segment[1].incr = 0.0; + segment[2].ticks = 441; + segment[2].incr = -(1.0/441.0); +} + +void setSegment(int seg, int ticks, double incr) { + segment[seg].ticks = ticks; + segment[seg].incr = incr; +} + +void keyOn() { +// env = 0.0; + state = 0; + if(env) segment[state].incr = (1.0 - env) / segment[state].ticks; + else env = 0.0; + tick = segment[state].ticks; +} +void keyOff() { + state = onStates; + tick = segment[state].ticks; +} +bool isOff() { + return state == (onStates+offStates); +} +bool step() { + if(state >= onStates+offStates) + return false; + if (tick == 0) + return true; + env +=segment[state].incr; + if(env < 0.0) + env = 0.0; + --tick; + while(tick == 0) { + ++state; + if(state >= onStates+offStates) + return false; + if(state == onStates) + return true; + tick = segment[state].ticks; + } + return true; +} +}; + +//--------------------------------------------------------- +// VAM +//--------------------------------------------------------- + +class VAM : public MessMono { + static int useCount; + static const int CB_AMP_SIZE = 961; + static const int LIN2EXP_SIZE = 256; + + static double cb2amp_tab[CB_AMP_SIZE]; + static double cb2amp(double cb); + + static float lin2exp[LIN2EXP_SIZE]; + + /* Synthvariables */ + static float *sin_tbl, *tri_tbl, *saw_tbl, *squ_tbl; + bool isOn; + int pitch, channel; + float velocity; + + //int idata[NUM_CONTROLLER]; // buffer for init data + int *idata; + + EnvelopeGenerator dco1_env; + EnvelopeGenerator dco2_env; + EnvelopeGenerator filt_env; + + LPFilter dco1_filter; + LPFilter dco2_filter; + + Oscillator dco1; + Oscillator dco2; + Oscillator lfo; + + bool filt_invert, filt_keytrack; + double filt_env_mod, filt_res, filt_cutoff, keytrack_cutoff; + + int controller[NUM_CONTROLLER]; + void noteoff(int channel, int pitch); + void setController(int ctrl, int data); + float *wave_tbl(int wave); + double lowpass_filter(double cutoff, double resonance, double input, LPFilter *f); + + + VAMGui* gui; + + public: + virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) const; + virtual void getInitData(int* n, const unsigned char**p) const; + virtual bool guiVisible() const; + virtual void showGui(bool); + virtual bool hasGui() const { return true; } + virtual void getGeometry(int* x, int* y, int* w, int* h) const; + virtual void setGeometry(int x, int y, int w, int h); + virtual void processMessages(); + virtual void process(float**, int, int); + virtual void note(int channel, int pitch, int velo); + virtual bool setController(int channel, int ctrl, int val); + virtual bool sysex(int, const unsigned char*); + VAM(int sr); + ~VAM(); + bool init(const char* name); +}; + +float* VAM::sin_tbl; +float* VAM::tri_tbl; +float* VAM::saw_tbl; +float* VAM::squ_tbl; +int VAM::useCount = 0; +double VAM::cb2amp_tab[VAM::CB_AMP_SIZE]; +float VAM::lin2exp[VAM::LIN2EXP_SIZE]; + + +//--------------------------------------------------------- +// VAM +//--------------------------------------------------------- + +VAM::VAM(int sr) + : MessMono() + { + idata = new int[NUM_CONTROLLER]; + setSampleRate(sr); + gui = 0; + } + +//--------------------------------------------------------- +// ~VAM +//--------------------------------------------------------- + +VAM::~VAM() + { + --useCount; + if (useCount == 0) { + delete[] sin_tbl; + delete[] tri_tbl; + delete[] saw_tbl; + delete[] squ_tbl; + } + } + +//--------------------------------------------------------- +// curTime +//--------------------------------------------------------- + +double VAM::cb2amp(double cb) + { + if(cb < 0.0) + return 1.0; + if(cb > 960.0) + return 0.0; + return cb2amp_tab[int(cb)]; + } + +double VAM::lowpass_filter(double cutoff, double resonance, double input, LPFilter *f) + { + double output; + cutoff *= 1.16; + + input -= f->out[3] * (resonance * 4.0) * (1.0 - 0.15 * cutoff * cutoff); + input *= 0.35013 * cutoff * cutoff * cutoff * cutoff; + + f->out[0] = input + 0.3 * f->in[0] + (1.0 - cutoff) * f->out[0]; // Pole 1 + f->in[0] = input; + f->out[1] = f->out[0] + 0.3 * f->in[1] + (1.0 - cutoff) * f->out[1]; // Pole 2 + f->in[1] = f->out[0]; + f->out[2] = f->out[1] + 0.3 * f->in[2] + (1.0 - cutoff) * f->out[2]; // Pole 3 + f->in[2] = f->out[1]; + f->out[3] = f->out[2] + 0.3 * f->in[3] + (1.0 - cutoff) * f->out[3]; // Pole 4 + f->in[3] = f->out[2]; + + // if(f.out[3] > 1.0) f.out[3] = 1.0; + + output = f->out[3]; + + + return output; + } + +float *VAM::wave_tbl(int wave) + { + if (wave == 0) { + return sin_tbl; + } + else if (wave == 1) { + return squ_tbl; + } + else if (wave == 2) { + return saw_tbl; + } + else if (wave == 3) { + return tri_tbl; + } + return sin_tbl; + } + +//--------------------------------------------------------- +// init +//--------------------------------------------------------- + +bool VAM::init(const char* name) + { + gui = new VAMGui; + gui->setWindowTitle(QString(name)); + gui->show(); + + if (useCount == 0) { + int i; + float tmp; + for(i = 0; i < CB_AMP_SIZE; i++) { + cb2amp_tab[i] = pow(10.0, double(i) / -300.0); + //cb2amp_tab[i] = 1.0 - i/(float)CB_AMP_SIZE; + } + for(i = 0; i < LIN2EXP_SIZE; i++) { + tmp = i/255.0; + lin2exp[i] = 1.5 * tmp * tmp * tmp - 0.69 * tmp * tmp + 0.16 * tmp; + } + int sr = sampleRate(); + /* Build up denormalised oscilator wavetables, these are sample_rate + long, costs more RAM to create them but makes freqency calcs much + cheaper, and means that interpolation isn't that neccesary, esp if + you use integer frequncies */ + + float *tmp_tbl = new float[sr]; + const int lag = sr/50; + sin_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = sin(i * 2.0 * PI / sr); + sin_tbl[i] = DENORMALISE(tmp); + } + tri_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = acos(cos(i * 2.0 * PI / sr)) / PI * 2.0 - 1.0; + tri_tbl[i] = DENORMALISE(tmp); + } + squ_tbl = new float[sr]; + for (i = 0; i < sr/2; i++) { + tmp_tbl[i] = -1.0f; + } + for (i = sr/2; i < sr; i++) { + tmp_tbl[i] = +1.0f; + } + tmp = -1.0f; + for (i = (sr/2)-lag; i < (sr/2)+lag; i++) { + tmp_tbl[i] = tmp; + tmp += 1.0/(lag * 2.0); + } + for (i = 0; i < sr; i++) { + squ_tbl[i] = (tmp_tbl[MOD(i-lag, sr)] + + tmp_tbl[MOD(i+lag, sr)]) * 0.5; + } + saw_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = ((2.0 * i) - (float)sr) / (float)sr; + tmp_tbl[i] = DENORMALISE(tmp); + } + for (i = 0; i < sr; i++) { + saw_tbl[i] = (tmp_tbl[MOD(i-lag, sr)] + + tmp_tbl[MOD(i+lag, sr)]) * 0.5; + } + delete[] tmp_tbl; + } + + dco1_filter.out[0] = dco1_filter.out[1] = dco1_filter.out[2] = dco1_filter.out[3] = 0.0; + dco1_filter.in[0] = dco1_filter.in[1] = dco1_filter.in[2] = dco1_filter.in[3] = 0.0; + dco2_filter.out[0] = dco2_filter.out[1] = dco2_filter.out[2] = dco2_filter.out[3] = 0.0; + dco2_filter.in[0] = dco2_filter.in[1] = dco2_filter.in[2] = dco2_filter.in[3] = 0.0; + + ++useCount; + dco1.phase = 0.0; + dco2.phase = 0.0; + lfo.phase = 0.0; + + memset(controller, 0, sizeof(controller)); + + int maxval = 128*128-1; + + setController(0, DCO1_PITCHMOD, 8191); + setController(0, DCO2_PITCHMOD, 8191); + setController(0, DCO1_WAVEFORM, 1); + setController(0, DCO2_WAVEFORM, 1); + setController(0, DCO1_FM, 0); + setController(0, DCO2_FM, 0); + setController(0, DCO1_PWM, 0); + setController(0, DCO2_PWM, 0); + setController(0, DCO1_ATTACK, 0); + setController(0, DCO2_ATTACK, 0); + setController(0, DCO1_DECAY, 0); + setController(0, DCO2_DECAY, 0); + setController(0, DCO1_SUSTAIN, maxval - 255); + setController(0, DCO2_SUSTAIN, maxval - 255); + setController(0, DCO1_RELEASE, 0); + setController(0, DCO2_RELEASE, 0); + setController(0, LFO_FREQ, 0); + setController(0, LFO_WAVEFORM, 0); + setController(0, FILT_ENV_MOD, 0); + setController(0, FILT_KEYTRACK, 0); + setController(0, FILT_RES, 0); + setController(0, FILT_ATTACK, 0); + setController(0, FILT_DECAY, 0); + setController(0, FILT_SUSTAIN, maxval); + setController(0, FILT_RELEASE, 3); + setController(0, DCO2ON, 0); + setController(0, FILT_INVERT, 0); + setController(0, FILT_CUTOFF, 15000); + setController(0, DCO1_DETUNE, 8191); + setController(0, DCO2_DETUNE, 8191); + setController(0, DCO1_PW, 0); + setController(0, DCO2_PW, 0); + + isOn = false; + return false; + } + +//--------------------------------------------------------- +// processMessages +// Called from host always, even if output path is unconnected. +//--------------------------------------------------------- + +void VAM::processMessages() +{ + //Process messages from the gui + // + // get and process all pending events from the + // synthesizer GUI + // + while (gui->fifoSize()) + { + MidiPlayEvent ev = gui->readEvent(); + if (ev.type() == ME_CONTROLLER) + { + // process local? + setController(ev.dataA() & 0xfff, ev.dataB()); + sendEvent(ev); + } + else + printf("VAM::process(): unknown event\n"); + } +} + +//--------------------------------------------------------- +// process +// Called from host, ONLY if output path is connected. +//--------------------------------------------------------- + +void VAM::process(float** ports, int offset, int sampleCount) + { + /* + // + // get and process all pending events from the + // synthesizer GUI + // + while (gui->fifoSize()) { + MidiPlayEvent ev = gui->readEvent(); + if (ev.type() == ME_CONTROLLER) { + // process local? + setController(ev.dataA() & 0xfff, ev.dataB()); + sendEvent(ev); + } + else + printf("VAM::process(): unknown event\n"); + } + */ + + float* buffer = *ports + offset; + if (!isOn) + return; + + float sample, osc, lfol, *dco1_tbl, *dco2_tbl, *lfo_tbl, pw; + float cutoff; + int sr = sampleRate(); + + dco1_tbl = wave_tbl(dco1.waveform); + dco2_tbl = wave_tbl(dco2.waveform); + lfo_tbl = wave_tbl(lfo.waveform); + + cutoff = filt_keytrack ? (dco1.freq /500.0 + filt_cutoff)/2 : filt_cutoff; + cutoff = LIMIT(cutoff, 0.0, 1.0); + + for (int i = 0; i < sampleCount; i++) { + if(!(dco1_env.step() + dco2_env.step())) { + isOn = false; + break; + } + filt_env.step(); + + /* DCO 1 */ + lfol = lfo_tbl[(int)lfo.phase]; + pw = dco1.pw + dco1.pwm * lfol * 0.5; + pw = LIMIT(pw, 0.0, 1.0); + if(dco1.phase < sr/2 * ( 1.0 - pw)) + osc = dco1_tbl[int(dco1.phase / (1.0 - pw))]; + else + osc = dco1_tbl[int(dco1.phase / (1.0 + pw))]; + lfol = lfo_tbl[(int)lfo.phase]; + dco1.phase += dco1.freq + dco1.fm * lfol * 1500.0; + lfo.phase += lfo.freq * 50.0; + if(!filt_invert) + sample = lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * filt_env.env)) + + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco1_filter) * cb2amp(960.0 * (1.0 - dco1_env.env)); + else + sample = lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * (1.0 - filt_env.env))) + + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco1_filter) * cb2amp(960.0 * (1.0 - dco1_env.env)); + while(dco1.phase > sr) + dco1.phase -= sr; + while(dco1.phase < 0.0) + dco1.phase += sr; + + /* DCO 2 */ + if(dco2.on) { + pw = dco2.pw + dco2.pwm * lfol * 0.5; + pw = LIMIT(pw, 0.0, 1.0); + if(dco2.phase < sr/2 * (1 - pw)) + osc = dco2_tbl[int(dco2.phase / (1.0 - pw))]; + else + osc = dco2_tbl[int(dco2.phase / (1.0 + pw))]; + dco2.phase += dco2.freq + dco2.fm * lfol * 1500.0; + if(!filt_invert) + sample += lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * filt_env.env)) + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco2_filter) * cb2amp(960.0 * (1.0 - dco2_env.env)); + else sample += lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * (1.0 - filt_env.env))) + 1.0 - filt_env_mod) + * cutoff, filt_res, osc, &dco2_filter) * cb2amp(960.0 * (1.0 - dco2_env.env)); + + while (dco2.phase > sr) dco2.phase -= sr; + while (dco2.phase < 0.0) dco2.phase += sr; + } + while(lfo.phase > sr) + lfo.phase -= sr; + while(lfo.phase < 0.0) + lfo.phase += sr; + sample *= velocity * 0.5; + sample = LIMIT(sample, -1.0, 1.0); + + //if(sample > 1.0) fprintf(stderr, "oooops %f\n", sample); + buffer[i] = sample; + } + } + +//--------------------------------------------------------- +// note +//--------------------------------------------------------- + +void VAM::note(int chan, int newpitch, int velo) + { + if (velo == 0) { + noteoff(chan, newpitch); + return; + } + isOn = true; + channel = chan; + pitch = newpitch; + velocity = velo / 127.0; + dco1.freq = 8.176 * exp(float(pitch + dco1.pitchmod + dco1.detune)*log(2.0)/12.0); + dco2.freq = 8.176 * exp(float(pitch + dco2.pitchmod + dco2.detune)*log(2.0)/12.0); + keytrack_cutoff = 16.0 * dco1.freq / sampleRate(); + if(keytrack_cutoff > 1.0) keytrack_cutoff = 1.0; + dco1_env.setSegment(0, dco1_env.attack, 1.0/dco1_env.attack); + dco1_env.setSegment(1, dco1_env.decay, -((1.0-dco1_env.sustain)/dco1_env.decay)); + dco2_env.setSegment(0, dco2_env.attack, 1.0/dco2_env.attack); + dco2_env.setSegment(1, dco2_env.decay, -((1.0-dco2_env.sustain)/dco2_env.decay)); + filt_env.setSegment(0, filt_env.attack, 1.0/filt_env.attack); + filt_env.setSegment(1, filt_env.decay, -((1.0-filt_env.sustain)/filt_env.decay)); + dco1_env.keyOn(); + dco2_env.keyOn(); + filt_env.env = 0.0; + filt_env.keyOn(); + // dco1.phase = 0.0; + // dco2.phase = 0.0; + // lfo.phase = 0.0; + } + +//--------------------------------------------------------- +// noteoff +//--------------------------------------------------------- + +void VAM::noteoff(int chan, int offpitch) + { + if(isOn && (pitch == offpitch) && (channel == chan)) { + dco1_env.keyOff(); + dco2_env.keyOff(); + filt_env.keyOff(); + } + } + +int VAM::getControllerInfo(int id, const char** name, int* controller, + int* min, int* max, int* initval) const + { + return gui->getControllerInfo(id, name, controller, min, max, initval); + } + +//--------------------------------------------------------- +// setController +//--------------------------------------------------------- + +bool VAM::setController(int /*channel*/, int ctrl, int data) + { + setController(ctrl & 0xfff, data); + MidiPlayEvent ev(0, 0, channel, ME_CONTROLLER, ctrl, data); + gui->writeEvent(ev); + return false; + } + +void VAM::setController(int ctrl, int data) + { + // fprintf(stderr, "ctrl: %d data: %d\n", ctrl, data); + int maxval = 128*128-1; + double normval = double(data) / double(maxval); + switch (ctrl) { + case DCO1_PITCHMOD: + dco1.pitchmod = (data - 8191) / 341.333; + break; + case DCO1_WAVEFORM: + dco1.waveform = data; + break; + case DCO1_FM: + dco1.fm = lin2exp[int(normval * 255.0)]; + break; + case DCO1_PWM: + dco1.pwm = normval; + break; + case DCO1_ATTACK: + dco1_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()) + 1; + break; + case DCO1_DECAY: + dco1_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case DCO1_SUSTAIN: + dco1_env.sustain = normval; + break; + case DCO1_RELEASE: + dco1_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + dco1_env.setSegment(2, dco1_env.release, -(1.0/dco1_env.release)); + break; + + case DCO2_PITCHMOD: + dco2.pitchmod = (data - 8191) / 341.333; + break; + case DCO2_WAVEFORM: + dco2.waveform = data; + break; + case DCO2_FM: + dco2.fm = normval; + break; + case DCO2_PWM: + dco2.pwm = normval; + break; + case DCO2_ATTACK: + dco2_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()) + 1; + break; + case DCO2_DECAY: + dco2_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case DCO2_SUSTAIN: + dco2_env.sustain = normval; + break; + case DCO2_RELEASE: + dco2_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + dco2_env.setSegment(2, dco2_env.release, -(1.0/dco2_env.release)); + break; + case LFO_FREQ: + lfo.freq = lin2exp[int(normval * 255.0)]; + //fprintf(stderr, "%f\n", lfo.freq); + break; + case LFO_WAVEFORM: + lfo.waveform = data; + break; + case FILT_ENV_MOD: + filt_env_mod = 1.0 - lin2exp[int(255.0 - normval * 255.0)]; + break; + case FILT_KEYTRACK: + filt_keytrack = data; + break; + case FILT_RES: + filt_res = normval; + break; + case FILT_ATTACK: + //filt_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()); + filt_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()) + 1; + break; + case FILT_DECAY: + filt_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case FILT_SUSTAIN: + filt_env.sustain = normval; + break; + case FILT_RELEASE: + filt_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + filt_env.setSegment(2, filt_env.release, -(1.0/filt_env.release)); + break; + case DCO2ON: + dco2.on = data; + break; + case FILT_INVERT: + filt_invert = data; + break; + case FILT_CUTOFF: + filt_cutoff = normval; + //fprintf(stderr, "%f\n", filt_cutoff); + break; + case DCO1_DETUNE: + dco1.detune = (data - 8191) / 16384.0; + break; + case DCO2_DETUNE: + dco2.detune = (data - 8191) / 16384.0; + break; + case DCO1_PW: + dco1.pw = normval; + if(dco1.pw == 1.0) + dco1.pw = 0.99; + break; + case DCO2_PW: + dco2.pw = normval; + if(dco2.pw == 1.0) dco2.pw = 0.99; + break; + default: + printf("VAM: set unknown Ctrl 0x%x to 0x%x\n", ctrl, data); + break; + } + controller[ctrl] = data; + } + +//--------------------------------------------------------- +// getInitData +//--------------------------------------------------------- + +void VAM::getInitData(int* n, const unsigned char**p) const + { + //int i;//prevent of compiler warning: unused variable + int* d = idata; + //int maxval = 128*128-1; //prevent of compiler warning: unused variable + *n = NUM_CONTROLLER * sizeof(int); + +// // setController(0, DCO1_PITCHMOD, p++); +// *d++ = int(dco1.pitchmod+8191*341.333); + *d++ = gui->getController(DCO1_PITCHMOD); + +// // setController(0, DCO2_PITCHMOD, p++); +// *d++ = int(dco2.pitchmod+8191*341.333); + *d++ = gui->getController(DCO2_PITCHMOD); + +// // setController(0, DCO1_WAVEFORM, p++); +// *d++ = dco1.waveform; + *d++ = gui->getController(DCO1_WAVEFORM); + +// // setController(0, DCO2_WAVEFORM, p++); +// *d++ = dco2.waveform; + *d++ = gui->getController(DCO2_WAVEFORM); + +// // setController(0, DCO1_FM, p++); +// for (i = 0;igetController(DCO1_FM); + +// +// +// // setController(0, DCO2_FM, p++); +// for (i = 0;igetController(DCO2_FM); + +// +// // setController(0, DCO1_PWM, p++); +// *d++ = int(dco1.pwm*double(maxval)); + *d++ = gui->getController(DCO1_PWM); + +// +// // setController(0, DCO2_PWM, p++); +// *d++ = int(dco2.pwm*double(maxval)); + *d++ = gui->getController(DCO2_PWM); + +// +// // setController(0, DCO1_ATTACK, p++); +// for (i = 0;igetController(DCO1_ATTACK); +// +// // setController(0, DCO2_ATTACK, p++); +// for (i = 0;igetController(DCO2_ATTACK); + +// +// // setController(0, DCO1_DECAY, p++); +// *d++ = int((dco1_env.decay-1)/sampleRate()/5 * maxval); + *d++ = gui->getController(DCO1_DECAY); + +// +// // setController(0, DCO2_DECAY, p++); +// *d++ = int((dco2_env.decay-1)/sampleRate()/5 * maxval); + *d++ = gui->getController(DCO2_DECAY); + +// +// // setController(0, DCO1_SUSTAIN, p++ ); +// *d++ = int(dco1_env.sustain*double(maxval)); + *d++ = gui->getController(DCO1_SUSTAIN); + +// +// // setController(0, DCO2_SUSTAIN, p++ ); +// *d++ = int(dco2_env.sustain*double(maxval)); + *d++ = gui->getController(DCO2_SUSTAIN); +// +// // setController(0, DCO1_RELEASE, p++); +// for (i = 0;igetController(DCO1_RELEASE); + +// +// // setController(0, DCO2_RELEASE, p++); +// for (i = 0;igetController(DCO2_RELEASE); + +// +// // setController(0, LFO_FREQ, p++); +// for (i = 0;igetController(LFO_FREQ); + +// +// // setController(0, LFO_WAVEFORM, p++); +// *d++ = lfo.waveform; + *d++ = gui->getController(LFO_WAVEFORM); + +// +// // setController(0, FILT_ENV_MOD, p++); +// for (i = 0;igetController(FILT_ENV_MOD); + +// +// // setController(0, FILT_KEYTRACK, p++); +// *d++ = filt_keytrack; + *d++ = gui->getController(FILT_KEYTRACK); + +// +// // setController(0, FILT_RES, p++); +// *d++ = int(filt_res*double(maxval)); + *d++ = gui->getController(FILT_RES); + +// +// // setController(0, FILT_ATTACK, p++); +// for (i = 0;igetController(FILT_ATTACK); + +// +// // setController(0, FILT_DECAY, p++); +// *d++ = int((filt_env.decay-1)/sampleRate()*double(maxval)/5); + *d++ = gui->getController(FILT_DECAY); + +// +// // setController(0, FILT_SUSTAIN, p++); +// *d++ = int(filt_env.sustain*double(maxval)); + *d++ = gui->getController(FILT_SUSTAIN); + +// +// // setController(0, FILT_RELEASE, p++); +// for (i = 0;igetController(FILT_RELEASE); + +// +// // setController(0, DCO2ON, p++); +// *d++ = dco2.on; + *d++ = gui->getController(DCO2ON); + +// +// // setController(0, FILT_INVERT, p++); +// *d++ = filt_invert; + *d++ = gui->getController(FILT_INVERT); + +// +// // setController(0, FILT_CUTOFF, p++); +// *d++ = int(filt_cutoff*double(maxval)); + *d++ = gui->getController(FILT_CUTOFF); + +// +// // setController(0, DCO1_DETUNE, p++); +// *d++ = int(dco1.detune *16834 + 8191); + *d++ = gui->getController(DCO1_DETUNE); + +// +// // setController(0, DCO2_DETUNE, p++); +// *d++ = int(dco2.detune *16834 + 8191); + *d++ = gui->getController(DCO2_DETUNE); + +// +// // setController(0, DCO1_PW, p++); +// *d++ = int(dco1.pw*double(maxval)); + *d++ = gui->getController(DCO1_PW); + +// +// // setController(0, DCO2_PW, p++); +// *d++ = int(dco2.pw*double(maxval)); + *d++ = gui->getController(DCO2_PW); + + *p = (unsigned char*)idata; + } + +//--------------------------------------------------------- +// sysex +//--------------------------------------------------------- + +bool VAM::sysex(int n, const unsigned char* data) + { + n=n; // remove warning of unused variable + int *p= (int*)data; + setController(0, DCO1_PITCHMOD, *p++); + setController(0, DCO2_PITCHMOD, *p++); + setController(0, DCO1_WAVEFORM, *p++); + setController(0, DCO2_WAVEFORM, *p++); + setController(0, DCO1_FM, *p++); + setController(0, DCO2_FM, *p++); + setController(0, DCO1_PWM, *p++); + setController(0, DCO2_PWM, *p++); + setController(0, DCO1_ATTACK, *p++); + setController(0, DCO2_ATTACK, *p++); + setController(0, DCO1_DECAY, *p++); + setController(0, DCO2_DECAY, *p++); + setController(0, DCO1_SUSTAIN, *p++ ); + setController(0, DCO2_SUSTAIN, *p++ ); + setController(0, DCO1_RELEASE, *p++); + setController(0, DCO2_RELEASE, *p++); + setController(0, LFO_FREQ, *p++); + setController(0, LFO_WAVEFORM, *p++); + setController(0, FILT_ENV_MOD, *p++); + setController(0, FILT_KEYTRACK, *p++); + setController(0, FILT_RES, *p++); + setController(0, FILT_ATTACK, *p++); + setController(0, FILT_DECAY, *p++); + setController(0, FILT_SUSTAIN, *p++); + setController(0, FILT_RELEASE, *p++); + setController(0, DCO2ON, *p++); + setController(0, FILT_INVERT, *p++); + setController(0, FILT_CUTOFF, *p++); + setController(0, DCO1_DETUNE, *p++); + setController(0, DCO2_DETUNE, *p++); + setController(0, DCO1_PW, *p++); + setController(0, DCO2_PW, *p++); + + return false; + } + +//--------------------------------------------------------- +// guiVisible +//--------------------------------------------------------- + +bool VAM::guiVisible() const + { + return gui->isVisible(); + } + +//--------------------------------------------------------- +// showGui +//--------------------------------------------------------- + +void VAM::showGui(bool val) + { + gui->setVisible(val); + } + +//--------------------------------------------------------- +// getGeometry +//--------------------------------------------------------- + +void VAM::getGeometry(int* x, int* y, int* w, int* h) const + { + QPoint pos(gui->pos()); + QSize size(gui->size()); + *x = pos.x(); + *y = pos.y(); + *w = size.width(); + *h = size.height(); + } + +//--------------------------------------------------------- +// setGeometry +//--------------------------------------------------------- + +void VAM::setGeometry(int x, int y, int w, int h) + { + gui->resize(QSize(w, h)); + gui->move(QPoint(x, y)); + } + +//--------------------------------------------------------- +// inst +//--------------------------------------------------------- + +class QWidget; + +static Mess* instantiate(int sr, QWidget*, QString*, const char* name) + { + VAM* vam = new VAM(sr); + if (vam->init(name)) { + delete vam; + return 0; + } + return vam; + } + +extern "C" { + static MESS descriptor = { + "vam", + "vam soft synth", + "0.1", // version string + MESS_MAJOR_VERSION, MESS_MINOR_VERSION, + instantiate, + }; + // We must compile with -fvisibility=hidden to avoid namespace + // conflicts with global variables. + // Only visible symbol is "mess_descriptor". + // (TODO: all plugins should be compiled this way) + + __attribute__ ((visibility("default"))) + const MESS* mess_descriptor() { return &descriptor; } + } + diff --git a/attic/muse2-oom/muse2/synti/vam/vam.h b/attic/muse2-oom/muse2/synti/vam/vam.h new file mode 100644 index 00000000..3da27e79 --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/vam.h @@ -0,0 +1,38 @@ +// vam.h +// +// (C) Copyright 2002 Jotsif Lindman H�nlund (jotsif@linux.nu) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA or point your web browser to http://www.gnu.org. + + +#ifndef __VAM_H +#define __VAM_H + +enum { + DCO1_PITCHMOD, DCO1_WAVEFORM, DCO1_FM, DCO1_PWM, + DCO1_ATTACK, DCO1_DECAY, DCO1_SUSTAIN, DCO1_RELEASE, + DCO2_PITCHMOD, DCO2_WAVEFORM, DCO2_FM, DCO2_PWM, + DCO2_ATTACK, DCO2_DECAY, DCO2_SUSTAIN, DCO2_RELEASE, + LFO_FREQ, LFO_WAVEFORM, FILT_ENV_MOD, FILT_KEYTRACK, + FILT_RES, FILT_ATTACK, FILT_DECAY, FILT_SUSTAIN, + FILT_RELEASE, DCO2ON, FILT_INVERT, FILT_CUTOFF, + DCO1_DETUNE, DCO2_DETUNE, DCO1_PW, DCO2_PW +}; + + +#define NUM_CONTROLLER 32 + +#endif /* __VAM_H */ diff --git a/attic/muse2-oom/muse2/synti/vam/vamgui.cpp b/attic/muse2-oom/muse2/synti/vam/vamgui.cpp new file mode 100644 index 00000000..50b6552c --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/vamgui.cpp @@ -0,0 +1,724 @@ +//========================================================= +// MusE +// Linux Music Editor +// +// vamgui.c +// This is a simple GUI implemented with QT for +// vam software synthesizer. +// (Many) parts of this file was taken from Werner Schweer's GUI +// for his organ soft synth. +// +// (C) Copyright 2002 Jotsif Lindman H�nlund (jotsif@linux.nu) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA or point your web browser to http://www.gnu.org. +//========================================================= + +#include +#include +#include + +#include + +#include "vamgui.h" +#include "vam.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "muse/globals.h" +#include "muse/xml.h" +#include "muse/midi.h" +#include "muse/midictrl.h" +#include "muse/icons.h" + +const char *vam_ctrl_names[] = { + "DCO1_PITCHMOD", "DCO1_WAVEFORM", "DCO1_FM", "DCO1_PWM", + "DCO1_ATTACK", "DCO1_DECAY", "DCO1_SUSTAIN", "DCO1_RELEASE", + "DCO2_PITCHMOD", "DCO2_WAVEFORM", "DCO2_FM", "DCO2_PWM", + "DCO2_ATTACK", "DCO2_DECAY", "DCO2_SUSTAIN", "DCO2_RELEASE", + "LFO_FREQ", "LFO_WAVEFORM", "FILT_ENV_MOD", "FILT_KEYTRACK", + "FILT_RES", "FILT_ATTACK", "FILT_DECAY", "FILT_SUSTAIN", + "FILT_RELEASE", "DCO2ON", "FILT_INVERT", "FILT_CUTOFF", + "DCO1_DETUNE", "DCO2_DETUNE", "DCO1_PW", "DCO2_PW" +}; + +//--------------------------------------------------------- +// Preset +//--------------------------------------------------------- + +struct Preset { + QString name; + int ctrl[NUM_CONTROLLER]; + void readConfiguration(Xml& xml); + void readControl(Xml& xml); + void writeConfiguration(Xml& xml, int level); + }; + +std::list presets; +typedef std::list::iterator iPreset; + +// Removed by T356 +//QString museProject; +//QString museGlobalShare; +//QString museUser; +//QString instanceName; + +// char* presetFileTypes[] = { +// "Presets (*.pre)", +// 0 +// }; + +//--------------------------------------------------------- +// readControl +//--------------------------------------------------------- + +void Preset::readControl(Xml& xml) +{ + int idx = 0; + int val = 0; + for (;;) { + Xml::Token token(xml.parse()); + const QString& tag(xml.s1()); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + xml.unknown("control"); + break; + case Xml::Attribut: + if (tag == "idx") { + idx = xml.s2().toInt(); + if (idx >= NUM_CONTROLLER) + idx = 0; + } + else if (tag == "val") + val = xml.s2().toInt(); + break; + case Xml::TagEnd: + if (tag == "control") { + ctrl[idx] = val; + return; + } + default: + break; + } + } +} + +//--------------------------------------------------------- +// readConfiguration +//--------------------------------------------------------- + +void Preset::readConfiguration(Xml& xml) +{ + for (;;) { + Xml::Token token(xml.parse()); + const QString& tag(xml.s1()); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "control") + readControl(xml); + else + xml.unknown("preset"); + break; + case Xml::Attribut: + if (tag == "name") + name = xml.s2(); + break; + case Xml::TagEnd: + if (tag == "preset") + return; + default: + break; + } + } +} + +//--------------------------------------------------------- +// writeConfiguration +//--------------------------------------------------------- + +void Preset::writeConfiguration(Xml& xml, int level) +{ + //xml.tag(level++, "preset name=\"%s\"", name.ascii()); + xml.tag(level++, "preset name=\"%s\"", Xml::xmlString(name).toAscii().constData()); + for (int i = 0; i < NUM_CONTROLLER; ++i) { + xml.tag(level, "control idx=\"%d\" val=\"%d\" /", i, ctrl[i]); + } + xml.tag(level--, "/preset"); +} + +//--------------------------------------------------------- +// VAMGui +//--------------------------------------------------------- + +VAMGui::VAMGui() + : QWidget(0, Qt::Window), + MessGui() +{ + setupUi(this); + QSocketNotifier* s = new QSocketNotifier(readFd, QSocketNotifier::Read); + connect(s, SIGNAL(activated(int)), SLOT(readMessage(int))); + + loadPresets->setIcon(QIcon(*openIcon)); + savePresets->setIcon(QIcon(*saveIcon)); + savePresetsToFile->setIcon(QIcon(*saveasIcon)); + deletePreset->setIcon(QIcon(*deleteIcon)); + + dctrl[DCO1_PITCHMOD] = SynthGuiCtrl(PitchModS, LCDNumber1, SynthGuiCtrl::SLIDER); + dctrl[DCO1_WAVEFORM] = SynthGuiCtrl(Waveform, 0, SynthGuiCtrl::COMBOBOX); + dctrl[DCO1_FM] = SynthGuiCtrl(FMS, LCDNumber1_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_PWM] = SynthGuiCtrl(PWMS, LCDNumber1_3, SynthGuiCtrl::SLIDER); + dctrl[DCO1_ATTACK] = SynthGuiCtrl(AttackS, LCDNumber1_3_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_DECAY] = SynthGuiCtrl(DecayS, LCDNumber1_3_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_SUSTAIN] = SynthGuiCtrl(SustainS, LCDNumber1_3_2_3, SynthGuiCtrl::SLIDER); + dctrl[DCO1_RELEASE] = SynthGuiCtrl(ReleaseS, LCDNumber1_3_2_4, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PITCHMOD] = SynthGuiCtrl(PitchModS2, LCDNumber1_4, SynthGuiCtrl::SLIDER); + dctrl[DCO2_WAVEFORM] = SynthGuiCtrl(Waveform2, 0, SynthGuiCtrl::COMBOBOX); + dctrl[DCO2_FM] = SynthGuiCtrl(FMS2, LCDNumber1_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PWM] = SynthGuiCtrl(PWMS2, LCDNumber1_3_3, SynthGuiCtrl::SLIDER); + dctrl[DCO2_ATTACK] = SynthGuiCtrl(AttackS2, LCDNumber1_3_2_5, SynthGuiCtrl::SLIDER); + dctrl[DCO2_DECAY] = SynthGuiCtrl(DecayS2, LCDNumber1_3_2_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_SUSTAIN] = SynthGuiCtrl(SustainS2, LCDNumber1_3_2_3_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_RELEASE] = SynthGuiCtrl(ReleaseS2, LCDNumber1_3_2_4_2, SynthGuiCtrl::SLIDER); + dctrl[LFO_FREQ] = SynthGuiCtrl(FreqS, LCDNumber1_5, SynthGuiCtrl::SLIDER); + dctrl[LFO_WAVEFORM] = SynthGuiCtrl(Waveform2_2, 0, SynthGuiCtrl::COMBOBOX); + dctrl[FILT_ENV_MOD] = SynthGuiCtrl(EnvModS, LCDNumber1_5_3, SynthGuiCtrl::SLIDER); + dctrl[FILT_KEYTRACK] = SynthGuiCtrl(KeyTrack, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_RES] = SynthGuiCtrl(ResS, LCDNumber1_5_5, SynthGuiCtrl::SLIDER); + dctrl[FILT_ATTACK] = SynthGuiCtrl(AttackS3, LCDNumber1_3_2_5_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_DECAY] = SynthGuiCtrl(DecayS3, LCDNumber1_3_2_2_2_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_SUSTAIN] = SynthGuiCtrl(SustainS3, LCDNumber1_3_2_3_2_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_RELEASE] = SynthGuiCtrl(ReleaseS3, LCDNumber1_3_2_4_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2ON] = SynthGuiCtrl(DCO2On, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_INVERT] = SynthGuiCtrl(FilterInvert, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_CUTOFF] = SynthGuiCtrl(CutoffS, LCDNumber1_5_5_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_DETUNE] = SynthGuiCtrl(DetuneS, LCDNumber1_6, SynthGuiCtrl::SLIDER); + dctrl[DCO2_DETUNE] = SynthGuiCtrl(DetuneS2, LCDNumber1_6_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_PW] = SynthGuiCtrl(PWS, LCDNumber1_2_3, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PW] = SynthGuiCtrl(PWS2, LCDNumber1_2_4, SynthGuiCtrl::SLIDER); + + + map = new QSignalMapper(this); + for (int i = 0; i < NUM_CONTROLLER; ++i) { + map->setMapping(dctrl[i].editor, i); + if (dctrl[i].type == SynthGuiCtrl::SLIDER) + connect((QSlider*)(dctrl[i].editor), SIGNAL(valueChanged(int)), map, SLOT(map())); + else if (dctrl[i].type == SynthGuiCtrl::COMBOBOX) + connect((QComboBox*)(dctrl[i].editor), SIGNAL(activated(int)), map, SLOT(map())); + else if (dctrl[i].type == SynthGuiCtrl::SWITCH) + connect((QCheckBox*)(dctrl[i].editor), SIGNAL(toggled(bool)), map, SLOT(map())); + } + connect(map, SIGNAL(mapped(int)), this, SLOT(ctrlChanged(int))); + + connect(presetList, SIGNAL(itemClicked(QListWidgetItem*)), + this, SLOT(presetClicked(QListWidgetItem*))); + // presetNameEdit + connect(presetSet, SIGNAL(clicked()), this, SLOT(setPreset())); + connect(savePresets, SIGNAL(clicked()), this, SLOT(savePresetsPressed())); + connect(loadPresets, SIGNAL(clicked()), this, SLOT(loadPresetsPressed())); + connect(deletePreset, SIGNAL(clicked()), this, SLOT(deletePresetPressed())); + connect(savePresetsToFile, SIGNAL(clicked()), this, SLOT(savePresetsToFilePressed())); + + ctrlHi = 0; + ctrlLo = 0; + dataHi = 0; + dataLo = 0; + presetFileName = NULL; + + // work around for probable QT/WM interaction bug. + // for certain window managers, e.g xfce, this window is + // is displayed although not specifically set to show(); + // bug: 2811156 Softsynth GUI unclosable with XFCE4 (and a few others) + show(); + hide(); + } + +//--------------------------------------------------------- +// ctrlChanged +//--------------------------------------------------------- + +void VAMGui::ctrlChanged(int idx) + { + SynthGuiCtrl* ctrl = &dctrl[idx]; + int val = 0; + if (ctrl->type == SynthGuiCtrl::SLIDER) { + QSlider* slider = (QSlider*)(ctrl->editor); + int max = slider->maximum(); + val = (slider->value() * 16383 + max/2) / max; + } + else if (ctrl->type == SynthGuiCtrl::COMBOBOX) { + val = ((QComboBox*)(ctrl->editor))->currentIndex(); + } + else if (ctrl->type == SynthGuiCtrl::SWITCH) { + val = ((QCheckBox*)(ctrl->editor))->isChecked(); + } + sendController(0, idx + CTRL_RPN14_OFFSET, val); + } + +int VAMGui::getController(int idx) + { + SynthGuiCtrl* ctrl = &dctrl[idx]; + int val = 0; + if (ctrl->type == SynthGuiCtrl::SLIDER) { + QSlider* slider = (QSlider*)(ctrl->editor); + int max = slider->maximum(); + val = (slider->value() * 16383 + max/2) / max; + } + else if (ctrl->type == SynthGuiCtrl::COMBOBOX) { + val = ((QComboBox*)(ctrl->editor))->currentIndex(); + } + else if (ctrl->type == SynthGuiCtrl::SWITCH) { + val = ((QCheckBox*)(ctrl->editor))->isChecked(); + } + return val; + } + +int VAMGui::getControllerInfo(int id, const char** name, int* controller, + int* min, int* max, int* /*initval*/) const + { + if (id >= NUM_CONTROLLER) + return 0; + + + *controller = id; + *name = vam_ctrl_names[id]; + const SynthGuiCtrl* ctrl = (const SynthGuiCtrl*)&dctrl[id]; + //int val = 0; + if (ctrl->type == SynthGuiCtrl::SLIDER) { + QSlider* slider = (QSlider*)(ctrl->editor); + *max = 16383; //slider->maximum(); + *min = slider->minimum(); + //val = (slider->value() * 16383 + max/2) / max; + + //val = 16383 + 1/2 + } + else if (ctrl->type == SynthGuiCtrl::COMBOBOX) { + //val = ((QComboBox*)(ctrl->editor))->currentIndex(); + *min = 0; + *max = ((QComboBox*)(ctrl->editor))->count(); + } + else if (ctrl->type == SynthGuiCtrl::SWITCH) { + //val = ((QCheckBox*)(ctrl->editor))->isChecked(); + *min=0; + *max=1; + } + return ++id; + } + +//--------------------------------------------------------- +// presetClicked +//--------------------------------------------------------- + +void VAMGui::presetClicked(QListWidgetItem* item) +{ + if (item == 0) + return; + presetNameEdit->setText(item->text()); + Preset* preset = 0; + for (iPreset i = presets.begin(); i != presets.end(); ++i) { + if (i->name == item->text()) { + preset = &*i; + break; + } + } + activatePreset(preset); +} + +//--------------------------------------------------------- +// activatePreset +//--------------------------------------------------------- + +void VAMGui::activatePreset(Preset* preset) +{ + if (preset == 0) { + fprintf(stderr, "internal error 1\n"); + exit(-1); + } + for (unsigned int i = 0; i < sizeof(dctrl)/sizeof(*dctrl); ++i) { + setParam(i, preset->ctrl[i]); + ctrlChanged(i); + } +} + +//--------------------------------------------------------- +// setPreset +//--------------------------------------------------------- + +void VAMGui::setPreset() +{ + if (presetNameEdit->text().isEmpty()) + return; + for (iPreset i = presets.begin(); i != presets.end(); ++i) { + if (i->name == presetNameEdit->text()) { + setPreset(&*i); + return; + } + } + addNewPreset(presetNameEdit->text()); +} + +//--------------------------------------------------------- +// addNewPreset +//--------------------------------------------------------- + +void VAMGui::addNewPreset(const QString& name) +{ + Preset p; + p.name = name; + setPreset(&p); + presets.push_back(p); + presetList->addItem(name); +} + +//--------------------------------------------------------- +// deleteNamedPreset +//--------------------------------------------------------- +void VAMGui::deleteNamedPreset(const QString& name) +{ + QListWidgetItem * item = presetList->findItems(name, Qt::MatchExactly)[0]; + if (!item) { + fprintf(stderr, "%s: Could not find preset!\n", __FUNCTION__); + return; + } + presetList->clearSelection(); + int index = presetList->row(item); + presetList->takeItem(index); + for (iPreset i = presets.begin(); i != presets.end(); ++i) { + if (i->name == name) { + presets.erase(i); + break; + } + } +} + + +//--------------------------------------------------------- +// setPreset +//--------------------------------------------------------- + +void VAMGui::setPreset(Preset* preset) +{ + for (unsigned int i = 0; i < NUM_CONTROLLER; ++i) { + int val = 0; + SynthGuiCtrl* ctrl = &dctrl[i]; + if (ctrl->type == SynthGuiCtrl::SLIDER) { + QSlider* slider = (QSlider*)(ctrl->editor); + int max = slider->maximum(); + val = (slider->value() * 16383 + max/2) / max; + } + else if (ctrl->type == SynthGuiCtrl::COMBOBOX) { + val = ((QComboBox*)(ctrl->editor))->currentIndex(); + } + else if (ctrl->type == SynthGuiCtrl::SWITCH) { + val = ((QCheckBox*)(ctrl->editor))->isChecked(); + } + + preset->ctrl[i] = val; + } + // + // send sysex to synti + // +#if 0 + putchar(0xf0); + putchar(0x7c); // mess + putchar(0x2); // vam + putchar(0x3); // setPreset + QByteArray ba = preset->name.toLatin1(); + const char* name = ba.constData(); + while (*name) + putchar(*name++ & 0x7f); + putchar(0); + for (int i = 0; i < NUM_CONTROLLER; ++i) { + putchar(i); + putchar(preset->ctrl[i]); + } + putchar(0xf7); +#endif +} + +//--------------------------------------------------------- +// setParam +// set param in gui +// val -- midi value 0 - 16383 +//--------------------------------------------------------- + +void VAMGui::setParam(int param, int val) + { + if (param >= int(sizeof(dctrl)/sizeof(*dctrl))) { + fprintf(stderr, "vam: set unknown parameter 0x%x to 0x%x\n", param, val); + return; + } + SynthGuiCtrl* ctrl = &dctrl[param]; + ctrl->editor->blockSignals(true); + if (ctrl->type == SynthGuiCtrl::SLIDER) { + QSlider* slider = (QSlider*)(ctrl->editor); + int max = slider->maximum(); + if(val < 0) val = (val * max + 8191) / 16383 - 1; + else val = (val * max + 8191) / 16383; + + slider->setValue(val); + if (ctrl->label) + ((QLCDNumber*)(ctrl->label))->display(val); + } + else if (ctrl->type == SynthGuiCtrl::COMBOBOX) { + ((QComboBox*)(ctrl->editor))->setCurrentIndex(val); + } + else if (ctrl->type == SynthGuiCtrl::SWITCH) { + ((QCheckBox*)(ctrl->editor))->setChecked(val); + } + ctrl->editor->blockSignals(false); + } + +//--------------------------------------------------------- +// sysexReceived +//--------------------------------------------------------- + +void VAMGui::sysexReceived(const unsigned char* data, int len) +{ + if (len >= 4) { + //--------------------------------------------- + // MusE Soft Synth + //--------------------------------------------- + + if (data[0] == 0x7c) { + if (data[1] == 2) { // vam + if (data[2] == 2) { // parameter response + if (len != 6) { + fprintf(stderr, "vam gui: bad sysEx len\n"); + return; + } + int val = data[4] + (data[5]<<7); + switch(data[3]) + { + case DCO1_PITCHMOD: + case DCO2_PITCHMOD: + case DCO1_DETUNE: + case DCO2_DETUNE: + setParam(data[3], ((val + 1) * 2) - 16383); + break; + default: + setParam(data[3], val); + break; + } + return; + } + else if (data[2] == 1) { // param request + return; + } + } + } + } + fprintf(stderr, "vam gui: unknown sysex received, len %d:\n", len); + for (int i = 0; i < len; ++i) + fprintf(stderr, "%02x ", data[i]); + fprintf(stderr, "\n"); +} + +//--------------------------------------------------------- +// processEvent +//--------------------------------------------------------- + +void VAMGui::processEvent(const MidiPlayEvent& ev) + { + if (ev.type() == ME_CONTROLLER) + setParam(ev.dataA() & 0xfff, ev.dataB()); + else if (ev.type() == ME_SYSEX) + sysexReceived(ev.data(), ev.len()) + ; + else + printf("VAMGui::illegal event type received\n"); + } + +//--------------------------------------------------------- +// loadPresetsPressed +//--------------------------------------------------------- + +void VAMGui::loadPresetsPressed() +{ +#if 1 // TODO + QString iname; + QString s(configPath); + +/* QString filename = QFileDialog::getOpenFileName(lastdir, QString("*.[Ss][Ff]2"), + this, + "Load Soundfont dialog", + "Choose soundfont");*/ + QString fn = QFileDialog::getOpenFileName(this, tr("MusE: Load VAM Presets"), + s, "Presets (*.vam)"); + + if (fn.isEmpty()) + return; + bool popenFlag=false; + FILE* f = fopen(fn.toAscii().constData(),"r");//fileOpen(this, fn, QString(".pre"), "r", popenFlag, true); + if (f == 0) + return; + presets.clear(); + presetList->clear(); + + Xml xml(f); + int mode = 0; + for (;;) { + Xml::Token token = xml.parse(); + QString tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (mode == 0 && tag == "muse") + mode = 1; +// else if (mode == 1 && tag == "instrument") +// mode = 2; + + else if (mode == 2 && tag == "preset") { + Preset preset; + preset.readConfiguration(xml); + presets.push_back(preset); + presetList->addItem(preset.name); + } + else if(mode != 1) + xml.unknown("SynthPreset"); + break; + case Xml::Attribut: + if(mode == 1 && tag == "iname") { +// fprintf(stderr, "%s\n", xml.s2().toLatin1()); + if(xml.s2() != "vam-1.0") + return; + else mode = 2; + } + break; + case Xml::TagEnd: + if (tag == "muse") + goto ende; + default: + break; + } + } +ende: + if (popenFlag) + pclose(f); + else + fclose(f); + + if (presetFileName) delete presetFileName; + presetFileName = new QString(fn); + QString dots ("..."); + fileName->setText(fn.right(32).insert(0, dots)); + + if (presets.empty()) + return; + Preset preset = presets.front(); + activatePreset(&preset); +#endif +} + +//--------------------------------------------------------- +// doSavePresets +//--------------------------------------------------------- +void VAMGui::doSavePresets(const QString& fn, bool showWarning) +{ + showWarning=showWarning; // prevent of unsused variable warning +#if 1 + bool popenFlag=false; + if (fn=="") { + printf("empty name\n"); + return; + } + printf("fn=%s\n",fn.toAscii().constData()); + FILE* f = fopen(fn.toAscii().constData(),"w");//fileOpen(this, fn, QString(".pre"), "w", popenFlag, false, showWarning); + if (f == 0) + return; + Xml xml(f); + xml.header(); + xml.tag(0, "muse version=\"1.0\""); + xml.tag(0, "instrument iname=\"vam-1.0\" /"); + + for (iPreset i = presets.begin(); i != presets.end(); ++i) + i->writeConfiguration(xml, 1); + + xml.tag(1, "/muse"); + + if (popenFlag) + pclose(f); + else + fclose(f); +#endif +} + +//--------------------------------------------------------- +// savePresetsPressed +//--------------------------------------------------------- + +void VAMGui::savePresetsPressed() +{ +#if 1 // TODO + QString s(configPath); + QString fn = QFileDialog::getSaveFileName(this, tr("MusE: Save VAM Presets"), + s, "Presets (*.vam)"); + if (fn.isEmpty()) + return; + doSavePresets (fn, true); +#endif +} + + +//--------------------------------------------------------- +// savePresetsToFilePressed +//--------------------------------------------------------- + +void VAMGui::savePresetsToFilePressed() +{ + if (!presetFileName ) { + + QString s(configPath); + QString fn = QFileDialog::getSaveFileName(this, tr("MusE: Save VAM Presets"), + s, "Presets (*.vam)"); + presetFileName = new QString(fn); + } + if (*presetFileName == QString("")) + return; + //if presetFileName-> + doSavePresets (*presetFileName, false); +} + +//--------------------------------------------------------- +// deletePresetPressed +//--------------------------------------------------------- + +void VAMGui::deletePresetPressed() +{ + deleteNamedPreset (presetList->currentItem()->text()); +} + +//--------------------------------------------------------- +// readMessage +//--------------------------------------------------------- + +void VAMGui::readMessage(int) + { + MessGui::readMessage(); + } + diff --git a/attic/muse2-oom/muse2/synti/vam/vamgui.h b/attic/muse2-oom/muse2/synti/vam/vamgui.h new file mode 100644 index 00000000..2271c8aa --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/vamgui.h @@ -0,0 +1,82 @@ +//========================================================= +// MusE +// Linux Music Editor +// vamgui.h +// +// (C) Copyright 2002 Jotsif Lindman H�nlund (jotsif@linux.nu) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA or point your web browser to http://www.gnu.org. +//========================================================= + +#ifndef __VAMGUI_H +#define __VAMGUI_H + +#include "ui_vamguibase.h" +#include "vam.h" +#include "libsynti/gui.h" + +class QListWidgetItem; +class Preset; +class QString; +class QSignalMapper; + +//--------------------------------------------------------- +// VAMGui +//--------------------------------------------------------- + +class VAMGui : public QWidget, public Ui::VAMGuiBase, public MessGui { + QSignalMapper* map; + int ctrlHi; + int ctrlLo; + int dataHi; + int dataLo; + SynthGuiCtrl dctrl[NUM_CONTROLLER]; + QString * presetFileName; + + Q_OBJECT + void sendControllerChange(int ctrl, int val); + void initParameter(); + void setParam(int, int); + void setPreset(Preset* preset); + void addNewPreset(const QString&); + void deleteNamedPreset(const QString&); + void activatePreset(Preset* preset); + virtual void processEvent(const MidiPlayEvent&); + + private slots: + void ctrlChanged(int idx); + + void presetClicked(QListWidgetItem*); + void setPreset(); + void loadPresetsPressed(); + void savePresetsPressed(); + void deletePresetPressed(); + void doSavePresets(const QString&, bool); + void savePresetsToFilePressed(); + void readMessage(int); + + protected: + virtual void sysexReceived(const unsigned char*, int); + + public: + int getController(int idx); + int getControllerInfo(int id, const char** name, int* controller, int* min, int* max, int* initval) const; + VAMGui(); + }; + +#endif /* __VAMGUI_H */ + + diff --git a/attic/muse2-oom/muse2/synti/vam/vamguibase.ui b/attic/muse2-oom/muse2/synti/vam/vamguibase.ui new file mode 100644 index 00000000..49867b65 --- /dev/null +++ b/attic/muse2-oom/muse2/synti/vam/vamguibase.ui @@ -0,0 +1,1974 @@ + + + VAMGuiBase + + + true + + + + 0 + 0 + 744 + 528 + + + + + 0 + 0 + + + + Virtual Analogue for MusE + + + + 11 + + + 6 + + + + + LFO + + + + 2 + + + 6 + + + + + Freq + + + false + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Waveform + + + false + + + + + + + + Sine + + + + + Pulse + + + + + Saw + + + + + Triangle + + + + + + + + + + + Filter + + + + 6 + + + 2 + + + + + EnvMod + + + false + + + + + + + Attack + + + false + + + + + + + Decay + + + false + + + + + + + Sustain + + + false + + + + + + + Release + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Cutoff + + + false + + + + + + + Resonance + + + false + + + + + + + + 0 + 0 + + + + Invert + + + + + + + + 0 + 0 + + + + KeyTrack + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 255 + + + 1 + + + Qt::Horizontal + + + QSlider::NoTicks + + + 25 + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + + + + + 0 + 0 + + + + + 200 + 32767 + + + + Presets + + + + 6 + + + 2 + + + + + + 0 + 0 + + + + + 32767 + 32767 + + + + + + + + + + + false + + + + + + + + 0 + 0 + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + + + Set + + + + + + + + 0 + 0 + + + + load preset list + + + + + + + image0image0 + + + + + + + save preset list + + + + + + + image1image1 + + + + + + + + 0 + 0 + + + + save preset list to a new file + + + + + + + image2image2 + + + + + + + delete preset + + + + + + + image3image3 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + + + 0 + 0 + + + + DCO 1 + + + + 6 + + + 2 + + + + + Pitch + + + false + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Detune + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + -50 + + + 50 + + + Qt::Horizontal + + + + + + + + 100 + 0 + + + + -24 + + + 24 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + PWM + + + false + + + + + + + Decay + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Sustain + + + false + + + + + + + Release + + + false + + + + + + + Attack + + + false + + + + + + + FM + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + PW + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + Waveform + + + false + + + + + + + + 0 + 0 + + + + + Sine + + + + + Pulse + + + + + Saw + + + + + Triangle + + + + + + + + + + + + 0 + 0 + + + + DCO 2 + + + + 6 + + + 2 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 100 + 0 + + + + -24 + + + 24 + + + Qt::Horizontal + + + + + + + FM + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Detune + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Pitch + + + false + + + + + + + -50 + + + 50 + + + Qt::Horizontal + + + + + + + Waveform + + + false + + + + + + + + 0 + 0 + + + + + Sine + + + + + Pulse + + + + + Saw + + + + + Triangle + + + + + + + + Release + + + false + + + + + + + PWM + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Attack + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Decay + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + Sustain + + + false + + + + + + + + 0 + 0 + + + + 3 + + + QLCDNumber::Flat + + + + + + + PW + + + false + + + + + + + On + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + 255 + + + 1 + + + Qt::Horizontal + + + + + + + + + + VAM 1.0beta3 +Virtual Analog for MusE +Released under GPL. +Copyright(C) 2002 +Jotsif Lindman Hörnlund +( jotsif@linux.nu ) +Copyright(C) 2005 +Robert Jonsson +(rj@spamatica.se) + + + Qt::AlignCenter + + + false + + + + + + + + + + PitchModS + valueChanged(int) + LCDNumber1 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + FMS + valueChanged(int) + LCDNumber1_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + PWMS + valueChanged(int) + LCDNumber1_3 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + AttackS + valueChanged(int) + LCDNumber1_3_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + DecayS + valueChanged(int) + LCDNumber1_3_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + SustainS + valueChanged(int) + LCDNumber1_3_2_3 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + ReleaseS + valueChanged(int) + LCDNumber1_3_2_4 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + FreqS + valueChanged(int) + LCDNumber1_5 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + FMS2 + valueChanged(int) + LCDNumber1_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + PWMS2 + valueChanged(int) + LCDNumber1_3_3 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + AttackS2 + valueChanged(int) + LCDNumber1_3_2_5 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + SustainS2 + valueChanged(int) + LCDNumber1_3_2_3_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + ReleaseS2 + valueChanged(int) + LCDNumber1_3_2_4_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + ResS + valueChanged(int) + LCDNumber1_5_5 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + EnvModS + valueChanged(int) + LCDNumber1_5_3 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + AttackS3 + valueChanged(int) + LCDNumber1_3_2_5_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + DecayS3 + valueChanged(int) + LCDNumber1_3_2_2_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + SustainS3 + valueChanged(int) + LCDNumber1_3_2_3_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + ReleaseS3 + valueChanged(int) + LCDNumber1_3_2_4_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + PitchModS2 + valueChanged(int) + LCDNumber1_4 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + DecayS2 + valueChanged(int) + LCDNumber1_3_2_2_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + CutoffS + valueChanged(int) + LCDNumber1_5_5_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + DetuneS + valueChanged(int) + LCDNumber1_6 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + DetuneS2 + valueChanged(int) + LCDNumber1_6_2 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + PWS + valueChanged(int) + LCDNumber1_2_3 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + PWS2 + valueChanged(int) + LCDNumber1_2_4 + display(int) + + + 20 + 20 + + + 20 + 20 + + + + + -- cgit v1.2.3