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