Compare commits

...

9 Commits

  1. 20
      Makefile
  2. 12
      Makefile.conf
  3. 18
      examples/Makefile
  4. 46
      examples/main_adc.cc
  5. 28
      examples/main_adc.hh
  6. 0
      examples/main_blink.cc
  7. 124
      examples/main_template_full.cc
  8. 30
      examples/main_template_full.hh
  9. 0
      examples/main_testtone.cc
  10. 17
      src/Makefile
  11. 110
      src/density.cc
  12. 33
      src/density.hh
  13. 119
      src/utils.cc
  14. 60
      src/utils.hh

20
Makefile

@ -1,13 +1,21 @@
.PHONY: all flash clean
.PHONY: all lib example flash clean clean-lib clean-examples
all: compile flash
all: flash
compile:
lib:
$(MAKE) -C src
flash:
$(MAKE) -C src program
example: lib
$(MAKE) -C examples
clean:
flash: example
$(MAKE) -C examples program
clean: clean-lib clean-examples
clean-lib:
$(MAKE) -C src clean
clean-examples:
$(MAKE) -C examples clean

12
Makefile.conf

@ -0,0 +1,12 @@
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
-include $(HERE)build.conf
TARGET_LIB ?= libdizzy
DEBUG ?= 0
LIBDAISY_DIR ?= ../../heck_libDaisy
DAISYSP_DIR ?= ../../heck_DaisySP
CXX_STANDARD ?= -std=c++17
CXXFLAGS += -Wall -Wno-unused -Wno-reorder-ctor -Wno-switch
CXXFLAGS += -fdiagnostics-color=always

18
examples/Makefile

@ -0,0 +1,18 @@
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
-include $(HERE)../Makefile.conf
TARGET ?= main_blink
DEBUG ?= 0
LIBDIZZY_DIR ?= ../src/
CXXFLAGS += -I$(LIBDIZZY_DIR)
LDFLAGS += -L$(LIBDIZZY_DIR)build/
LDFLAGS += -ldizzy
ALL_SRC = $(wildcard *.cc)
TARGET_SRC = $(TARGET).cc
MODULES_SRC = $(filter-out main_%,$(ALL_SRC))
CXX_SRC = $(MODULES_SRC) $(TARGET_SRC)
CXX_SOURCES = $(CXX_SRC)
include $(LIBDAISY_DIR)/core/Makefile

46
examples/main_adc.cc

@ -0,0 +1,46 @@
#include "main_adc.hh"
#include "utils.hh"
#include <functional>
namespace Heck {
namespace { // anonymous namespace for internal linkage
ld::DaisySeed seed{};
Observer<int> pot1{};
SWTimer scan_pots{};
void init()
{
seed.Init(Constants::CPU_BOOST480MHZ);
seed.StartLog(Constants::Developer::LOG_BLOCKS_BOOT);
ld::AdcChannelConfig adc_cfg[3];
adc_cfg[0].InitSingle(ld::DaisySeed::GetPin(Constants::Hardware::PIN_POT_1));
seed.adc.Init(adc_cfg, 1);
seed.adc.Start();
scan_pots.set_period(10);
scan_pots.set_callback([]() {
pot1.on_change_fuzzy(seed.adc.Get(0), 10, [](int val) {
seed.PrintLine("POT_1: %d", val);
});
});
}
void mainloop()
{
u32&& time_boot_ms{};
while (true) {
time_boot_ms = ld::System::GetNow();
scan_pots.is_it_already_time_again(time_boot_ms);
}
}
} // namespace
} // namespace Heck
int main()
{
Heck::init();
Heck::mainloop();
}

28
examples/main_adc.hh

@ -0,0 +1,28 @@
#ifndef HECK_MAIN_ADC_HH
#define HECK_MAIN_ADC_HH
#include <functional>
#include "types.hh"
namespace Heck {
namespace Constants {
namespace Hardware {
constexpr int PIN_BUTTON_1 = 28;
constexpr int PIN_POT_1 = 15;
constexpr int PIN_POT_2 = 16;
constexpr int PIN_POT_3 = 15;
}
constexpr bool CPU_BOOST480MHZ = false;
namespace Developer {
constexpr bool LOG_BLOCKS_BOOT = false;
}
} // namespace Constants
//Hardware
extern ld::DaisySeed seed;
// extern ld::Switch but_rec;
} // namespace Heck
#endif

0
src/main_blink.cc → examples/main_blink.cc

124
examples/main_template_full.cc

@ -0,0 +1,124 @@
// Hecks perkons extension
#include <functional>
#include "main_template_full.hh"
#include "utils.hh"
namespace Heck {
namespace { // anonymous namespace for internal linkage
// =============================================================================================
// INIT
// =============================================================================================
ld::DaisySeed seed{};
static ld::MidiUartHandler midi{};
// function prototypes
void audio_callback(
ld::AudioHandle::InputBuffer in,
ld::AudioHandle::OutputBuffer out,
size_t size)
;
void midi_realtime_handler(const ld::MidiEvent& msg);
void init()
{
seed.Configure();
seed.Init(Constants::CPU_BOOST480MHZ);
seed.StartLog(Constants::Developer::LOG_BLOCKS_BOOT);
seed.PrintLine("Setting Blocksize: %i", Constants::AUDIO_BUFFERSIZE);
seed.SetAudioBlockSize(Constants::AUDIO_BUFFERSIZE);
seed.PrintLine("Setting Samplerate: %i", Constants::AUDIO_SAMPLERATE);
seed.SetAudioSampleRate(Constants::AUDIO_SAMPLERATE);
seed.PrintLine("Initializing MIDI");
ld::MidiUartHandler::Config midi_config{};
midi.Init(midi_config);
seed.PrintLine("Starting MIDI Receive");
midi.StartReceiveRt(&midi_realtime_handler);
midi.Listen();
seed.PrintLine("Starting Audio");
seed.StartAudio(audio_callback);
}
// =============================================================================================
// RUN
// =============================================================================================
void audio_callback(ld::AudioHandle::InputBuffer in, ld::AudioHandle::OutputBuffer out, size_t size)
{
// Channel 1
for (size_t i = 0; i < size; i++) {
out[0][i] = in[0][i];
}
// Channel 2
for (size_t i = 0; i < size; i++) {
out[1][i] = in[1][i];
}
}
void midi_realtime_handler(const ld::MidiEvent& msg)
{
switch (msg.srt_type) {
case ld::TimingClock: {
} break;
case ld::Start: {
} break;
case ld::Stop: {
} break;
case ld::Reset: {
} break;
case ld::Continue: {
} break;
}
}
void midi_async_handler(const ld::MidiEvent& msg)
{
char strbuf[128];
GetMidiTypeAsString(msg, &strbuf[0]);
seed.PrintLine("%s", strbuf);
return;
}
void mainloop()
{
seed.PrintLine("Entering MainLoop");
u32 systick_now{};
bool heartbeat_led_state{ false };
SWTimer heartbeat{};
heartbeat.set_period(100);
heartbeat.set_callback([&heartbeat_led_state]() {
heartbeat_led_state = !heartbeat_led_state;
seed.SetLed(heartbeat_led_state);
return;
});
while (true) {
systick_now = ld::System::GetNow();
while (midi.HasEvents()) {
midi_async_handler(midi.PopEvent());
}
heartbeat.is_it_already_time_again(systick_now);
}
}
} // namespace
} // namespace Heck
int main()
{
Heck::init();
Heck::mainloop();
}

30
examples/main_template_full.hh

@ -0,0 +1,30 @@
#ifndef HECK_DAISY_GLOBALS_HH
#define HECK_DAISY_GLOBALS_HH
#include <cstdint>
#include "daisy_seed.h"
#include "daisysp.h"
#include "types.hh"
namespace Heck {
namespace Constants {
namespace Hardware {
// constexpr int PIN_BUTTON_RECORD = 28;
}
constexpr bool CPU_BOOST480MHZ = false;
constexpr int AUDIO_BUFFERSIZE = 4;
constexpr Samplerate AUDIO_SAMPLERATE = Samplerate::SAI_48KHZ;
namespace Developer {
constexpr bool LOG_BLOCKS_BOOT = false;
}
} // namespace Constants
//Hardware
extern ld::DaisySeed seed;
// extern ld::Switch but_rec;
} // namespace Heck
#endif

0
src/main_testtone.cc → examples/main_testtone.cc

17
src/Makefile

@ -1,20 +1,7 @@
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
-include $(HERE)../build.conf
TARGET ?= main_blink
DEBUG ?= 0
LIBDAISY_DIR ?= ../../heck_libDaisy
DAISYSP_DIR ?= ../../heck_DaisySP
CXX_STANDARD ?= -std=c++17
CXXFLAGS += -Wall -Wno-unused -Wno-reorder-ctor -Wno-switch
CXXFLAGS += -fdiagnostics-color=always
-include $(HERE)../Makefile.conf
ALL_SRC = $(wildcard *.cc)
TARGET_SRC = $(TARGET).cc
MODULES_SRC = $(filter-out main_%,$(ALL_SRC))
CXX_SRC = $(MODULES_SRC) $(TARGET_SRC)
CXX_SOURCES = $(CXX_SRC)
CXX_SOURCES = $(ALL_SRC)
include $(LIBDAISY_DIR)/core/Makefile

110
src/density.cc

@ -0,0 +1,110 @@
#include "density.hh"
namespace Heck {
void Density::process(const f32 *inSourceP, f32 *inDestP, u32 size)
{
UInt32 nSampleFrames = size;
const Float32 *sourceP = inSourceP;
Float32 *destP = inDestP;
Float64 inputSample;
Float64 drySample;
Float64 overallscale = 1.0;
overallscale /= 44100.0;
overallscale *= Constants::AUDIO_SAMPLERATE;
Float64 density = params[0];
Float64 iirAmount = pow(params[1], 3) / overallscale;
Float64 output = params[2];
Float64 wet = params[3];
Float64 dry = 1.0 - wet;
Float64 bridgerectifier;
Float64 out = fabs(density);
density = density * fabs(density);
Float64 count;
while (nSampleFrames-- > 0) {
inputSample = *sourceP;
if (fabs(inputSample) < 1.18e-23) {
inputSample = fpd * 1.18e-17;
}
drySample = inputSample;
if (fpFlip) {
iirSampleA = (iirSampleA * (1 - iirAmount)) + (inputSample * iirAmount);
inputSample -= iirSampleA;
} else {
iirSampleB = (iirSampleB * (1 - iirAmount)) + (inputSample * iirAmount);
inputSample -= iirSampleB;
}
//highpass section
count = density;
while (count > 1.0) {
bridgerectifier = fabs(inputSample) * 1.57079633;
if (bridgerectifier > 1.57079633) {
bridgerectifier = 1.57079633;
}
//max value for sine function
bridgerectifier = sin(bridgerectifier);
if (inputSample > 0.0) {
inputSample = bridgerectifier;
} else {
inputSample = -bridgerectifier;
}
count = count - 1.0;
}
//we have now accounted for any really high density settings.
while (out > 1.0) {
out = out - 1.0;
}
bridgerectifier = fabs(inputSample) * 1.57079633;
if (bridgerectifier > 1.57079633) {
bridgerectifier = 1.57079633;
}
//max value for sine function
if (density > 0) {
bridgerectifier = sin(bridgerectifier);
} else {
bridgerectifier = 1 - cos(bridgerectifier);
}
//produce either boosted or starved version
if (inputSample > 0) {
inputSample = (inputSample * (1 - out)) + (bridgerectifier * out);
} else {
inputSample = (inputSample * (1 - out)) - (bridgerectifier * out);
}
//blend according to density control
if (output < 1.0) {
inputSample *= output;
}
if (wet < 1.0) {
inputSample = (drySample * dry) + (inputSample * wet);
}
//nice little output stage template: if we have another scale of floating point
//number, we really don't want to meaninglessly multiply that by 1.0.
fpFlip = !fpFlip;
//begin 32 bit floating point dither
if constexpr (DO_DITHER) {
int expon;
frexpf((float)inputSample, &expon);
fpd ^= fpd << 13;
fpd ^= fpd >> 17;
fpd ^= fpd << 5;
inputSample += ((double(fpd) - uint32_t(0x7fffffff)) * 5.5e-36l * pow(2, expon + 62));
//end 32 bit floating point dither
}
*destP = inputSample;
//that simple.
sourceP++;
destP++;
}
}
} // namespace Heck

33
src/density.hh

@ -0,0 +1,33 @@
#ifndef HECK_OSP_DENSITY
#define HECK_OSP_DENSITY
#include "types.hh"
#include <array>
namespace Heck::Constants {
constexpr Samplerate AUDIO_SAMPLERATE = Samplerate::SAI_48KHZ;
}
namespace Heck {
struct Density {
using Float32 = f32;
using Float64 = f64;
using UInt32 = u32;
static constexpr bool DO_DITHER{ false };
std::array<f64, 4> params{ 0., 0., 1., 1. };
void process(const f32 * const inSourceP, f32 *inDestP, u32 size);
private:
Float64 iirSampleA;
Float64 iirSampleB;
uint32_t fpd;
bool fpFlip;
};
} // namespace Heck
#endif

119
src/utils.cc

@ -0,0 +1,119 @@
#include "utils.hh"
namespace Heck {
void GetMidiTypeAsString(const ld::MidiEvent& msg, char* str)
{
switch (msg.type) {
case ld::NoteOff:
strcpy(str, "NoteOff");
break;
case ld::NoteOn:
strcpy(str, "NoteOn");
break;
case ld::PolyphonicKeyPressure:
strcpy(str, "PolyKeyPres.");
break;
case ld::ControlChange:
strcpy(str, "CC");
break;
case ld::ProgramChange:
strcpy(str, "Prog. Change");
break;
case ld::ChannelPressure:
strcpy(str, "Chn. Pressure");
break;
case ld::PitchBend:
strcpy(str, "PitchBend");
break;
case ld::SystemCommon:
strcpy(str, "Sys. Common");
break;
case ld::SystemRealTime:
strcpy(str, "Sys. Realtime");
break;
case ld::ChannelMode:
strcpy(str, "Chn. Mode");
break;
default:
strcpy(str, "Unknown");
break;
}
}
void GetMidiRTTypeAsString(const ld::MidiEvent& msg, char* str)
{
switch (msg.srt_type) {
case ld::TimingClock:
strcpy(str, "TimingClock");
break;
case ld::SRTUndefined0:
strcpy(str, "SRTUndefined0");
break;
case ld::Start:
strcpy(str, "Start");
break;
case ld::Continue:
strcpy(str, "Continue");
break;
case ld::Stop:
strcpy(str, "Stop");
break;
case ld::SRTUndefined1:
strcpy(str, "SRTUndefined1");
break;
case ld::ActiveSensing:
strcpy(str, "ActiveSensing");
break;
case ld::Reset:
strcpy(str, "Reset");
break;
case ld::SystemRealTimeLast:
strcpy(str, "SystemRealTimeLast");
break;
default:
strcpy(str, "Unknown");
break;
}
}
float scalen_min_max(float val, float min, float max)
{
float range = max - min;
float ret = min + (val * range);
return ret;
}
float scalen_center_range(float val, float center, float range)
{
float min = center - (range / 2);
float ret = min + (val * range);
return ret;
}
} // namespace Heck
namespace Heck {
void SWTimer::set_period(u32 time_units)
{
time_period_ = time_units;
}
void SWTimer::set_callback(const Callback& cb)
{
callback_ = cb;
}
bool SWTimer::is_it_already_time_again(u32 time_now)
{
if (time_now - time_last_exec_ >= time_period_) {
time_last_exec_ = time_now;
if (callback_) {
//todo: constexpr if metrics
callback_();
}
return true;
}
return false;
}
} // namespace Heck

60
src/utils.hh

@ -0,0 +1,60 @@
#ifndef HECK_DAISY_UTILS_HH
#define HECK_DAISY_UTILS_HH
#include "daisy_seed.h"
#include "types.hh"
namespace Heck {
void GetMidiTypeAsString(const ld::MidiEvent& msg, char* str);
void GetMidiRTTypeAsString(const ld::MidiEvent& msg, char* str);
float scalen_min_max(float val, float min, float max);
float scalen_center_range(float val, float center, float range);
} // namespace Heck
namespace Heck {
class SWTimer {
public:
using Callback = std::function<void(void)>;
void set_period(u32 time_units);
void set_callback(const Callback& cb);
bool is_it_already_time_again(u32 time_now);
private:
Callback callback_{};
u32 time_last_exec_{};
u32 time_period_{};
};
} // namespace Heck
namespace Heck {
template<typename T> class Observer {
public:
bool on_change(T val_new, std::function<void(T val_current)> fn)
{
if (val_new != val_current_) {
val_current_ = val_new;
fn(val_current_);
return true;
}
return false;
}
bool on_change_fuzzy(T val_new, T min_deviation, std::function<void(T val_current)> fn)
{
if (std::abs(val_new - val_current_) >= min_deviation) {
val_current_ = val_new;
fn(val_current_);
return true;
}
return false;
}
private:
static inline T val_current_{};
};
} // namespace Heck
#endif // HECK_DAISY_UTILS_HH
Loading…
Cancel
Save