Add audio::duration type & use it for effect duration parameters

This commit is contained in:
Nikita Lisitsa 2022-10-06 15:02:47 +03:00
parent 3890fa0b02
commit 3e9814aee4
6 changed files with 108 additions and 26 deletions

View file

@ -1,9 +1,22 @@
#pragma once #pragma once
#include <cstdint>
#include <cmath>
namespace psemek::audio namespace psemek::audio
{ {
constexpr int frequency = 44100; constexpr int frequency = 44100;
constexpr float inv_frequency = 1.f / frequency; constexpr float inv_frequency = 1.f / frequency;
inline std::int64_t seconds_to_samples(float seconds)
{
return static_cast<std::int64_t>(2 * std::round(seconds * frequency));
}
inline float samples_to_seconds(std::int64_t samples)
{
return static_cast<float>(samples) * 0.5f * inv_frequency;
}
} }

View file

@ -0,0 +1,67 @@
#pragma once
#include <psemek/audio/constants.hpp>
#include <cstdint>
#include <cmath>
namespace psemek::audio
{
struct duration
{
duration()
: samples_{0}
{}
duration(std::int64_t samples)
: samples_{samples}
{}
duration(std::size_t samples)
: samples_{samples}
{}
duration(float seconds)
: samples_{seconds_to_samples(seconds)}
{}
duration(duration const & other) = default;
float seconds() const
{
return samples_to_seconds(samples_);
}
std::int64_t samples() const
{
return samples_;
}
duration & operator += (duration const & other)
{
samples_ += other.samples_;
return *this;
}
duration & operator -= (duration const & other)
{
samples_ -= other.samples_;
return *this;
}
friend duration operator + (duration const & d1, duration const & d2)
{
return duration{d1.samples() + d2.samples()};
}
friend duration operator - (duration const & d1, duration const & d2)
{
return duration{d1.samples() - d2.samples()};
}
private:
std::int64_t samples_;
};
}

View file

@ -1,10 +1,11 @@
#pragma once #pragma once
#include <psemek/audio/stream.hpp> #include <psemek/audio/stream.hpp>
#include <psemek/audio/duration.hpp>
namespace psemek::audio namespace psemek::audio
{ {
stream_ptr fade_in(stream_ptr stream, float length, float start = 0.f); stream_ptr fade_in(stream_ptr stream, duration length, duration start = {});
} }

View file

@ -1,10 +1,11 @@
#pragma once #pragma once
#include <psemek/audio/stream.hpp> #include <psemek/audio/stream.hpp>
#include <psemek/audio/duration.hpp>
namespace psemek::audio namespace psemek::audio
{ {
stream_ptr fade_out(stream_ptr stream, float length, float start = 0.f); stream_ptr fade_out(stream_ptr stream, duration length, duration start = {});
} }

View file

@ -12,10 +12,10 @@ namespace psemek::audio
struct fade_in_impl struct fade_in_impl
: stream : stream
{ {
fade_in_impl(stream_ptr stream, float length, float start) fade_in_impl(stream_ptr stream, duration length, duration start)
: stream_(std::move(stream)) : stream_(std::move(stream))
, length_(2 * std::round(length * frequency)) , length_(length)
, start_samples_(2 * std::round(start * frequency)) , start_(start)
{} {}
std::optional<std::size_t> length() const override std::optional<std::size_t> length() const override
@ -31,24 +31,24 @@ namespace psemek::audio
std::size_t read(float * data, std::size_t sample_count) override std::size_t read(float * data, std::size_t sample_count) override
{ {
auto const result = stream_->read(data, sample_count); auto const result = stream_->read(data, sample_count);
std::fill(data, data + std::min(result, start_samples_), 0.f); std::fill(data, data + std::min<std::size_t>(result, start_.samples()), 0.f);
if (result <= start_samples_) if (result <= start_.samples())
{ {
start_samples_ -= result; start_ -= result;
} }
else else
{ {
for (std::size_t i = start_samples_; i < result; i += 2) for (std::size_t i = start_.samples(); i < result; i += 2)
{ {
float m = static_cast<float>(std::min(current_, length_)) / length_; float m = static_cast<float>(std::min<std::size_t>(current_, length_.samples())) / length_.samples();
data[i + 0] *= m; data[i + 0] *= m;
data[i + 1] *= m; data[i + 1] *= m;
current_ += 2; current_ += 2;
} }
start_samples_ = 0; start_ = duration{};
} }
return result; return result;
@ -56,14 +56,14 @@ namespace psemek::audio
private: private:
stream_ptr stream_; stream_ptr stream_;
std::size_t length_; duration length_;
duration start_;
std::size_t current_ = 0; std::size_t current_ = 0;
std::size_t start_samples_;
}; };
} }
stream_ptr fade_in(stream_ptr stream, float length, float start) stream_ptr fade_in(stream_ptr stream, duration length, duration start)
{ {
return std::make_shared<fade_in_impl>(std::move(stream), length, start); return std::make_shared<fade_in_impl>(std::move(stream), length, start);
} }

View file

@ -12,10 +12,10 @@ namespace psemek::audio
struct fade_out_impl struct fade_out_impl
: stream : stream
{ {
fade_out_impl(stream_ptr stream, float length, float start) fade_out_impl(stream_ptr stream, duration length, duration start)
: stream_(std::move(stream)) : stream_(std::move(stream))
, length_(2 * std::round(length * frequency)) , length_(length)
, start_samples_(2 * std::round(start * frequency)) , start_(start)
{} {}
std::optional<std::size_t> length() const override std::optional<std::size_t> length() const override
@ -31,27 +31,27 @@ namespace psemek::audio
std::size_t read(float * data, std::size_t sample_count) override std::size_t read(float * data, std::size_t sample_count) override
{ {
if (current_ >= length_) if (current_ >= length_.samples())
return 0; return 0;
auto result = stream_->read(data, sample_count); auto result = stream_->read(data, sample_count);
if (result <= start_samples_) if (result <= start_.samples())
{ {
start_samples_ -= result; start_ -= result;
} }
else else
{ {
for (std::size_t i = start_samples_; i < result; i += 2) for (std::size_t i = start_.samples(); i < result; i += 2)
{ {
float m = static_cast<float>(length_ - std::min(current_, length_)) / length_; float m = static_cast<float>(length_.samples() - std::min<std::size_t>(current_, length_.samples())) / length_.samples();
data[i + 0] *= m; data[i + 0] *= m;
data[i + 1] *= m; data[i + 1] *= m;
current_ += 2; current_ += 2;
} }
start_samples_ = 0; start_ = {};
} }
return result; return result;
@ -59,14 +59,14 @@ namespace psemek::audio
private: private:
stream_ptr stream_; stream_ptr stream_;
std::size_t length_; duration length_;
duration start_;
std::size_t current_ = 0; std::size_t current_ = 0;
std::size_t start_samples_;
}; };
} }
stream_ptr fade_out(stream_ptr stream, float length, float start) stream_ptr fade_out(stream_ptr stream, duration length, duration start)
{ {
return std::make_shared<fade_out_impl>(std::move(stream), length, start); return std::make_shared<fade_out_impl>(std::move(stream), length, start);
} }