Final AMD implementation

pull/1/head
asb2m10 10 years ago
parent c228e50f10
commit 9f8c11346e
  1. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  2. 7
      README.md
  3. 4
      Source/Dexed.h
  4. 11
      Source/PluginFx.h
  5. 9
      Source/PluginParam.cpp
  6. 19
      Source/msfa/dx7note.cc
  7. 4
      Source/msfa/env.cc
  8. 2
      Source/msfa/env.h
  9. 35
      Source/msfa/fm_core.cc
  10. 14
      Source/msfa/fm_op_kernel.cc
  11. 2
      Source/msfa/pitchenv.cc

@ -30,18 +30,15 @@ new version here but you see it in the change log, it's because this version is
(current sprint). Only officials (tested) builds are listed here. (current sprint). Only officials (tested) builds are listed here.
* Version 0.6.1 [vst win32/x64](http://le-son666.com/software/dexed/dexed-0.6.1-win.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.6.1-osx.vst.zip) * Version 0.6.1 [vst win32/x64](http://le-son666.com/software/dexed/dexed-0.6.1-win.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.6.1-osx.vst.zip)
* Version 0.6.0 [vst win32/x64](http://le-son666.com/software/dexed/dexed-0.6.0-win.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.6.0-osx.vst.zip)
* Version 0.5.1 [vst win32](http://le-son666.com/software/dexed/dexed-0.5.1-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.5.1-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.5.1-osx.vst.zip)
* Version 0.5.0 [vst win32](http://le-son666.com/software/dexed/dexed-0.5.0a-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.5.0a-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.5.0-osx.vst.zip)
Changelog Changelog
--------- ---------
#### Version 0.7.0 (current sprint) #### Version 0.7.0 (current sprint)
* Preliminary Algo 4 & 6 feedback support * Preliminary Algo 4 & 6 feedback support
* DX Engine 'Dirty DX' emulation * DX Engine 'Dirty DX' emulation
* DX Engine LFO amplitude - still buggy * DX Engine LFO amplitude
* Fixed stucked notes when programs where changed * Fixed stucked notes when programs where changed
* Fixed engine envelop wrong timing if it was not 44100Khz - still buggy * Fixed engine envelop wrong timing if it was not 44100Khz
#### Version 0.6.1 #### Version 0.6.1
* Mouse over + LFO type fix + pitch eg values * Mouse over + LFO type fix + pitch eg values

@ -24,14 +24,14 @@
void dexed_trace(const char *source, const char *fmt, ...); void dexed_trace(const char *source, const char *fmt, ...);
#ifdef DEBUG #ifdef DEBUG
#define DEXED_VERSION "0.7.0 BETA DEBUG" #define DEXED_VERSION "0.7.0a1 DEBUG"
#ifdef _MSC_VER #ifdef _MSC_VER
#define TRACE(fmt, ...) dexed_trace(__FUNCTION__,fmt,##__VA_ARGS__) #define TRACE(fmt, ...) dexed_trace(__FUNCTION__,fmt,##__VA_ARGS__)
#else #else
#define TRACE(fmt, ...) dexed_trace(__PRETTY_FUNCTION__,fmt,##__VA_ARGS__) #define TRACE(fmt, ...) dexed_trace(__PRETTY_FUNCTION__,fmt,##__VA_ARGS__)
#endif #endif
#else #else
#define DEXED_VERSION "0.7.0 BETA" #define DEXED_VERSION "0.7.0a1"
#define TRACE(fmt, ...) #define TRACE(fmt, ...)
#endif #endif

@ -21,6 +21,15 @@
#ifndef PLUGINFX_H_INCLUDED #ifndef PLUGINFX_H_INCLUDED
#define PLUGINFX_H_INCLUDED #define PLUGINFX_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class ModuleFx {
public:
virtual ~ModuleFx() {};
virtual void init(int sampleRate) = 0;
virtual void process(float *work, int sz) = 0;
};
class PluginFx { class PluginFx {
float s1,s2,s3,s4; float s1,s2,s3,s4;
float sampleRate; float sampleRate;
@ -55,6 +64,8 @@ class PluginFx {
public: public:
ScopedPointer<ModuleFx> obxdFilter;
// this is set directly by the ui / parameter // this is set directly by the ui / parameter
float uiCutoff; float uiCutoff;
float uiReso; float uiReso;

@ -141,15 +141,6 @@ float CtrlDX::getValueHost() {
void CtrlDX::setValueHost(float f) { void CtrlDX::setValueHost(float f) {
setValue((f * steps)); setValue((f * steps));
/*
DexedAudioProcessorEditor *editor = (DexedAudioProcessorEditor *) parent->getActiveEditor();
if ( editor == NULL ) {
return;
}
String msg;
msg << label << " = " << getValueDisplay();
editor->global.setParamMessage(msg);*/
} }
void CtrlDX::setValue(int v) { void CtrlDX::setValue(int v) {

@ -19,6 +19,7 @@
using namespace std; using namespace std;
#endif #endif
#include <math.h> #include <math.h>
#include <stdlib.h>
#include "synth.h" #include "synth.h"
#include "freqlut.h" #include "freqlut.h"
#include "exp2.h" #include "exp2.h"
@ -126,8 +127,10 @@ static const uint8_t pitchmodsenstab[] = {
0, 10, 20, 33, 55, 92, 153, 255 0, 10, 20, 33, 55, 92, 153, 255
}; };
static const uint8_t ampmodsenstab[] = {
0, 66, 109, 255 // 0, 66, 109, 255
static const uint32_t ampmodsenstab[] = {
0, 4342338, 7171437, 16777216
}; };
void Dx7Note::init(const char patch[156], int midinote, int velocity) { void Dx7Note::init(const char patch[156], int midinote, int velocity) {
@ -190,7 +193,7 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay,
// TODO(PG) : make this integer friendly // TODO(PG) : make this integer friendly
uint32_t pwmd = (ctrls->values_[kControllerModWheel] * 0.7874) * (1 << 24); uint32_t pwmd = (ctrls->values_[kControllerModWheel] * 0.7874) * (1 << 24);
int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23));
uint32_t amd = ampmoddepth_ * lfo_delay; // Q32 :D uint32_t amd = ((int64_t)ampmoddepth_ * (int64_t)lfo_delay) >> 8; // Q24 :D
pitchmod += (((int64_t)pwmd) * (int64_t)senslfo) >> 39; pitchmod += (((int64_t)pwmd) * (int64_t)senslfo) >> 39;
pitchmod += (((int64_t)pmd) * (int64_t)senslfo) >> 39; pitchmod += (((int64_t)pmd) * (int64_t)senslfo) >> 39;
@ -216,12 +219,13 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay,
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitchmod); params_[op].freq = Freqlut::lookup(basepitch_[op] + pitchmod);
int32_t level = env_[op].getsample(); int32_t level = env_[op].getsample();
int32_t gain = Exp2::lookup(level - (14 * (1 << 24)));
if ( ampmodsens_[op] != 0 ) { if ( ampmodsens_[op] != 0 ) {
uint32_t sensamp = ampmodsens_[op] * (lfo_val - (1 << 23)); uint32_t sensamp = ((int64_t)ampmodsens_[op]) * ((int64_t)gain) >> 24;
uint32_t amd_level = (((int64_t)amd) * (int64_t)sensamp) >> 40; sensamp = ((int64_t)sensamp) * ((int64_t)lfo_val) >> 24;
level -= amd_level; uint32_t amd_level = (((int64_t)amd) * (int64_t)sensamp) >> 24;
gain -= amd_level;
} }
int32_t gain = Exp2::lookup(level - (14 * (1 << 24)));
params_[op].gain[1] = gain; params_[op].gain[1] = gain;
} }
core_.compute(buf, params_, algorithm_, fb_buf_, fb_shift_, ctrls); core_.compute(buf, params_, algorithm_, fb_buf_, fb_shift_, ctrls);
@ -249,6 +253,7 @@ void Dx7Note::update(const char patch[156], int midinote) {
fb_shift_ = feedback != 0 ? 8 - feedback : 16; fb_shift_ = feedback != 0 ? 8 - feedback : 16;
pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6;
} }
void Dx7Note::peekVoiceStatus(VoiceStatus &status) { void Dx7Note::peekVoiceStatus(VoiceStatus &status) {

@ -19,7 +19,7 @@
#include "synth.h" #include "synth.h"
#include "env.h" #include "env.h"
using namespace std; //using namespace std;
uint32_t Env::sr_multiplier = (1<<24); uint32_t Env::sr_multiplier = (1<<24);
@ -40,7 +40,7 @@ void Env::init(const int r[4], const int l[4], int32_t ol, int rate_scaling) {
} }
int32_t Env::getsample() { int32_t Env::getsample() {
if (ix_ < 3 || (ix_ < 4) && !down_) { if (ix_ < 3 || ((ix_ < 4) && !down_)) {
if (rising_) { if (rising_) {
const int jumptarget = 1716; const int jumptarget = 1716;
if (level_ < (jumptarget << 16)) { if (level_ < (jumptarget << 16)) {

@ -47,7 +47,7 @@ class Env {
static void init_sr(double sample_rate); static void init_sr(double sample_rate);
private: private:
// This code is normalized to 44100, need to put a multiplier // PG: This code is normalized to 44100, need to put a multiplier
// if we are not using 44100. // if we are not using 44100.
static uint32_t sr_multiplier; static uint32_t sr_multiplier;

@ -48,9 +48,9 @@ const FmAlgorithm algorithms[32] = {
{ { 0xc1, 0x11, 0x11, 0x14, 0x01, 0x14 } }, // 1 { { 0xc1, 0x11, 0x11, 0x14, 0x01, 0x14 } }, // 1
{ { 0x01, 0x11, 0x11, 0x14, 0xc1, 0x14 } }, // 2 { { 0x01, 0x11, 0x11, 0x14, 0xc1, 0x14 } }, // 2
{ { 0xc1, 0x11, 0x14, 0x01, 0x11, 0x14 } }, // 3 { { 0xc1, 0x11, 0x14, 0x01, 0x11, 0x14 } }, // 3
{ { 0xe1, 0x11, 0x94, 0x01, 0x11, 0x14 } }, // 4 { { 0xc1, 0x11, 0x94, 0x01, 0x11, 0x14 } }, // 4 ** EXCEPTION VIA CODE
{ { 0xc1, 0x14, 0x01, 0x14, 0x01, 0x14 } }, // 5 { { 0xc1, 0x14, 0x01, 0x14, 0x01, 0x14 } }, // 5
{ { 0xd1, 0x94, 0x01, 0x14, 0x01, 0x14 } }, // 6 { { 0xc1, 0x94, 0x01, 0x14, 0x01, 0x14 } }, // 6 ** EXCEPTION VIA CODE
{ { 0xc1, 0x11, 0x05, 0x14, 0x01, 0x14 } }, // 7 { { 0xc1, 0x11, 0x05, 0x14, 0x01, 0x14 } }, // 7
{ { 0x01, 0x11, 0xc5, 0x14, 0x01, 0x14 } }, // 8 { { 0x01, 0x11, 0xc5, 0x14, 0x01, 0x14 } }, // 8
{ { 0x01, 0x11, 0x05, 0x14, 0xc1, 0x14 } }, // 9 { { 0x01, 0x11, 0x05, 0x14, 0xc1, 0x14 } }, // 9
@ -130,28 +130,33 @@ void FmCore::compute(int32_t *output, FmOpParams *params, int algorithm,
// PG: this is my 'dirty' implementation of FB for 2 and 3 operators... // PG: this is my 'dirty' implementation of FB for 2 and 3 operators...
// still needs some tuning... // still needs some tuning...
if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) {
switch ( (flags >> 6) - 0xc ) { switch ( algorithm ) {
// one operator feedback, normal process
case 0 :
//cout << "\t" << op << " fb " << inbus << outbus << add << endl;
FmOpKernel::compute_fb(outptr, param.phase, param.freq,
gain1, gain2,
fb_buf, feedback_shift, add, controllers);
break;
// two operator feedback, process exception for ALGO 6 // two operator feedback, process exception for ALGO 6
case 1 : case 5 :
FmOpKernel::compute_fb2(outptr, params, fb_buf, feedback_shift, controllers); FmOpKernel::compute_fb2(outptr, params, fb_buf, feedback_shift, controllers);
params[1].phase += params[1].freq << LG_N; // yuk, hack, we already processed op-5 param.phase += param.freq << LG_N;
params[1].phase += param.freq + params[1].freq << LG_N; // yuk, hack, we already processed op-5
op++; // ignore next operator; op++; // ignore next operator;
break; break;
// three operator feedback, process exception for ALGO 4 // three operator feedback, process exception for ALGO 4
case 2 : case 3 :
FmOpKernel::compute_fb3(outptr, params, fb_buf, feedback_shift, controllers); FmOpKernel::compute_fb3(outptr, params, fb_buf, feedback_shift, controllers);
params[1].phase += params[1].freq << LG_N; // hack, we already processed op-5 - op-4 param.phase += param.freq << LG_N;
params[2].phase += params[2].freq << LG_N; // yuk yuk params[1].phase += param.freq + params[1].freq << LG_N; // hack, we already processed op-5 - op-4
params[2].phase += param.freq + params[1].freq + params[2].freq << LG_N; // yuk yuk
op += 2; // ignore the 2 other operators op += 2; // ignore the 2 other operators
break; break;
default:
// one operator feedback, normal proces
//cout << "\t" << op << " fb " << inbus << outbus << add << endl;
FmOpKernel::compute_fb(outptr, param.phase, param.freq,
gain1, gain2,
fb_buf, feedback_shift, add, controllers);
param.phase += param.freq << LG_N;
break;
} }
has_contents[outbus] = true;
continue;
} else { } else {
// cout << op << " pure " << inbus << outbus << add << endl; // cout << op << " pure " << inbus << outbus << add << endl;
FmOpKernel::compute_pure(outptr, param.phase, param.freq, FmOpKernel::compute_pure(outptr, param.phase, param.freq,

@ -23,17 +23,9 @@
#endif #endif
#include "synth.h" #include "synth.h"
#include "sin.h" #include "sin.h"
#include "fm_op_kernel.h" #include "fm_op_kernel.h"
uint32_t restdither() {
return rand() & 0x3FFF;
return 0;
}
#ifdef HAVE_NEONx #ifdef HAVE_NEONx
static bool hasNeon() { static bool hasNeon() {
return true; return true;
@ -52,8 +44,6 @@ static bool hasNeon() {
} }
#endif #endif
//#define BIT8 0xFFFFFF00
void FmOpKernel::compute(int32_t *output, const int32_t *input, void FmOpKernel::compute(int32_t *output, const int32_t *input,
int32_t phase0, int32_t freq, int32_t phase0, int32_t freq,
int32_t gain1, int32_t gain2, bool add, const Controllers *controllers) { int32_t gain1, int32_t gain2, bool add, const Controllers *controllers) {
@ -172,7 +162,7 @@ void FmOpKernel::compute_fb2(int32_t *output, FmOpParams *parms, int32_t *fb_buf
phase[1] = parms[1].phase; phase[1] = parms[1].phase;
dgain[0] = (parms[0].gain[1] - parms[0].gain[0] + (N >> 1)) >> LG_N; dgain[0] = (parms[0].gain[1] - parms[0].gain[0] + (N >> 1)) >> LG_N;
dgain[1] = (parms[1].gain[1] - parms[1].gain[1] + (N >> 1)) >> LG_N; dgain[1] = (parms[1].gain[1] - parms[1].gain[0] + (N >> 1)) >> LG_N;
gain[0] = parms[0].gain[0]; gain[0] = parms[0].gain[0];
gain[1] = parms[1].gain[1]; gain[1] = parms[1].gain[1];
@ -188,7 +178,7 @@ void FmOpKernel::compute_fb2(int32_t *output, FmOpParams *parms, int32_t *fb_buf
// op 1 // op 1
gain[1] += dgain[1]; gain[1] += dgain[1];
//scaled_fb = (y0 + y) >> (fb_shift + 1); scaled_fb = (y0 + y) >> (fb_shift + 1);
y0 = y; y0 = y;
y = Sin::lookup(phase[1] + scaled_fb + y); y = Sin::lookup(phase[1] + scaled_fb + y);
y = ((int64_t)y * (int64_t)gain) >> 24; y = ((int64_t)y * (int64_t)gain) >> 24;

@ -53,7 +53,7 @@ void PitchEnv::set(const int r[4], const int l[4]) {
} }
int32_t PitchEnv::getsample() { int32_t PitchEnv::getsample() {
if (ix_ < 3 || (ix_ < 4) && !down_) { if (ix_ < 3 || ((ix_ < 4) && !down_)) {
if (rising_) { if (rising_) {
level_ += inc_; level_ += inc_;
if (level_ >= targetlevel_) { if (level_ >= targetlevel_) {

Loading…
Cancel
Save