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