Skip to content

Commit

Permalink
Merge pull request #4 from lnd3/version-0.1.4
Browse files Browse the repository at this point in the history
Upcoming changes for version 0.1.4
  • Loading branch information
lnd3 authored Sep 7, 2024
2 parents ba45b33 + 0252974 commit ee77b84
Show file tree
Hide file tree
Showing 101 changed files with 7,286 additions and 1,449 deletions.
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 3.0.2)
cmake_minimum_required (VERSION 3.21.7)

project(ltools)

Expand All @@ -23,6 +23,10 @@ else()
testing
meta
memory
math
hid
audio
nodegraph

concurrency
filesystem
Expand Down
10 changes: 10 additions & 0 deletions packages/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project (audio)

set(deps
logging
testing
memory
math
)

bs_generate_package(audio "tier1" "${deps}" "PortAudio")
9 changes: 9 additions & 0 deletions packages/audio/include/audio/AudioUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <functional>

namespace l::audio {
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);
}
106 changes: 106 additions & 0 deletions packages/audio/include/audio/PortAudio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#pragma once

#include <mutex>
#include <atomic>
#include <condition_variable>
#include <semaphore>
#include <vector>
#include <unordered_map>

#include "../../include/portaudio.h"

namespace l::audio {

struct AudioStreamData {
double mDacOutputTimeAtLastCallback = 0.0;
int32_t mSampleRate = 0;
int32_t mNumBufferParts = 0;
int32_t mTotalNumFrames = 0;
int32_t mTotalBufferSize = 0;
int32_t mFramePosition = 0;
int32_t mDacFramesPerBufferPart = 0;
int32_t mNumChannels = 0;
float* mBuffer = nullptr;
std::binary_semaphore mDacWriteReady{ 0 };

float* GetCurrentBufferPosition() {
auto framePos = mFramePosition;
return mBuffer + framePos * mNumChannels;
}

void NextPart() {
// go to the part just before the one being written
auto framesAhead = mDacFramesPerBufferPart * (mNumBufferParts - 1);
mFramePosition = (mFramePosition + framesAhead) % mTotalNumFrames;
}

void NextPartCanBeWritten() {
mDacWriteReady.release();
}

bool CanWrite() {
return mDacWriteReady.try_acquire();
}

int32_t GetPartTotalSize() {
return mDacFramesPerBufferPart * mNumChannels;
}

int32_t GetNumFramesPerPart() {
return mDacFramesPerBufferPart;
}

int32_t GetSampleRate() {
return mSampleRate;
}
};

typedef void PaStream;

enum class ChannelMode {
MONO,
STEREO
};

enum class BufferingMode {
SINGLE_BUFFERING = 0,
DOUBLE_BUFFERING,
TRIPLE_BUFFERING
};

class AudioStream {
public:
AudioStream() = default;
~AudioStream() = default;

bool OpenStream(int32_t dacBufferFrames, float latency = 0.0f, BufferingMode mode = BufferingMode::DOUBLE_BUFFERING, ChannelMode channel = ChannelMode::STEREO);
bool StartStream();
std::vector<float>& GetWriteBuffer();
bool CanWrite();
void Write();
bool StopStream();
int32_t GetPartTotalSize();
int32_t GetNumFramesPerPart();
int32_t GetSampleRate();
protected:
PaStreamParameters mOutputParameters;
PaStream* mPaStream;

AudioStreamData mAudioStreamData;
std::vector<float> mOutputBufferInterleaved;
std::vector<float> mWriteBuffer;
};

class AudioManager {
public:
AudioManager() = default;
~AudioManager();

bool Init();
AudioStream* GetStream(std::string_view name);
void CloseStream(std::string_view name);
protected:
std::unordered_map<size_t, std::unique_ptr<AudioStream>> mStreams;
};

}
48 changes: 48 additions & 0 deletions packages/audio/source/common/AudioUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "audio/AudioUtils.h"

#include "logging/LoggingAll.h"
#include "math/MathAll.h"

#include "math/MathFunc.h"

#include <math.h>

namespace l::audio {

float GetFrequencyFromNote(float note) {
return 440.0f * l::math::functions::pow(2.0f, (note - 49.0f) / 12.0f);
}

double GetPhaseModifier(double note, double modifier) {
double limit = 1.0 / l::math::functions::max(note / 25.0, 1.0);
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) {
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();
}
updated = true;
}

// Update stuff
// process samples until
// * batch max has been reached
// * end has been reached

float samples = l::math::functions::min(static_cast<float>(end) - startNum, samplesLeft);
if (process != nullptr) {
process(static_cast<int32_t>(startNum), static_cast<int32_t>(startNum + samples), updated);
}
startNum += samples;
samplesLeft -= samples;
}
return samplesLeft;
}

}
Loading

0 comments on commit ee77b84

Please sign in to comment.