Add audio::duration type & use it for effect duration parameters
This commit is contained in:
parent
3890fa0b02
commit
3e9814aee4
6 changed files with 108 additions and 26 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
67
libs/audio/include/psemek/audio/duration.hpp
Normal file
67
libs/audio/include/psemek/audio/duration.hpp
Normal 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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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 = {});
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = {});
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue