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
#include <cstdint>
#include <cmath>
namespace psemek::audio
{
constexpr int frequency = 44100;
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
#include <psemek/audio/stream.hpp>
#include <psemek/audio/duration.hpp>
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
#include <psemek/audio/stream.hpp>
#include <psemek/audio/duration.hpp>
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
: 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))
, length_(2 * std::round(length * frequency))
, start_samples_(2 * std::round(start * frequency))
, length_(length)
, start_(start)
{}
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
{
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
{
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 + 1] *= m;
current_ += 2;
}
start_samples_ = 0;
start_ = duration{};
}
return result;
@ -56,14 +56,14 @@ namespace psemek::audio
private:
stream_ptr stream_;
std::size_t length_;
duration length_;
duration start_;
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);
}

View file

@ -12,10 +12,10 @@ namespace psemek::audio
struct fade_out_impl
: 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))
, length_(2 * std::round(length * frequency))
, start_samples_(2 * std::round(start * frequency))
, length_(length)
, start_(start)
{}
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
{
if (current_ >= length_)
if (current_ >= length_.samples())
return 0;
auto result = stream_->read(data, sample_count);
if (result <= start_samples_)
if (result <= start_.samples())
{
start_samples_ -= result;
start_ -= result;
}
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 + 1] *= m;
current_ += 2;
}
start_samples_ = 0;
start_ = {};
}
return result;
@ -59,14 +59,14 @@ namespace psemek::audio
private:
stream_ptr stream_;
std::size_t length_;
duration length_;
duration start_;
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);
}