Skip to content

Commit

Permalink
Merge pull request #5 from lnd3/version-0.1.5
Browse files Browse the repository at this point in the history
Upcoming version 0.1.5
  • Loading branch information
lnd3 authored Sep 25, 2024
2 parents c68a353 + e28bb42 commit d57b4bc
Show file tree
Hide file tree
Showing 65 changed files with 6,485 additions and 3,202 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ else()
meta
memory
math
hid
audio
hid
nodegraph

concurrency
Expand Down
88 changes: 87 additions & 1 deletion packages/audio/include/audio/AudioUtils.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,95 @@
#pragma once

#include "math/MathAll.h"

#include <functional>

namespace l::audio {

class INoteProcessor {
public:
virtual ~INoteProcessor() = default;
virtual void NoteOn(int32_t, int32_t = 127) {}
virtual void NoteOff() {}
virtual void NoteOff(int32_t) {}
virtual void NoteSustain(bool) {}
};

extern const float gNoNote_f;
extern const int32_t gNoNote;
float GetFrequencyFromNote(float note);
double GetPhaseModifier(double note, double modifier);
float BatchUpdate(float updateSamples, float samplesLeft, int32_t start, int32_t end, std::function<void()> update, std::function<void(int32_t, int32_t, bool)> process);

int32_t GetAudioTicksFromMS(float ms, float sampleRate = 44100.0f);
float GetMSFromAudioTicks(float numTicks, float sampleRate = 44100.0f);

float GetRWAFactorFromMS(float numMS, float limit = 0.0001f, float rwaUpdateRate = 1.0f, float sampleRate = 44100.0f);
float GetRWAFactorFromMSSkewed(float ms, float limit = 0.0001f, float rwaUpdateRate = 1.0f, float sampleRate = 44100.0f);


float BatchUpdate(float updateSamples, float samplesLeft, int32_t start, int32_t end, std::function<float()> update, std::function<void(int32_t, int32_t, bool)> process);

template<class T>
class FilterRWA {
public:

FilterRWA() :
mSmooth(static_cast<T>(0.005)),
mValue(static_cast<T>(0)),
mTargetValue(static_cast<T>(0)),
mRWAUpdateRate(static_cast<T>(1.0))
{}
~FilterRWA() = default;

bool SnapAt(T value = static_cast<T>(0), T proximity = static_cast<T>(0.00001)) {
if (l::math::functions::abs(mValue - value) < proximity) {
mValue = value;
return true;
}
return false;
}

FilterRWA<T>& SetConvergenceInMs(T convergenceInMS, T limit = static_cast<T>(0.0001), T sampleRate = static_cast<T>(44100.0)) {
mSmooth = GetRWAFactorFromMS(convergenceInMS, limit, mRWAUpdateRate, sampleRate);
return *this;
}

FilterRWA<T>& SetConvergenceFactor(T smooth = static_cast<T>(0.005)) {
mSmooth = smooth;
return *this;
}

FilterRWA<T>& SetConvergenceInTicks(T ticks, T limit = static_cast<T>(0.001)) {
mSmooth = l::math::tween::GetRWAFactor(static_cast<int32_t>(ticks), limit);
return *this;
}

FilterRWA<T>& SetRWAUpdateRate(T fetchesPerUpdate = static_cast<float>(1.0)) {
mRWAUpdateRate = l::math::functions::max(fetchesPerUpdate, static_cast<float>(1.0));
return *this;
}

FilterRWA<T>& SetTarget(T target) {
mTargetValue = target;
return *this;
}

T Next() {
mValue += mSmooth * (mTargetValue - mValue);
return mValue;
}

T& Value() {
return mValue;
}

protected:
T mSmooth;
T mValue;
T mTargetValue;
T mRWAUpdateRate;
};

using FilterRWAFloat = FilterRWA<float>;

}
2 changes: 1 addition & 1 deletion packages/audio/include/audio/PortAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace l::audio {
AudioStream() = default;
~AudioStream() = default;

bool OpenStream(int32_t dacBufferFrames, float latency = 0.0f, BufferingMode mode = BufferingMode::DOUBLE_BUFFERING, ChannelMode channel = ChannelMode::STEREO);
bool OpenStream(int32_t dacFramesPerBufferPart, float latencyMs = 0.0f, BufferingMode mode = BufferingMode::DOUBLE_BUFFERING, ChannelMode channel = ChannelMode::STEREO);
bool StartStream();
std::vector<float>& GetWriteBuffer();
bool CanWrite();
Expand Down
31 changes: 28 additions & 3 deletions packages/audio/source/common/AudioUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
#include "math/MathAll.h"

#include "math/MathFunc.h"
#include "math/MathTween.h"

#include <math.h>

namespace l::audio {
const float gNoNote_f = -500.0f;
const int32_t gNoNote = -500;

float GetFrequencyFromNote(float note) {
return 440.0f * l::math::functions::pow(2.0f, (note - 49.0f) / 12.0f);
Expand All @@ -18,14 +21,37 @@ namespace l::audio {
return 800.0 * modifier * modifier * limit;
}

float BatchUpdate(float updateSamples, float samplesLeft, int32_t start, int32_t end, std::function<void()> update, std::function<void(int32_t, int32_t, bool)> process) {
int32_t GetAudioTicksFromMS(float ms, float sampleRate) {
return static_cast<int32_t>(ms * sampleRate / 1000.0f);
}

float GetMSFromAudioTicks(float numAudioSamples, float sampleRate) {
return numAudioSamples * 1000.0f / sampleRate;
}

float GetRWAFactorFromMS(float ms, float limit, float rwaUpdateRate, float sampleRate) {
int32_t updateSteps = GetAudioTicksFromMS(ms, sampleRate / rwaUpdateRate);
return l::math::tween::GetRWAFactor(updateSteps, limit);
}

float GetRWAFactorFromMSSkewed(float ms, float limit, float rwaUpdateRate, float sampleRate) {
float msRoot = l::math::functions::sqrt(ms);
int32_t steps = GetAudioTicksFromMS(msRoot, sampleRate / rwaUpdateRate);
float factor = l::math::tween::GetRWAFactor(steps, limit);
factor *= factor;
return factor;
}

float BatchUpdate(float updateSamples, float samplesLeft, int32_t start, int32_t end, std::function<float()> update, std::function<void(int32_t, int32_t, bool)> process) {
updateSamples = l::math::functions::max(updateSamples, 1.0f);
float startNum = static_cast<float>(start);
while (startNum < static_cast<float>(end)) {
bool updated = false;
if (samplesLeft < 1.0f) {
samplesLeft += updateSamples;
if (update != nullptr) {
update();
float rate = update();
updateSamples = rate > 0.0f ? rate : updateSamples;
}
updated = true;
}
Expand All @@ -44,5 +70,4 @@ namespace l::audio {
}
return samplesLeft;
}

}
1 change: 1 addition & 0 deletions packages/hid/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(deps
testing

math
audio
)

bs_generate_package(hid "tier1" "${deps}" "")
15 changes: 4 additions & 11 deletions packages/hid/include/hid/KeyboardPiano.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,14 @@
#include "logging/LoggingAll.h"

#include "hid/KeyState.h"
#include "audio/AudioUtils.h"

#include <functional>
#include <unordered_map>
#include <array>

namespace l::hid {

class INoteProcessor {
public:
virtual ~INoteProcessor() = default;
virtual void NoteOn(int32_t) {}
virtual void NoteOff() {}
virtual void NoteOff(int32_t) {}
};

enum class KeyFunctionTypes {
OCTAVE_DOWN = 0,
OCTAVE_UP
Expand All @@ -30,7 +23,7 @@ namespace l::hid {
const std::array<char, 18> charMapFromNoteBUpper = { '1', 'q', '2', 'w', '3', 'e', 'r', '5', 't', '6', 'y', '7', 'u', 'i', '9', 'o', '0', 'p' };

KeyboardPiano() : KeyboardPiano(nullptr, nullptr) {}
KeyboardPiano(l::hid::KeyState* keyState, l::hid::INoteProcessor* instrument) :
KeyboardPiano(l::hid::KeyState* keyState, l::audio::INoteProcessor* instrument) :
mKeyState(keyState),
mNotePlayer(instrument)
{
Expand All @@ -54,7 +47,7 @@ namespace l::hid {
}

void SetKeyState(KeyState* keyState);
void SetNoteProcessor(INoteProcessor* notePlayer);
void SetNoteProcessor(l::audio::INoteProcessor* notePlayer);
void ForEachNoteChange(std::function<void(int32_t, bool)> noteHandler);

void Update();
Expand All @@ -70,7 +63,7 @@ namespace l::hid {
std::unordered_map<int32_t, int32_t> mCharCodeToNote;
std::unordered_map<KeyFunctionTypes, int32_t> mKeyFunctions;
KeyState* mKeyState = nullptr;
INoteProcessor* mNotePlayer = nullptr;
l::audio::INoteProcessor* mNotePlayer = nullptr;
};

}
57 changes: 47 additions & 10 deletions packages/hid/include/hid/Midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace l::hid::midi {

struct MidiData {
uint32_t msg; // input message
uint32_t device; // device id
uint32_t deviceIn; // device id
uint32_t deviceOut; // corresponding out device
uint32_t timestamp; // Since opening the midi device
uint32_t status; // noteon=145, noteoff=129, knob=176, padon=144, padoff=128, sustain=177,
uint32_t channel;
Expand All @@ -19,6 +20,32 @@ namespace l::hid::midi {
uint32_t unused;
};


struct DeviceInfo {
std::string mName;
int32_t mInDevice = -1;
int32_t mOutDevice = -1;
int32_t mChannelKeys = -1;
int32_t mChannelButtons = -1;
int32_t mChannelKnobs = -1;

std::string_view GetName() {
return mName;
}
bool HasMidiIn() {
return mInDevice >= 0;
}
bool HasMidiOut() {
return mOutDevice >= 0;
}
uint32_t GetMidiIn() {
return static_cast<uint32_t>(mInDevice);
}
uint32_t GetMidiOut() {
return static_cast<uint32_t>(mOutDevice);
}
};

/*
uint32_t msg; // message
uint32_t instance; // device id
Expand All @@ -30,24 +57,34 @@ namespace l::hid::midi {
*/
using CallbackFunction = std::function<void(const MidiData&)>;

struct MidiHandle {
int32_t mCallbackId = 0;
uint32_t mMidiDeviceInId = 0;
uint32_t mMidiDeviceOutId = 0;
};

namespace details {
extern std::mutex midiCallbackMutex;
extern std::vector<l::hid::midi::CallbackFunction> midiCallback;
extern int32_t midiGuid;
extern std::unordered_map<int32_t, l::hid::midi::CallbackFunction> midiCallback;

void HandleMidiData(uint32_t msg, uint32_t instance, uint32_t param1, uint32_t param2);
void HandleMidiData(uint32_t msg, uint32_t deviceIn, uint32_t deviceOut, uint32_t param1, uint32_t param2);
}

class MidiManager {
public:
MidiManager() {
RegisterCallback([](const MidiData& data) {
LOG(LogInfo) << "listener 1: dev" << data.device << " stat " << data.status << " ch " << data.channel << " d1 " << data.data1 << " d2 " << data.data2;
});
}
virtual ~MidiManager() = default;
MidiManager() = default;
virtual ~MidiManager() {
ClearCallbacks();
};

virtual void RegisterCallback(CallbackFunction cb);
virtual void ClearCallbacks();
virtual void RescanMidiDevices();
virtual int32_t RegisterCallback(CallbackFunction cb);
virtual void UnregisterCallback(int32_t id);
virtual uint32_t GetNumDevices();
virtual std::string_view GetDeviceName(uint32_t);
virtual DeviceInfo* GetDeviceInfo(uint32_t deviceId);
virtual void SendToDevice(uint32_t deviceIndex, uint32_t status, uint32_t channel, uint32_t data1, uint32_t data2);
};

Expand Down
2 changes: 1 addition & 1 deletion packages/hid/source/common/KeyboardPiano.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace l::hid {
mKeyState = keyState;
}

void KeyboardPiano::SetNoteProcessor(INoteProcessor* notePlayer) {
void KeyboardPiano::SetNoteProcessor(l::audio::INoteProcessor* notePlayer) {
mNotePlayer = notePlayer;
}

Expand Down
Loading

0 comments on commit d57b4bc

Please sign in to comment.