Add Karplus-Strong guitar generation algorithm
This commit is contained in:
parent
cb69759cce
commit
af2bab53b9
2 changed files with 79 additions and 0 deletions
10
libs/audio/include/psemek/audio/wave/karplus_strong.hpp
Normal file
10
libs/audio/include/psemek/audio/wave/karplus_strong.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/audio/stream.hpp>
|
||||||
|
|
||||||
|
namespace psemek::audio
|
||||||
|
{
|
||||||
|
|
||||||
|
stream_ptr karplus_strong(float frequency);
|
||||||
|
|
||||||
|
}
|
||||||
69
libs/audio/source/wave/karplus_strong.cpp
Normal file
69
libs/audio/source/wave/karplus_strong.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue