Added a slightly better version of synth_dexed which supports also F32 (if you set

USE_OPEN_AUDIO_LIB).
pull/41/head
Holger Wirtz 3 years ago
parent 4b2fbe09d5
commit a3ac774a23
  1. 4
      MicroDexed.ino
  2. 2
      UI.hpp
  3. 2
      dexed_sd.h
  4. 122
      synth_dexed.cpp
  5. 139
      synth_dexed.h

@ -43,7 +43,7 @@
#include "UI.hpp" #include "UI.hpp"
// Audio engines // Audio engines
AudioSourceMicroDexed* MicroDexed[NUM_DEXED]; AudioSynthDexed* MicroDexed[NUM_DEXED];
#if defined(USE_FX) #if defined(USE_FX)
AudioSynthWaveform* chorus_modulator[NUM_DEXED]; AudioSynthWaveform* chorus_modulator[NUM_DEXED];
#if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT
@ -173,7 +173,7 @@ AudioConnection * dynamicConnections[NUM_DEXED * 4];
#endif #endif
void create_audio_engine_chain(uint8_t instance_id) void create_audio_engine_chain(uint8_t instance_id)
{ {
MicroDexed[instance_id] = new AudioSourceMicroDexed(SAMPLE_RATE); MicroDexed[instance_id] = new AudioSynthDexed(SAMPLE_RATE);
mono2stereo[instance_id] = new AudioEffectMonoStereo(); mono2stereo[instance_id] = new AudioEffectMonoStereo();
#if defined(USE_FX) #if defined(USE_FX)
chorus_modulator[instance_id] = new AudioSynthWaveform(); chorus_modulator[instance_id] = new AudioSynthWaveform();

@ -70,7 +70,7 @@ extern void change_disp_sd(bool d);
#endif #endif
extern AudioControlSGTL5000 sgtl5000_1; extern AudioControlSGTL5000 sgtl5000_1;
extern AudioSourceMicroDexed* MicroDexed[NUM_DEXED]; extern AudioSynthDexed* MicroDexed[NUM_DEXED];
#if defined(USE_FX) #if defined(USE_FX)
extern AudioSynthWaveform* chorus_modulator[NUM_DEXED]; extern AudioSynthWaveform* chorus_modulator[NUM_DEXED];
extern AudioEffectModulatedDelay* modchorus[NUM_DEXED]; extern AudioEffectModulatedDelay* modchorus[NUM_DEXED];

@ -30,7 +30,7 @@
extern uint8_t sd_card; extern uint8_t sd_card;
extern Dexed* dexed; extern Dexed* dexed;
extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; extern AudioSynthDexed * MicroDexed[NUM_DEXED];
extern void show_patch(uint8_t instance_id); extern void show_patch(uint8_t instance_id);
extern void send_sysex_voice(uint8_t midi_channel, uint8_t* data); extern void send_sysex_voice(uint8_t midi_channel, uint8_t* data);

@ -1,4 +1,5 @@
#include "synth_dexed.h" #include "synth_dexed.h"
/** /**
Copyright (c) 2013-2014 Pascal Gauthier. Copyright (c) 2013-2014 Pascal Gauthier.
@ -388,13 +389,76 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer)
else if (vuSignal > 0.001f) else if (vuSignal > 0.001f)
vuSignal *= decayFactor; vuSignal *= decayFactor;
else else
vuSignal = 0; vuSignal = 0.0;
} }
//arm_scale_f32(sumbuf, 0.00015, sumbuf, AUDIO_BLOCK_SAMPLES); //arm_scale_f32(sumbuf, 0.00015, sumbuf, AUDIO_BLOCK_SAMPLES);
arm_float_to_q15(sumbuf, buffer, AUDIO_BLOCK_SAMPLES); arm_float_to_q15(sumbuf, buffer, AUDIO_BLOCK_SAMPLES);
} }
void Dexed::getSamples(uint16_t n_samples, float32_t* buffer)
{
uint16_t i, j;
uint8_t note;
float s;
const double decayFactor = 0.99992;
if (refreshVoice)
{
for (i = 0; i < max_notes; i++)
{
if ( voices[i].live )
voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity, voices[i].porta, &controllers);
}
lfo.reset(data + 137);
refreshVoice = false;
}
for (i = 0; i < n_samples; i += _N_)
{
AlignedBuf<int32_t, _N_> audiobuf;
for (uint8_t j = 0; j < _N_; ++j)
{
audiobuf.get()[j] = 0;
buffer[i + j] = 0.0;
}
int32_t lfovalue = lfo.getsample();
int32_t lfodelay = lfo.getdelay();
for (note = 0; note < max_notes; note++)
{
if (voices[note].live)
{
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers);
for (j = 0; j < _N_; ++j)
{
buffer[i + j] += static_cast<float>(audiobuf.get()[j]) / 32768;
audiobuf.get()[j] = 0;
}
}
}
}
fx.process(buffer, n_samples); // Needed for fx.Gain()!!!
// mild compression
for (i = 0; i < n_samples; i++)
{
s = abs(buffer[i]);
if (s > vuSignal)
vuSignal = s;
else if (vuSignal > 0.001f)
vuSignal *= decayFactor;
else
vuSignal = 0;
}
arm_scale_f32(buffer, 0.00015, buffer, AUDIO_BLOCK_SAMPLES);
}
void Dexed::keydown(int16_t pitch, uint8_t velo) { void Dexed::keydown(int16_t pitch, uint8_t velo) {
if ( velo == 0 ) { if ( velo == 0 ) {
keyup(pitch); keyup(pitch);
@ -1591,20 +1655,20 @@ void Env::transfer(Env &src) {
inc_ = src.inc_; inc_ = src.inc_;
} }
/* /*
* Copyright 2013 Google Inc. Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
* You may obtain a copy of the License at You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
#define exp2(arg) pow(2.0, arg) #define exp2(arg) pow(2.0, arg)
@ -2323,20 +2387,20 @@ void Porta::init_sr(double sampleRate)
int32_t Porta::rates[128]; int32_t Porta::rates[128];
/* /*
* Copyright 2012 Google Inc. Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
* You may obtain a copy of the License at You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ */
#define R (1 << 29) #define R (1 << 29)

@ -1,8 +1,12 @@
#include <Arduino.h> #include <Arduino.h>
#include <Audio.h> #include <Audio.h>
#include "config.h" #include "config.h"
#if defined(USE_OPEN_AUDIO_LIB)
#include "OpenAudio_ArduinoLibrary.h"
#endif
/***************************************************** /*****************************************************
* CODE; orig_code/synth.h CODE; orig_code/synth.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -76,7 +80,7 @@ inline static T max(const T& a, const T& b) {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/aligned_buf.h CODE; orig_code/aligned_buf.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2013 Google Inc. Copyright 2013 Google Inc.
@ -111,7 +115,7 @@ class AlignedBuf {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/sin.h CODE; orig_code/sin.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -178,7 +182,7 @@ int32_t Sin::lookup(int32_t phase) {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/exp2.h CODE; orig_code/exp2.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -263,16 +267,16 @@ int32_t Tanh::lookup(int32_t x) {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/fast_log.h CODE; orig_code/fast_log.h
*****************************************************/ *****************************************************/
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* https://community.arm.com/tools/f/discussions/4292/cmsis-dsp-new-functionality-proposal/22621#22621 https://community.arm.com/tools/f/discussions/4292/cmsis-dsp-new-functionality-proposal/22621#22621
* Fast approximation to the log2() function. It uses a two step Fast approximation to the log2() function. It uses a two step
* process. First, it decomposes the floating-point number into process. First, it decomposes the floating-point number into
* a fractional component F and an exponent E. The fraction component a fractional component F and an exponent E. The fraction component
* is used in a polynomial approximation and then the exponent added is used in a polynomial approximation and then the exponent added
* to the result. A 3rd order polynomial is used and the result to the result. A 3rd order polynomial is used and the result
* when computing db20() is accurate to 7.984884e-003 dB. when computing db20() is accurate to 7.984884e-003 dB.
** ------------------------------------------------------------------- */ ** ------------------------------------------------------------------- */
static float log2f_approx_coeff[4] = {1.23149591368684f, -4.11852516267426f, 6.02197014179219f, -3.13396450166353f}; static float log2f_approx_coeff[4] = {1.23149591368684f, -4.11852516267426f, 6.02197014179219f, -3.13396450166353f};
@ -296,7 +300,7 @@ static float log2f_approx(float X)
Y *= F; Y *= F;
Y += (*C++); Y += (*C++);
Y += E; Y += E;
return(Y); return (Y);
} }
// https://codingforspeed.com/using-faster-exponential-approximation/ // https://codingforspeed.com/using-faster-exponential-approximation/
@ -318,7 +322,7 @@ inline float dbToUnit(float db) {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/freqlut.h CODE; orig_code/freqlut.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -344,7 +348,7 @@ class Freqlut {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/lfo.h CODE; orig_code/lfo.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2013 Google Inc. Copyright 2013 Google Inc.
@ -392,7 +396,7 @@ class Lfo {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/env.h CODE; orig_code/env.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2017 Pascal Gauthier. Copyright 2017 Pascal Gauthier.
@ -472,7 +476,7 @@ class Env {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/pitchenv.h CODE; orig_code/pitchenv.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2013 Google Inc. Copyright 2013 Google Inc.
@ -525,7 +529,7 @@ extern const int8_t pitchenv_tab[];
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/controllers.h CODE; orig_code/controllers.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2013 Google Inc. Copyright 2013 Google Inc.
@ -571,12 +575,12 @@ class FmMod {
void setRange(uint8_t r) void setRange(uint8_t r)
{ {
range = r < 0 || r > 99 ? 0 : r; range = r < 0 && r > 99 ? 0 : r;
} }
void setTarget(uint8_t assign) void setTarget(uint8_t assign)
{ {
assign = assign < 0 || assign > 7 ? 0 : assign; assign = assign < 0 && assign > 7 ? 0 : assign;
pitch = assign & 1; // PITCH pitch = assign & 1; // PITCH
amp = assign & 2; // AMP amp = assign & 2; // AMP
eg = assign & 4; // EG eg = assign & 4; // EG
@ -664,7 +668,7 @@ class Controllers {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/PluginFx.h CODE; orig_code/PluginFx.h
*****************************************************/ *****************************************************/
/** /**
@ -738,7 +742,7 @@ class PluginFx {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/fm_op_kernel.h CODE; orig_code/fm_op_kernel.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -786,7 +790,7 @@ class FmOpKernel {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/fm_core.h CODE; orig_code/fm_core.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2012 Google Inc. Copyright 2012 Google Inc.
@ -839,7 +843,7 @@ class FmCore {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/dx7note.h CODE; orig_code/dx7note.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2016-2017 Pascal Gauthier. Copyright 2016-2017 Pascal Gauthier.
@ -918,7 +922,7 @@ class Dx7Note {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/dexed.h CODE; orig_code/dexed.h
*****************************************************/ *****************************************************/
/* /*
MicroDexed MicroDexed
@ -1043,7 +1047,7 @@ class Dexed
bool isMonoMode(void); bool isMonoMode(void);
void setMonoMode(bool mode); void setMonoMode(bool mode);
void setRefreshMode(bool mode); void setRefreshMode(bool mode);
void getSamples(uint16_t n_samples, int16_t* buffer); //void getSamples(uint16_t n_samples, int16_t* buffer);
void panic(void); void panic(void);
void notesOff(void); void notesOff(void);
void resetControllers(void); void resetControllers(void);
@ -1102,12 +1106,14 @@ class Dexed
VoiceStatus voiceStatus; VoiceStatus voiceStatus;
Lfo lfo; Lfo lfo;
FmCore* engineMsfa; FmCore* engineMsfa;
void getSamples(uint16_t n_samples, float32_t* buffer);
void getSamples(uint16_t n_samples, int16_t* buffer);
}; };
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/porta.h CODE; orig_code/porta.h
*****************************************************/ *****************************************************/
/* /*
Copyright 2019 Jean Pierre Cimalando. Copyright 2019 Jean Pierre Cimalando.
@ -1134,16 +1140,16 @@ struct Porta {
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/source_microdexed.h CODE; orig_code/source_microdexed.h
*****************************************************/ *****************************************************/
class AudioSourceMicroDexed : public AudioStream, public Dexed { class AudioSynthDexed : public AudioStream, public Dexed {
public: public:
const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES); const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES);
uint32_t xrun = 0; uint32_t xrun = 0;
uint16_t render_time_max = 0; uint16_t render_time_max = 0;
AudioSourceMicroDexed(int sample_rate) : AudioStream(0, NULL), Dexed(sample_rate) { }; AudioSynthDexed(int sample_rate) : AudioStream(0, NULL), Dexed(sample_rate) { };
void update(void) void update(void)
{ {
@ -1184,64 +1190,113 @@ class AudioSourceMicroDexed : public AudioStream, public Dexed {
volatile bool in_update = false; volatile bool in_update = false;
}; };
#if defined(USE_OPEN_AUDIO_LIB)
class AudioSynthDexed_F32 : public AudioStream_F32, public Dexed {
public:
const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES);
uint32_t xrun = 0;
uint16_t render_time_max = 0;
AudioSynthDexed_F32(int sample_rate) : AudioStream_F32(0, NULL), Dexed(sample_rate) { };
void update(void)
{
if (in_update == true)
{
xrun++;
return;
}
else
in_update = true;
elapsedMicros render_time;
audio_block_f32_t *lblock;
lblock = allocate_f32();
if (!lblock)
{
in_update = false;
return;
}
getSamples(AUDIO_BLOCK_SAMPLES, lblock->data);
if (render_time > audio_block_time_us) // everything greater audio_block_time_us (2.9ms for buffer size of 128) is a buffer underrun!
xrun++;
if (render_time > render_time_max)
render_time_max = render_time;
AudioStream_F32::transmit(lblock, 0);
AudioStream_F32::release(lblock);
in_update = false;
};
private:
volatile bool in_update = false;
};
#endif
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/PluginFx.cpp CODE; orig_code/PluginFx.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/dexed.cpp CODE; orig_code/dexed.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/dx7note.cpp CODE; orig_code/dx7note.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/env.cpp CODE; orig_code/env.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/exp2.cpp CODE; orig_code/exp2.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/fm_core.cpp CODE; orig_code/fm_core.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/fm_op_kernel.cpp CODE; orig_code/fm_op_kernel.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/freqlut.cpp CODE; orig_code/freqlut.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/lfo.cpp CODE; orig_code/lfo.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/pitchenv.cpp CODE; orig_code/pitchenv.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/porta.cpp CODE; orig_code/porta.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================
/***************************************************** /*****************************************************
* CODE; orig_code/sin.cpp CODE; orig_code/sin.cpp
*****************************************************/ *****************************************************/
//===================================================== //=====================================================

Loading…
Cancel
Save