Add audio compressor
This commit is contained in:
parent
e7d3bc45d1
commit
59f83aec12
2 changed files with 91 additions and 0 deletions
13
libs/audio/include/psemek/audio/effect/compressor.hpp
Normal file
13
libs/audio/include/psemek/audio/effect/compressor.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/audio/stream.hpp>
|
||||||
|
#include <psemek/audio/constants.hpp>
|
||||||
|
|
||||||
|
namespace psemek::audio
|
||||||
|
{
|
||||||
|
|
||||||
|
stream_ptr compressor(stream_ptr stream, float volume_threshold = from_db(-1.f), float strength = 0.9f, float envelope_attack = 0.01f, float envelope_release = 1.f);
|
||||||
|
|
||||||
|
stream_ptr limiter(stream_ptr stream, float volume_threshold = from_db(0.f), float envelope_attack = 0.01f, float envelope_release = 1.f);
|
||||||
|
|
||||||
|
}
|
||||||
78
libs/audio/source/effect/compressor.cpp
Normal file
78
libs/audio/source/effect/compressor.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include <psemek/audio/effect/compressor.hpp>
|
||||||
|
#include <psemek/audio/smooth.hpp>
|
||||||
|
#include <psemek/geom/math.hpp>
|
||||||
|
|
||||||
|
namespace psemek::audio
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct compressor_impl
|
||||||
|
: stream
|
||||||
|
{
|
||||||
|
compressor_impl(stream_ptr stream, float volume_threshold, float strength, float envelope_attack, float envelope_release)
|
||||||
|
: stream_(std::move(stream))
|
||||||
|
, volume_threshold_log_(std::log(volume_threshold))
|
||||||
|
, strength_(strength)
|
||||||
|
, envelope_attack_multiplier_(smoothness_to_multiplier(envelope_attack))
|
||||||
|
, envelope_release_multiplier_(smoothness_to_multiplier(envelope_release))
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::optional<std::size_t> length() const override
|
||||||
|
{
|
||||||
|
return stream_->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t read(float * data, std::size_t sample_count) override
|
||||||
|
{
|
||||||
|
auto result = stream_->read(data, sample_count);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < result; i += 2)
|
||||||
|
{
|
||||||
|
float v = std::max(std::abs(data[i]), std::abs(data[i + 1]));
|
||||||
|
|
||||||
|
float multiplier = (v > envelope_) ? envelope_attack_multiplier_ : envelope_release_multiplier_;
|
||||||
|
|
||||||
|
envelope_ += (v - envelope_) * multiplier;
|
||||||
|
|
||||||
|
float strength = strength_;
|
||||||
|
|
||||||
|
float log_gain = strength * std::min(0.f, volume_threshold_log_ - std::log(envelope_));
|
||||||
|
|
||||||
|
float gain = std::exp(log_gain);
|
||||||
|
|
||||||
|
data[i + 0] *= gain;
|
||||||
|
data[i + 1] *= gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t played() const override
|
||||||
|
{
|
||||||
|
return stream_->played();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
stream_ptr stream_;
|
||||||
|
float volume_threshold_log_;
|
||||||
|
float strength_;
|
||||||
|
float envelope_attack_multiplier_;
|
||||||
|
float envelope_release_multiplier_;
|
||||||
|
float envelope_ = 0.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_ptr compressor(stream_ptr stream, float volume_threshold, float strength, float envelope_attack, float envelope_release)
|
||||||
|
{
|
||||||
|
return std::make_shared<compressor_impl>(std::move(stream), volume_threshold, strength, envelope_attack, envelope_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_ptr limiter(stream_ptr stream, float volume_threshold, float envelope_attack, float envelope_release)
|
||||||
|
{
|
||||||
|
return compressor(std::move(stream), volume_threshold, 1.f, envelope_attack, envelope_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue