1 /*
2  *  mdaJX10Processor.cpp
3  *  mda-vst3
4  *
5  *  Created by Arne Scheffler on 6/14/08.
6  *
7  *  mda VST Plug-ins
8  *
9  *  Copyright (c) 2008 Paul Kellett
10  *
11  *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14  *
15  */
16 
17 #include "mdaJX10Processor.h"
18 #include "mdaJX10Controller.h"
19 
20 #include <cmath>
21 
22 namespace Steinberg {
23 namespace Vst {
24 namespace mda {
25 
26 #define NPARAMS  24      //number of parameters
27 #define SILENCE  0.001f  //voice choking
28 #define PI       3.1415926535897932f
29 #define TWOPI    6.2831853071795864f
30 #define ANALOG   0.002f  //oscillator drift
31 
32 float JX10Processor::programParams[kNumPrograms][NPARAMS] = {
33 	{1.0f, 0.37f, 0.25f, 0.3f, 0.32f, 0.5f, 0.9f, 0.6f, 0.12f, 0.0f, 0.5f, 0.9f, 0.89f, 0.9f, 0.73f, 0.0f, 0.5f, 1.0f, 0.71f, 0.81f, 0.65f, 0.0f, 0.5f, 0.5f},
34 	{0.88f, 0.51f, 0.5f, 0.0f, 0.49f, 0.5f, 0.46f, 0.76f, 0.69f, 0.1f, 0.69f, 1.0f, 0.86f, 0.76f, 0.57f, 0.3f, 0.8f, 0.68f, 0.66f, 0.79f, 0.13f, 0.25f, 0.45f, 0.5f},
35 	{0.88f, 0.51f, 0.5f, 0.16f, 0.49f, 0.5f, 0.49f, 0.82f, 0.66f, 0.08f, 0.89f, 0.85f, 0.69f, 0.76f, 0.47f, 0.12f, 0.22f, 0.55f, 0.66f, 0.89f, 0.34f, 0.0f, 1.0f, 0.5f},
36 	{1.0f, 0.26f, 0.14f, 0.0f, 0.35f, 0.5f, 0.3f, 0.25f, 0.7f, 0.0f, 0.63f, 0.0f, 0.35f, 0.0f, 0.25f, 0.0f, 0.5f, 1.0f, 0.3f, 0.81f, 0.5f, 0.5f, 0.5f, 0.5f},
37 	{0.41f, 0.5f, 0.79f, 0.0f, 0.08f, 0.32f, 0.49f, 0.01f, 0.34f, 0.0f, 0.93f, 0.61f, 0.87f, 1.0f, 0.93f, 0.11f, 0.48f, 0.98f, 0.32f, 0.81f, 0.5f, 0.0f, 0.5f, 0.5f},
38 	{0.29f, 0.76f, 0.26f, 0.0f, 0.18f, 0.76f, 0.35f, 0.15f, 0.77f, 0.14f, 0.54f, 0.0f, 0.42f, 0.13f, 0.21f, 0.0f, 0.56f, 0.0f, 0.32f, 0.2f, 0.58f, 0.22f, 0.53f, 0.5f},
39 	{1.0f, 0.65f, 0.24f, 0.4f, 0.34f, 0.85f, 0.65f, 0.63f, 0.75f, 0.16f, 0.5f, 0.0f, 0.3f, 0.0f, 0.25f, 0.17f, 0.5f, 1.0f, 0.03f, 0.81f, 0.5f, 0.0f, 0.68f, 0.5f},
40 	{0.0f, 0.25f, 0.5f, 1.0f, 0.46f, 0.5f, 0.51f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.3f, 0.0f, 0.25f, 0.37f, 0.5f, 1.0f, 0.38f, 0.81f, 0.62f, 0.0f, 0.5f, 0.5f},
41 	{0.84f, 0.51f, 0.15f, 0.45f, 0.41f, 0.42f, 0.54f, 0.01f, 0.58f, 0.21f, 0.67f, 0.0f, 0.09f, 1.0f, 0.25f, 0.2f, 0.85f, 1.0f, 0.3f, 0.83f, 0.09f, 0.4f, 0.49f, 0.5f},
42 	{0.71f, 0.75f, 0.53f, 0.18f, 0.24f, 1.0f, 0.56f, 0.52f, 0.69f, 0.19f, 0.7f, 1.0f, 0.14f, 0.65f, 0.95f, 0.07f, 0.91f, 1.0f, 0.15f, 0.84f, 0.33f, 0.0f, 0.49f, 0.5f},
43 	{0.0f, 0.25f, 0.43f, 0.0f, 0.71f, 0.48f, 0.23f, 0.77f, 0.8f, 0.32f, 0.63f, 0.4f, 0.18f, 0.66f, 0.14f, 0.0f, 0.38f, 0.65f, 0.16f, 0.48f, 0.5f, 0.0f, 0.67f, 0.5f},
44 	{0.62f, 0.26f, 0.51f, 0.79f, 0.35f, 0.54f, 0.64f, 0.39f, 0.51f, 0.65f, 0.0f, 0.07f, 0.52f, 0.24f, 0.84f, 0.13f, 0.3f, 0.76f, 0.21f, 0.58f, 0.3f, 0.0f, 0.36f, 0.5f},
45 	{0.81f, 1.0f, 0.21f, 0.78f, 0.15f, 0.35f, 0.39f, 0.17f, 0.69f, 0.4f, 0.62f, 0.0f, 0.47f, 0.19f, 0.37f, 0.0f, 0.5f, 0.2f, 0.33f, 0.38f, 0.53f, 0.0f, 0.12f, 0.5f},
46 	{0.0f, 0.51f, 0.52f, 0.96f, 0.44f, 0.5f, 0.41f, 0.46f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.25f, 0.15f, 0.5f, 1.0f, 0.32f, 0.81f, 0.49f, 0.0f, 0.83f, 0.5f},
47 	{0.48f, 0.51f, 0.22f, 0.0f, 0.0f, 0.5f, 0.5f, 0.47f, 0.73f, 0.3f, 0.8f, 0.0f, 0.1f, 0.0f, 0.07f, 0.0f, 0.42f, 0.0f, 0.22f, 0.21f, 0.59f, 0.16f, 0.98f, 0.5f},
48 	{0.0f, 0.51f, 0.5f, 0.83f, 0.49f, 0.5f, 0.55f, 0.75f, 0.69f, 0.35f, 0.5f, 0.0f, 0.56f, 0.0f, 0.56f, 0.0f, 0.8f, 1.0f, 0.24f, 0.26f, 0.49f, 0.0f, 0.07f, 0.5f},
49 	{0.75f, 0.51f, 0.5f, 0.83f, 0.49f, 0.5f, 0.55f, 0.75f, 0.69f, 0.35f, 0.5f, 0.14f, 0.49f, 0.0f, 0.39f, 0.0f, 0.8f, 1.0f, 0.24f, 0.26f, 0.49f, 0.0f, 0.07f, 0.5f},
50 	{1.0f, 0.25f, 0.2f, 0.81f, 0.19f, 0.5f, 0.3f, 0.51f, 0.85f, 0.09f, 0.0f, 0.0f, 0.88f, 0.0f, 0.21f, 0.0f, 0.5f, 1.0f, 0.46f, 0.81f, 0.5f, 0.0f, 0.27f, 0.5f},
51 	{1.0f, 0.25f, 0.2f, 0.72f, 0.19f, 0.86f, 0.48f, 0.43f, 0.94f, 0.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.61f, 1.0f, 0.32f, 0.81f, 0.5f, 0.0f, 0.27f, 0.5f},
52 	{0.97f, 0.26f, 0.3f, 0.0f, 0.35f, 0.5f, 0.8f, 0.4f, 0.52f, 0.0f, 0.5f, 0.0f, 0.77f, 0.0f, 0.25f, 0.0f, 0.5f, 1.0f, 0.3f, 0.81f, 0.16f, 0.0f, 0.0f, 0.5f},
53 	{0.0f, 0.25f, 0.5f, 0.65f, 0.35f, 0.5f, 0.33f, 0.76f, 0.53f, 0.0f, 0.5f, 0.0f, 0.3f, 0.0f, 0.25f, 0.0f, 0.55f, 0.25f, 0.3f, 0.81f, 0.52f, 0.0f, 0.14f, 0.5f},
54 	{1.0f, 0.26f, 0.22f, 0.64f, 0.82f, 0.59f, 0.72f, 0.47f, 0.34f, 0.34f, 0.82f, 0.2f, 0.69f, 1.0f, 0.15f, 0.09f, 0.5f, 1.0f, 0.07f, 0.81f, 0.46f, 0.0f, 0.24f, 0.5f},
55 	{1.0f, 0.26f, 0.22f, 0.71f, 0.35f, 0.5f, 0.67f, 0.7f, 0.26f, 0.0f, 0.5f, 0.48f, 0.69f, 1.0f, 0.15f, 0.0f, 0.5f, 1.0f, 0.07f, 0.81f, 0.46f, 0.0f, 0.24f, 0.5f},
56 	{0.49f, 0.25f, 0.66f, 0.81f, 0.35f, 0.5f, 0.36f, 0.15f, 0.75f, 0.2f, 0.5f, 0.0f, 0.38f, 0.0f, 0.25f, 0.0f, 0.6f, 1.0f, 0.22f, 0.19f, 0.5f, 0.0f, 0.17f, 0.5f},
57 	{0.37f, 0.51f, 0.77f, 0.71f, 0.22f, 0.5f, 0.33f, 0.47f, 0.71f, 0.16f, 0.59f, 0.0f, 0.0f, 0.0f, 0.25f, 0.04f, 0.58f, 0.0f, 0.22f, 0.15f, 0.44f, 0.33f, 0.15f, 0.5f},
58 	{0.5f, 0.51f, 0.17f, 0.8f, 0.34f, 0.5f, 0.51f, 0.0f, 0.58f, 0.0f, 0.67f, 0.0f, 0.09f, 0.0f, 0.25f, 0.2f, 0.85f, 0.0f, 0.3f, 0.81f, 0.7f, 0.0f, 0.0f, 0.5f},
59 	{0.23f, 0.51f, 0.38f, 0.0f, 0.35f, 0.5f, 0.33f, 1.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.29f, 0.0f, 0.25f, 0.68f, 0.39f, 0.58f, 0.36f, 0.81f, 0.64f, 0.38f, 0.92f, 0.5f},
60 	{0.39f, 0.51f, 0.27f, 0.38f, 0.12f, 0.5f, 0.35f, 0.78f, 0.5f, 0.0f, 0.5f, 0.0f, 0.3f, 0.0f, 0.25f, 0.35f, 0.5f, 0.8f, 0.7f, 0.81f, 0.5f, 0.0f, 0.5f, 0.5f},
61 	{0.0f, 0.25f, 0.5f, 0.0f, 0.35f, 0.5f, 0.23f, 0.2f, 0.75f, 0.0f, 0.5f, 0.0f, 0.22f, 0.0f, 0.25f, 0.0f, 0.47f, 0.0f, 0.3f, 0.81f, 0.5f, 0.8f, 0.5f, 0.5f},
62 	{1.0f, 0.51f, 0.24f, 0.0f, 0.0f, 0.35f, 0.42f, 0.26f, 0.75f, 0.14f, 0.69f, 0.0f, 0.67f, 0.55f, 0.97f, 0.82f, 0.7f, 1.0f, 0.42f, 0.84f, 0.67f, 0.3f, 0.47f, 0.5f},
63 	{0.75f, 0.51f, 0.29f, 0.0f, 0.49f, 0.5f, 0.55f, 0.16f, 0.69f, 0.08f, 0.2f, 0.76f, 0.29f, 0.76f, 1.0f, 0.46f, 0.8f, 1.0f, 0.39f, 0.79f, 0.27f, 0.0f, 0.68f, 0.5f},
64 	{0.0f, 0.5f, 0.53f, 0.0f, 0.13f, 0.39f, 0.38f, 0.74f, 0.54f, 0.2f, 0.0f, 0.0f, 0.55f, 0.52f, 0.31f, 0.0f, 0.17f, 0.73f, 0.28f, 0.87f, 0.24f, 0.0f, 0.29f, 0.5f},
65 	{0.5f, 0.77f, 0.52f, 0.0f, 0.35f, 0.5f, 0.44f, 0.5f, 0.65f, 0.16f, 0.0f, 0.0f, 0.0f, 0.18f, 0.0f, 0.0f, 0.75f, 0.8f, 0.0f, 0.81f, 0.49f, 0.0f, 0.44f, 0.5f},
66 	{0.89f, 0.91f, 0.37f, 0.0f, 0.35f, 0.5f, 0.51f, 0.62f, 0.54f, 0.0f, 0.0f, 0.0f, 0.37f, 0.0f, 1.0f, 0.04f, 0.08f, 0.72f, 0.04f, 0.77f, 0.49f, 0.0f, 0.58f, 0.5f},
67 	{1.0f, 0.51f, 0.51f, 0.37f, 0.0f, 0.5f, 0.51f, 0.1f, 0.5f, 0.11f, 0.5f, 0.0f, 0.0f, 0.0f, 0.25f, 0.35f, 0.65f, 0.65f, 0.32f, 0.79f, 0.49f, 0.2f, 0.35f, 0.5f},
68 	{0.0f, 0.51f, 0.51f, 0.82f, 0.06f, 0.5f, 0.57f, 0.0f, 0.32f, 0.15f, 0.5f, 0.21f, 0.15f, 0.0f, 0.25f, 0.24f, 0.6f, 0.8f, 0.1f, 0.75f, 0.55f, 0.25f, 0.69f, 0.5f},
69 	{0.12f, 0.9f, 0.67f, 0.0f, 0.35f, 0.5f, 0.5f, 0.21f, 0.29f, 0.12f, 0.6f, 0.0f, 0.35f, 0.36f, 0.25f, 0.08f, 0.5f, 1.0f, 0.27f, 0.83f, 0.51f, 0.1f, 0.25f, 0.5f},
70 	{0.43f, 0.76f, 0.23f, 0.0f, 0.28f, 0.36f, 0.5f, 0.0f, 0.59f, 0.0f, 0.5f, 0.24f, 0.16f, 0.91f, 0.08f, 0.17f, 0.5f, 0.8f, 0.45f, 0.81f, 0.5f, 0.0f, 0.58f, 0.5f},
71 	{0.4f, 0.51f, 0.25f, 0.0f, 0.3f, 0.28f, 0.39f, 0.15f, 0.75f, 0.0f, 0.5f, 0.39f, 0.3f, 0.82f, 0.25f, 0.33f, 0.74f, 0.76f, 0.41f, 0.81f, 0.47f, 0.23f, 0.5f, 0.5f},
72 	{0.68f, 0.5f, 0.93f, 0.0f, 0.31f, 0.62f, 0.26f, 0.07f, 0.85f, 0.0f, 0.66f, 0.0f, 0.83f, 0.0f, 0.05f, 0.0f, 0.75f, 0.54f, 0.32f, 0.76f, 0.37f, 0.29f, 0.56f, 0.5f},
73 	{1.0f, 0.27f, 0.22f, 0.0f, 0.35f, 0.5f, 0.82f, 0.13f, 0.75f, 0.0f, 0.0f, 0.24f, 0.3f, 0.88f, 0.34f, 0.0f, 0.5f, 1.0f, 0.48f, 0.71f, 0.37f, 0.0f, 0.35f, 0.5f},
74 	{0.76f, 0.51f, 0.35f, 0.0f, 0.49f, 0.5f, 0.87f, 0.67f, 1.0f, 0.32f, 0.09f, 0.95f, 0.56f, 0.72f, 1.0f, 0.04f, 0.76f, 0.11f, 0.46f, 0.88f, 0.72f, 0.0f, 0.38f, 0.5f},
75 	{0.75f, 0.51f, 0.24f, 0.45f, 0.16f, 0.48f, 0.38f, 0.58f, 0.75f, 0.16f, 0.81f, 0.0f, 0.3f, 0.4f, 0.31f, 0.37f, 0.5f, 1.0f, 0.54f, 0.85f, 0.83f, 0.43f, 0.46f, 0.5f},
76 	{0.31f, 0.51f, 0.43f, 0.0f, 0.35f, 0.5f, 0.34f, 0.26f, 0.53f, 0.0f, 0.63f, 0.0f, 0.22f, 0.0f, 0.39f, 0.0f, 0.8f, 0.0f, 0.44f, 0.81f, 0.51f, 0.0f, 0.5f, 0.5f},
77 	{0.72f, 0.82f, 1.0f, 0.0f, 0.35f, 0.5f, 0.37f, 0.47f, 0.54f, 0.0f, 0.5f, 0.0f, 0.45f, 0.0f, 0.39f, 0.0f, 0.39f, 0.0f, 0.48f, 0.81f, 0.6f, 0.0f, 0.71f, 0.5f},
78 	{0.81f, 0.76f, 0.19f, 0.0f, 0.18f, 0.7f, 0.4f, 0.3f, 0.54f, 0.17f, 0.4f, 0.0f, 0.42f, 0.23f, 0.47f, 0.12f, 0.48f, 0.0f, 0.49f, 0.53f, 0.36f, 0.34f, 0.56f, 0.5f},
79 	{0.57f, 0.49f, 0.31f, 0.0f, 0.35f, 0.5f, 0.46f, 0.0f, 0.68f, 0.0f, 0.5f, 0.46f, 0.3f, 1.0f, 0.23f, 0.3f, 0.5f, 1.0f, 0.31f, 1.0f, 0.38f, 0.0f, 0.5f, 0.5f},
80 	{0.0f, 0.25f, 0.5f, 0.0f, 0.35f, 0.5f, 0.08f, 0.36f, 0.69f, 1.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.96f, 0.5f, 1.0f, 0.92f, 0.97f, 0.5f, 1.0f, 0.0f, 0.5f},
81 	{0.0f, 0.25f, 0.5f, 0.0f, 0.35f, 0.5f, 0.16f, 0.85f, 0.5f, 0.28f, 0.5f, 0.37f, 0.3f, 0.0f, 0.25f, 0.89f, 0.5f, 1.0f, 0.89f, 0.24f, 0.5f, 1.0f, 1.0f, 0.5f},
82 	{1.0f, 0.37f, 0.51f, 0.0f, 0.35f, 0.5f, 0.0f, 1.0f, 0.97f, 0.0f, 0.5f, 0.02f, 0.2f, 0.0f, 0.2f, 0.0f, 0.46f, 0.0f, 0.3f, 0.81f, 0.5f, 0.78f, 0.48f, 0.5f},
83 	{0.0f, 0.25f, 0.5f, 0.0f, 0.76f, 0.94f, 0.3f, 0.33f, 0.76f, 0.0f, 0.68f, 0.0f, 0.59f, 0.0f, 0.59f, 0.1f, 0.5f, 0.0f, 0.5f, 0.81f, 0.5f, 0.7f, 0.0f, 0.5f},
84 	{0.5f, 0.41f, 0.23f, 0.45f, 0.77f, 0.0f, 0.4f, 0.65f, 0.95f, 0.0f, 0.5f, 0.33f, 0.5f, 0.0f, 0.25f, 0.0f, 0.7f, 0.65f, 0.18f, 0.32f, 1.0f, 0.0f, 0.06f, 0.5f},
85 };
86 
87 #ifdef SMTG_MDA_VST2_COMPATIBILITY
88 //-----------------------------------------------------------------------------
89 FUID JX10Processor::uid (0x5653544D, 0x44416A6D, 0x6461206A, 0x78313000);
90 #else
91 //-----------------------------------------------------------------------------
92 FUID JX10Processor::uid (0x82CD49DE, 0x13D743BA, 0xABDAC299, 0x1CE06F7C);
93 #endif
94 
95 //-----------------------------------------------------------------------------
JX10Processor()96 JX10Processor::JX10Processor ()
97 : currentProgram (0)
98 {
99 	setControllerClass (JX10Controller::uid);
100 	allocParameters (NPARAMS);
101 }
102 
103 //-----------------------------------------------------------------------------
~JX10Processor()104 JX10Processor::~JX10Processor ()
105 {
106 }
107 
108 //-----------------------------------------------------------------------------
initialize(FUnknown * context)109 tresult PLUGIN_API JX10Processor::initialize (FUnknown* context)
110 {
111 	tresult res = BaseProcessor::initialize (context);
112 	if (res == kResultTrue)
113 	{
114 		addEventInput (USTRING("MIDI in"), 1);
115 		addAudioOutput (USTRING("Stereo Out"), SpeakerArr::kStereo);
116 
117 		const float* newParams = programParams[0];
118 		if (newParams)
119 		{
120 			for (int32 i = 0; i < NPARAMS; i++)
121 				params[i] = newParams[i];
122 		}
123 
124 		//initialise...
125 		for(int32 v=0; v<NVOICES; v++)
126 		{
127 			memset (&voice[v], 0, sizeof (VOICE));
128 			voice[v].dp   = voice[v].dp2   = 1.0f;
129 			voice[v].saw  = voice[v].p     = voice[v].p2    = 0.0f;
130 			voice[v].env  = voice[v].envd  = voice[v].envl  = 0.0f;
131 			voice[v].fenv = voice[v].fenvd = voice[v].fenvl = 0.0f;
132 			voice[v].f0   = voice[v].f1    = voice[v].f2    = 0.0f;
133 			voice[v].note = 0;
134 		}
135 		notes[0] = EVENTS_DONE;
136 		lfo = modwhl = filtwhl = press = fzip = 0.0f;
137 		rezwhl = pbend = ipbend = 1.0f;
138 		volume = 0.0005f;
139 		K = mode = lastnote = sustain = activevoices = 0;
140 		noise = 22222;
141 
142 		recalculate ();
143 	}
144 	return res;
145 }
146 
147 //-----------------------------------------------------------------------------
terminate()148 tresult PLUGIN_API JX10Processor::terminate ()
149 {
150 	return BaseProcessor::terminate ();
151 }
152 
153 //-----------------------------------------------------------------------------
setActive(TBool state)154 tresult PLUGIN_API JX10Processor::setActive (TBool state)
155 {
156 	if (state)
157 		recalculate ();
158 
159 	return BaseProcessor::setActive (state);
160 }
161 
162 //-----------------------------------------------------------------------------
setParameter(ParamID index,ParamValue newValue,int32 sampleOffset)163 void JX10Processor::setParameter (ParamID index, ParamValue newValue, int32 sampleOffset)
164 {
165 	if (index < NPARAMS)
166 		BaseProcessor::setParameter (index, newValue, sampleOffset);
167 	else if (index == BaseController::kPresetParam) // program change
168 	{
169 		currentProgram = std::min<int32> (kNumPrograms - 1, (int32)(newValue * kNumPrograms));
170 		const float* newParams = programParams[currentProgram];
171 		if (newParams)
172 		{
173 			for (int32 i = 0; i < NPARAMS; i++)
174 				params[i] = newParams[i];
175 		}
176 	}
177 	else if (index == BaseController::kModWheelParam) // mod wheel
178 	{
179 		newValue *= 127.;
180 		modwhl = 0.000005f * (newValue*newValue);
181 	}
182 	else if (index == BaseController::kPitchBendParam) // pitch bend
183 	{
184 		if (newValue <= 1)
185 			newValue = (newValue - 0.5) * 0x2000;
186 		ipbend = (float)exp (0.000014102 * (double)newValue);
187 		pbend = 1.0f / ipbend;
188 	}
189 	else if (index == BaseController::kBreathParam)
190 	{
191 		newValue *= 127.;
192 		filtwhl = 0.02f * newValue;
193 	}
194 	else if (index == BaseController::kCtrler3Param)
195 	{
196 		newValue *= 127.;
197 		filtwhl = -0.03f * newValue;
198 	}
199 	else if (index == BaseController::kExpressionParam)
200 	{
201 		newValue *= 127.;
202 		rezwhl = 0.0065f * (float)(154 - newValue);
203 	}
204 	else if (index == BaseController::kAftertouchParam)
205 	{
206 		newValue *= 127.;
207 		press = 0.00001f * (float)(newValue * newValue);
208 	}
209 }
210 
211 //-----------------------------------------------------------------------------
setCurrentProgram(Steinberg::uint32 val)212 void JX10Processor::setCurrentProgram (Steinberg::uint32 val)
213 {
214 	currentProgram = val;
215 }
216 
217 //-----------------------------------------------------------------------------
setCurrentProgramNormalized(ParamValue val)218 void JX10Processor::setCurrentProgramNormalized (ParamValue val)
219 {
220 	setCurrentProgram (std::min<int32> (kNumPrograms - 1, (int32)(val * kNumPrograms)));
221 }
222 
223 //-----------------------------------------------------------------------------
doProcessing(ProcessData & data)224 void JX10Processor::doProcessing (ProcessData& data)
225 {
226 	int32 sampleFrames = data.numSamples;
227 
228 	float* out1 = data.outputs[0].channelBuffers32[0];
229 	float* out2 = data.outputs[0].channelBuffers32[1];
230 
231 	int32 event=0, frame=0, frames, v;
232 	float oL, oR, e, vib, pwm, pb=pbend, ipb=ipbend, gl=glide;
233 	float x, y, hpf=0.997f, min=1.0f, w=0.0f, ww=noisemix;
234 	float ff, fe=filtenv, fq=filtq * rezwhl, fx=1.97f-0.85f*fq, fz=fzip;
235 	int32 k=K;
236 	Steinberg::uint32 r;
237 
238 	vib = (float)sin(lfo);
239 	ff = filtf + filtwhl + (filtlfo + press) * vib; //have to do again here as way that
240 	pwm = 1.0f + vib * (modwhl + pwmdep);           //below triggers on k was too cheap!
241 	vib = 1.0f + vib * (modwhl + vibrato);
242 
243 	if (activevoices>0 || notes[event]<sampleFrames)
244 	{
245 		while (frame<sampleFrames)
246 		{
247 			frames = notes[event++];
248 			if (frames>sampleFrames) frames = sampleFrames;
249 			frames -= frame;
250 			frame += frames;
251 
252 			while (--frames>=0)
253 			{
254 				VOICE *V = voice;
255 				oL = oR = 0.0f;
256 
257 				noise = (noise * 196314165) + 907633515;
258 				r = (noise & 0x7FFFFF) + 0x40000000; //generate noise + fast convert to float
259 				w = *(float *)&r;
260 				w = ww * (w - 3.0f);
261 
262 				if (--k<0)
263 				{
264 					lfo += dlfo;
265 					if (lfo>PI) lfo -= TWOPI;
266 					vib = (float)sin(lfo);
267 					ff = filtf + filtwhl + (filtlfo + press) * vib;
268 					pwm = 1.0f + vib * (modwhl + pwmdep);
269 					vib = 1.0f + vib * (modwhl + vibrato);
270 					k = KMAX;
271 				}
272 
273 				for(v=0; v<NVOICES; v++)  //for each voice
274 				{
275 					e = V->env;
276 					if (e > SILENCE)
277 					{ //Sinc-Loop Oscillator
278 						x = V->p + V->dp;
279 						if (x > min)
280 						{
281 							if (x > V->pmax)
282 							{
283 								x = V->pmax + V->pmax - x;
284 								V->dp = -V->dp;
285 							}
286 							V->p = x;
287 							x = V->sin0 * V->sinx - V->sin1; //sine osc
288 							V->sin1 = V->sin0;
289 							V->sin0 = x;
290 							x = x / V->p;
291 						}
292 						else
293 						{
294 							V->p = x = - x;
295 							V->dp = V->period * vib * pb * V->snaPitchbend; //set period for next cycle
296 							V->pmax = (float)floor(0.5f + V->dp) - 0.5f;
297 							V->dc = -0.5f * V->lev / V->pmax;
298 							V->pmax *= PI;
299 							V->dp = V->pmax / V->dp;
300 							V->sin0 = V->lev * (float)sin(x);
301 							V->sin1 = V->lev * (float)sin(x - V->dp);
302 							V->sinx = 2.0f * (float)cos(V->dp);
303 							if (x*x > .1f) x = V->sin0 / x; else x = V->lev; //was 0.01f;
304 						}
305 
306 						y = V->p2 + V->dp2; //osc2
307 						if (y > min)
308 						{
309 							if (y > V->pmax2)
310 							{
311 								y = V->pmax2 + V->pmax2 - y;
312 								V->dp2 = -V->dp2;
313 							}
314 							V->p2 = y;
315 							y = V->sin02 * V->sinx2 - V->sin12;
316 							V->sin12 = V->sin02;
317 							V->sin02 = y;
318 							y = y / V->p2;
319 						}
320 						else
321 						{
322 							V->p2 = y = - y;
323 							V->dp2 = V->period * V->detune * pwm * pb * V->snaPitchbend;
324 							V->pmax2 = (float)floor(0.5f + V->dp2) - 0.5f;
325 							V->dc2 = -0.5f * V->lev2 / V->pmax2;
326 							V->pmax2 *= PI;
327 							V->dp2 = V->pmax2 / V->dp2;
328 							V->sin02 = V->lev2 * (float)sin(y);
329 							V->sin12 = V->lev2 * (float)sin(y - V->dp2);
330 							V->sinx2 = 2.0f * (float)cos(V->dp2);
331 							if (y*y > .1f) y = V->sin02 / y; else y = V->lev2;
332 						}
333 						V->saw = V->saw * hpf + V->dc + x - V->dc2 - y;  //integrated sinc = saw
334 						x = V->saw + w;
335 						V->env += V->envd * (V->envl - V->env);
336 
337 						if (k==KMAX) //filter freq update at LFO rate
338 						{
339 							if ((V->env+V->envl)>3.0f) { V->envd=dec; V->envl=sus; } //envelopes
340 							V->fenv += V->fenvd * (V->fenvl - V->fenv);
341 							if ((V->fenv+V->fenvl)>3.0f) { V->fenvd=fdec; V->fenvl=fsus; }
342 
343 							fz += 0.005f * (ff - fz); //filter zipper noise filter
344 							y = V->fc * (float)exp (fz + fe * V->fenv) * ipb; //filter cutoff
345 							if (y<0.005f) y =0.005f;
346 							V->ff = y;
347 
348 							V->period += gl * (V->target - V->period); //glide
349 							if (V->target < V->period) V->period += gl * (V->target - V->period);
350 						}
351 
352 						if (V->ff > fx) V->ff = fx; //stability limit
353 
354 						V->f0 += V->ff * V->f1; //state-variable filter
355 						V->f1 -= V->ff * (V->f0 + fq * V->f1 - x - V->f2);
356 						V->f1 -= 0.2f * V->f1 * V->f1 * V->f1; //soft limit  //was 0.08f
357 						V->f2 = x;
358 
359 						float oneSample = V->env * V->f0 * V->snaVolume;
360 						oL += oneSample * V->snaPanLeft;
361 						oR += oneSample * V->snaPanRight;
362 					}
363 					V++;
364 				}
365 
366 				*out1++ = oL;
367 				*out2++ = oR;
368 			}
369 
370 			if (frame<sampleFrames)
371 			{
372 				int32 note = notes[event++];
373 				int32 vel  = notes[event++];
374 				int32 noteID = notes[event++];
375 				noteOn (note, vel, noteID);
376 			}
377 		}
378 
379 		activevoices = NVOICES;
380 		for(v=0; v<NVOICES; v++)
381 		{
382 			if (voice[v].env<SILENCE)  //choke voices
383 			{
384 				voice[v].env = voice[v].envl = 0.0f;
385 				voice[v].f0 = voice[v].f1 = voice[v].f2 = 0.0f;
386 				activevoices--;
387 			}
388 		}
389 	}
390 	else
391 	{
392 		// complete empty block
393 		memset (out1, 0, sampleFrames * sizeof (float));
394 		memset (out2, 0, sampleFrames * sizeof (float));
395 	}
396 	notes[0] = EVENTS_DONE;  //mark events buffer as done
397 	fzip = fz;
398 	K = k;
399 }
400 
401 //-----------------------------------------------------------------------------
processEvents(IEventList * events)402 void JX10Processor::processEvents (IEventList* events)
403 {
404 	if (events)
405 	{
406 		int32 eventPos = 0;
407 		int32 count = events->getEventCount ();
408 		for (int32 i = 0; i < count; i++)
409 		{
410 			Event e;
411 			events->getEvent (i, e);
412 			switch (e.type)
413 			{
414 				case Event::kNoteOnEvent:
415 				{
416 					notes[eventPos++] = e.sampleOffset;
417 					notes[eventPos++] = e.noteOn.pitch;
418 					notes[eventPos++] = e.noteOn.velocity * 127;
419 					notes[eventPos++] = e.noteOn.noteId;
420 					break;
421 				}
422 				case Event::kNoteOffEvent:
423 				{
424 					notes[eventPos++] = e.sampleOffset;
425 					notes[eventPos++] = e.noteOff.pitch;
426 					notes[eventPos++] = 0;
427 					notes[eventPos++] = e.noteOn.noteId;
428 					break;
429 				}
430 				default:
431 					continue;
432 			}
433 			if (eventPos > EVENTBUFFER) eventPos -= 3; //discard events if buffer full!!
434 		}
435 		notes[eventPos] = EVENTS_DONE;
436 	}
437 }
438 
439 //-----------------------------------------------------------------------------
noteOn(int32 note,int32 velocity,int32 noteID)440 void JX10Processor::noteOn (int32 note, int32 velocity, int32 noteID)
441 {
442 	float p, l=100.0f; //louder than any envelope!
443 	int32  v=0, tmp, held=0;
444 
445 	bool polyMode = (mode < 3);
446 	bool _glide = !(mode == 0 || mode == 3);
447 	bool legato = (mode == 1 || mode == 5);
448 
449 	if (velocity>0) //note on
450 	{
451 		if (veloff) velocity = 80;
452 
453 		if (!polyMode) //monophonic
454 		{
455 			if (voice[0].note > 0) //legato pitch change
456 			{
457 				for(tmp= (NVOICES-1); tmp>0; tmp--)  //queue any held notes
458 				{
459 					voice[tmp].note = voice[tmp - 1].note;
460 				}
461 				p = tune * (float)exp (-0.05776226505 * ((double)note + ANALOG * (double)v));
462 				while (p<3.0f || (p * detune)<3.0f) p += p;
463 				voice[v].target = p;
464 				if ((_glide)==0) voice[v].period = p;
465 				voice[v].fc = (float)exp (filtvel * (float)(velocity - 64)) / p;
466 				voice[v].env += SILENCE + SILENCE; ///was missed out below if returned?
467 				voice[v].note = note;
468 				voice[v].noteID = noteID;
469 				voice[v].snaVolume = 1.f;
470 				voice[v].snaPanLeft = voice[v].snaPanRight = 1.f;
471 				voice[v].snaPitchbend = 1.f;
472 				return;
473 			}
474 		}
475 		else //polyphonic
476 		{
477 			for(tmp=0; tmp<NVOICES; tmp++)  //replace quietest voice not in attack
478 			{
479 				if (voice[tmp].note > 0) held++;
480 				if (voice[tmp].env<l && voice[tmp].envl<2.0f) { l=voice[tmp].env;  v=tmp; }
481 			}
482 		}
483 		p = tune * (float)exp (-0.05776226505 * ((double)note + ANALOG * (double)v));
484 		while (p<3.0f || (p * detune)<3.0f) p += p;
485 		voice[v].target = p;
486 		voice[v].detune = detune;
487 
488 		tmp = 0;
489 		if (_glide || legato)
490 		{
491 			if ((_glide) || held) tmp = note - lastnote; //glide
492 		}
493 		voice[v].period = p * (float)pow (1.059463094359, (double)tmp - glidedisp);
494 		if (voice[v].period<3.0f) voice[v].period = 3.0f; //limit min period
495 
496 		voice[v].note = lastnote = note;
497 		voice[v].noteID = noteID;
498 
499 		voice[v].fc = (float)exp (filtvel * (float)(velocity - 64)) / p; //filter tracking
500 
501 		voice[v].lev = voltrim * volume * (0.004f * (float)((velocity + 64) * (velocity + 64)) - 8.0f);
502 		voice[v].lev2 = voice[v].lev * oscmix;
503 
504 		if (params[20]<0.5f) //force 180 deg phase difference for PWM
505 		{
506 			if (voice[v].dp>0.0f)
507 			{
508 				p = voice[v].pmax + voice[v].pmax - voice[v].p;
509 				voice[v].dp2 = -voice[v].dp;
510 			}
511 			else
512 			{
513 				p = voice[v].p;
514 				voice[v].dp2 = voice[v].dp;
515 			}
516 			voice[v].p2 = voice[v].pmax2 = p + PI * voice[v].period;
517 
518 			voice[v].dc2 = 0.0f;
519 			voice[v].sin02 = voice[v].sin12 = voice[v].sinx2 = 0.0f;
520 		}
521 
522 		if (!polyMode) //monophonic retriggering
523 		{
524 			voice[v].env += SILENCE + SILENCE;
525 		}
526 		else
527 		{
528 			//if (params[15] < 0.28f)
529 			//{
530 			//  voice[v].f0 = voice[v].f1 = voice[v].f2 = 0.0f; //reset filter
531 			//  voice[v].env = SILENCE + SILENCE;
532 			//  voice[v].fenv = 0.0f;
533 			//}
534 			//else
535 			voice[v].env += SILENCE + SILENCE; //anti-glitching trick
536 		}
537 		voice[v].envl  = 2.0f;
538 		voice[v].envd  = att;
539 		voice[v].fenvl = 2.0f;
540 		voice[v].fenvd = fatt;
541 		voice[v].snaVolume = 1.f;
542 		voice[v].snaPanLeft = voice[v].snaPanRight = 1.f;
543 		voice[v].snaPitchbend = 1.f;
544 	}
545 	else //note off
546 	{
547 		if ((!polyMode) && (voice[0].note==note)) //monophonic (and current note)
548 		{
549 			for(v= (NVOICES-1); v>0; v--)
550 			{
551 				if (voice[v].note>0) held = v; //any other notes queued?
552 			}
553 			if (held>0)
554 			{
555 				voice[v].note = voice[held].note;
556 				voice[held].note = 0;
557 
558 				p = tune * (float)exp (-0.05776226505 * ((double)voice[v].note + ANALOG * (double)v));
559 				while (p<3.0f || (p * detune)<3.0f) p += p;
560 				voice[v].target = p;
561 				if ((_glide || legato)==0) voice[v].period = p;
562 				voice[v].fc = 1.0f / p;
563 			}
564 			else
565 			{
566 				voice[v].envl  = 0.0f;
567 				voice[v].envd  = rel;
568 				voice[v].fenvl = 0.0f;
569 				voice[v].fenvd = frel;
570 				voice[v].note  = 0;
571 			}
572 		}
573 		else //polyphonic
574 		{
575 			for(v=0; v<NVOICES; v++) if (voice[v].note==note) //any voices playing that note?
576 			{
577 				if (sustain==0)
578 				{
579 					voice[v].envl  = 0.0f;
580 					voice[v].envd  = rel;
581 					voice[v].fenvl = 0.0f;
582 					voice[v].fenvd = frel;
583 					voice[v].note  = 0;
584 				}
585 				else voice[v].note = SUSTAIN;
586 			}
587 		}
588 	}
589 }
590 
591 //-----------------------------------------------------------------------------
recalculate()592 void JX10Processor::recalculate ()
593 {
594 	double ifs = 1.0 / getSampleRate ();
595 
596 	mode = std::min<int32>(5, (int32)(params[3] * 6));
597 	noisemix = params[21] * params[21];
598 	voltrim = (3.2f - params[0] - 1.5f * noisemix) * (1.5f - 0.5f * params[7]);
599 	noisemix *= 0.06f;
600 	oscmix = params[0];
601 
602 	semi = (float)floor(48.0f * params[1]) - 24.0f;
603 	cent = 15.876f * params[2] - 7.938f;
604 	cent = 0.1f * (float)floor(cent * cent * cent);
605 	detune = (float)pow (1.059463094359f, - semi - 0.01f * cent);
606 	tune = -23.376f - 2.0f * params[23] - 12.0f * (float)floor(params[22] * 4.9);
607 	tune = getSampleRate () * (float)pow (1.059463094359f, tune);
608 
609 	vibrato = pwmdep = 0.2f * (params[20] - 0.5f) * (params[20] - 0.5f);
610 	if (params[20]<0.5f) vibrato = 0.0f;
611 
612 	lfoHz = (float)exp (7.0f * params[19] - 4.0f);
613 	dlfo = lfoHz * (float)(ifs * TWOPI * KMAX);
614 
615 	filtf = 8.0f * params[6] - 1.5f;
616 	filtq  = (1.0f - params[7]) * (1.0f - params[7]); ////// + 0.02f;
617 	filtlfo = 2.5f * params[9] * params[9];
618 	filtenv = 12.0f * params[8] - 6.0f;
619 	filtvel = 0.1f * params[10] - 0.05f;
620 	if (params[10]<0.05f) { veloff = 1; filtvel = 0; } else veloff = 0;
621 
622 	att = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[15]));
623 	dec = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[16]));
624 	sus = params[17];
625 	rel = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[18]));
626 	if (params[18]<0.01f) rel = 0.1f; //extra fast release
627 
628 	ifs *= KMAX; //lower update rate...
629 
630 	fatt = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[11]));
631 	fdec = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[12]));
632 	fsus = params[13] * params[13];
633 	frel = 1.0f - (float)exp (-ifs * exp (5.5 - 7.5 * params[14]));
634 
635 	if (params[4]<0.02f) glide = 1.0f; else
636 	glide = 1.0f - (float)exp (-ifs * exp (6.0 - 7.0 * params[4]));
637 	glidedisp = (6.604f * params[5] - 3.302f);
638 	glidedisp *= glidedisp * glidedisp;
639 }
640 
641 }}} // namespaces
642 
643