12#include "OfflineProduct.h"
32 double shift_, sine_ = 0;
33 std::optional<OfflineConvolutionWindow> near_;
38 if (!std::isfinite(shift) || std::abs(shift) >= 1)
44 const double reduced = shift > .5 ? 1 - shift : shift < -.5 ? -1 - shift : shift;
45 sine_ = std::sin(std::numbers::pi * reduced);
46 near_.emplace(work.
job(), work.
block(), [
this](
int lag)
47 { return (lag % 2 ? -sine_ : sine_) / (std::numbers::pi * (lag + shift_)); });
51 template <
class Reader>
54 const int b = work_.
block();
55 if (leaf >= work_.
leaves())
57 const auto first =
static_cast<std::int64_t
>(leaf) * b;
60 work_.
read(source, first, b, out);
64 work_.
read(source, first - b, 3 * b, near_->input());
65 const auto *close = near_->process();
66 for (
int i = 0; i < b; ++i)
67 out[i] = close[i] + (i % 2 ? -sine_ : sine_) * out[i];
79 std::array<double, 32> sine_{};
83 void operator()(std::int64_t first,
int count,
double *out)
85 owner->source_(first, count, out);
86 for (
int i = 0; i < count; ++i)
88 owner->sine_[
static_cast<std::size_t
>((first + i) % (2 * owner->factor_))];
91 std::optional<OfflineHilbertMap> map_;
96 : source_(std::move(source)),
99 if (factor < 1 || factor > 16 || (factor & (factor - 1)))
101 for (
int p = 1; p < factor; ++p)
103 sine_[p] = std::sin(std::numbers::pi * p / factor);
104 sine_[p + factor] = -sine_[p];
106 map_.emplace(work_, modulated_);
116 map_->rebuild(work_, modulated_);
122 [[nodiscard]] std::span<const double>
get(std::size_t leaf)
126 const int block = work_.
block();
127 const auto first =
static_cast<std::int64_t
>(leaf) * block;
128 const int count =
static_cast<int>(std::min<std::int64_t>(block, work_.
frames() - first));
129 map_->evaluateCauchy(work_, leaf, modulated_, transform_.get());
130 work_.
read(source_, first, count, raw_.get());
131 const int written = (count + factor_ - 1) / factor_;
132 for (
int k = 0; k < written; ++k)
134 const auto frame = first / factor_ + k;
136 raw_[k * factor_] / factor_ + (frame % 2 ? 1 : -1) * transform_[k * factor_];
138 return {output_.get(),
static_cast<std::size_t
>(written)};
141template <
class Reader,
class Consumer>
143 Consumer consume,
int block = 4096)
146 for (std::size_t leaf = 0; leaf < projection.leaves(); ++leaf)
148 const auto data = projection.get(leaf);
149 consume(
static_cast<std::int64_t
>(leaf) * (block / factor),
static_cast<int>(data.size()),
void evaluateCauchyFar(std::size_t leaf, double shift, double *output, bool alternating=false) const
int block() const noexcept
OfflineSession & job() noexcept
std::int64_t frames() const noexcept
std::size_t leaves() const noexcept
void read(Reader &source, std::int64_t first, int count, double *out) const
OfflineScratchArray< U > allocateScratch(std::uint64_t count)
SincPhase & operator=(const SincPhase &)=delete
void evaluate(const OfflineHilbertMap &map, std::size_t leaf, Reader &source, double *out)
SincPhase(OfflineProductWorkspace &work, double shift)
SincPhase(const SincPhase &)=delete
std::size_t leaves() const
SincProjection(OfflineSession &job, std::int64_t frames, int factor, Reader source, int block)
SincProjection & operator=(const SincProjection &)=delete
SincProjection(const SincProjection &)=delete
std::span< const double > get(std::size_t leaf)
void projectSinc(OfflineSession &job, std::int64_t frames, int factor, Reader source, Consumer consume, int block=4096)
void offlineFail(OfflineStatus status)
std::unique_ptr< T[], OfflineScratchDeleter< T > > OfflineScratchArray