Add Karplus-Strong guitar generation algorithm

This commit is contained in:
Nikita Lisitsa 2022-10-08 19:49:11 +03:00
parent cb69759cce
commit af2bab53b9
2 changed files with 79 additions and 0 deletions

View file

@ -0,0 +1,10 @@
#pragma once
#include <psemek/audio/stream.hpp>
namespace psemek::audio
{
stream_ptr karplus_strong(float frequency);
}

View file

@ -0,0 +1,69 @@
#include <psemek/audio/wave/karplus_strong.hpp>
#include <psemek/audio/constants.hpp>
#include <psemek/random/generator.hpp>
#include <psemek/random/uniform.hpp>
#include <vector>
#include <atomic>
namespace psemek::audio
{
namespace
{
struct karplus_strong_impl
: stream
{
karplus_strong_impl(float frequency)
: buffer_(2 * std::round(audio::frequency / frequency))
{
random::generator rng{0x4b0a763ef6573bf2ull, 0};
for (auto & v : buffer_)
v = random::uniform(rng, -1.f, 1.f);
}
std::optional<std::size_t> length() const override
{
return std::nullopt;
}
std::size_t read(float * data, std::size_t sample_count) override
{
std::size_t const size = buffer_.size();
for (std::size_t i = 0; i < sample_count; i += 2)
{
buffer_[buffer_pos_ + 0] = (buffer_[buffer_pos_ + 0] + buffer_[(buffer_pos_ + 2) % size + 0]) / 2.f;
buffer_[buffer_pos_ + 1] = (buffer_[buffer_pos_ + 1] + buffer_[(buffer_pos_ + 2) % size + 1]) / 2.f;
data[i + 0] = buffer_[buffer_pos_ + 0];
data[i + 1] = buffer_[buffer_pos_ + 1];
buffer_pos_ += 2;
buffer_pos_ %= size;
}
return sample_count;
}
std::size_t played() const override
{
return played_.load();
}
private:
std::vector<float> buffer_;
std::size_t buffer_pos_{0};
std::atomic<std::size_t> played_;
};
}
stream_ptr karplus_strong(float frequency)
{
return std::make_shared<karplus_strong_impl>(frequency);
}
}