Skip to content

Commit

Permalink
Merge pull request #63 from petiaccja/stl-compat
Browse files Browse the repository at this point in the history
snake_case member function for stl compatibility
  • Loading branch information
petiaccja authored Jul 16, 2022
2 parents f067ede + 436e539 commit 8af0df1
Show file tree
Hide file tree
Showing 63 changed files with 1,034 additions and 1,041 deletions.
16 changes: 8 additions & 8 deletions benchmark/Bench_ApplyFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ class DesignFilterFixture : public celero::TestFixture {
index = (index + 1) % pattern.size();
}

filter.zeros.Resize(filterOrder, 0);
filter.poles.Resize(filterOrder, 0);
filter.zeros.resize(filterOrder, 0);
filter.poles.resize(filterOrder, 0);
filter.gain = T(1.0) + T(0.001) * pattern[0];
for (auto& v : filter.zeros.RealRoots()) {
for (auto& v : filter.zeros.real_roots()) {
v = T(-0.95) + T(0.001) * pattern[index];
index = (index + 1) % pattern.size();
}
for (auto& v : filter.poles.RealRoots()) {
for (auto& v : filter.poles.real_roots()) {
v = T(-0.90) + T(0.001) * pattern[index];
index = (index + 1) % pattern.size();
}
Expand All @@ -122,7 +122,7 @@ using TfFixture = DesignFilterFixture<float, maxIirDirectOrder>;
using CascadeFixture = DesignFilterFixture<float, maxIirCascadeOrder>;

BASELINE_F(ApplyFilter, gain, BaselineFixture, 25, 1) {
Multiply(AsView(out).SubSignal(0, signal.Size()), signal, filter[0]);
Multiply(AsView(out).subsignal(0, signal.size()), signal, filter[0]);
celero::DoNotOptimizeAway(out[0]);
}

Expand All @@ -138,21 +138,21 @@ BENCHMARK_F(ApplyFilter, fir_ola, OlaFixture, 25, 1) {

BENCHMARK_F(ApplyFilter, iir_df_i, TfFixture, 25, 1) {
const auto realization = TransferFunction{ filter };
DirectFormI<float> state{ realization.Order() };
DirectFormI<float> state{ realization.order() };
Filter(out, signal, realization, state);
celero::DoNotOptimizeAway(out[0]);
}

BENCHMARK_F(ApplyFilter, iir_df_ii, TfFixture, 25, 1) {
const auto realization = TransferFunction{ filter };
DirectFormII<float> state{ realization.Order() };
DirectFormII<float> state{ realization.order() };
Filter(out, signal, realization, state);
celero::DoNotOptimizeAway(out[0]);
}

BENCHMARK_F(ApplyFilter, iir_cascade, CascadeFixture, 25, 1) {
const auto realization = CascadedBiquad{ filter };
CascadedForm<float> state{ realization.Order() };
CascadedForm<float> state{ realization.order() };
Filter(out, signal, realization, state);
celero::DoNotOptimizeAway(out[0]);
}
4 changes: 2 additions & 2 deletions docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ auto Crossfeed(SignalView<const float> left, SignalView<const float> right)
const auto filter = CascadedBiquad{ zpk };

// Apply filter.
CascadedForm<float> state{ filter.Order() };
CascadedForm<float> state{ filter.order() };
const auto lpLeft = Filter(left, filter, state);
state.Reset();
state.reset();
const auto lpRight = Filter(left, filter, state);

// Combine results.
Expand Down
2 changes: 1 addition & 1 deletion examples/01_Basics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ int main() {
// 1) set an existing memory region, "signal", to contain a square wave,
SquareWave(signal, 1024, 10.0);
// 2) return the requested signal in a brand-new memory region.
const auto window = BlackmanHarrisWindow<float, TIME_DOMAIN>(signal.Size());
const auto window = BlackmanHarrisWindow<float, TIME_DOMAIN>(signal.size());
// Use the first method when you want to avoid allocation for safety or performance
// reasons. Otherwise, the second one is often cleaner due to immutability.

Expand Down
8 changes: 4 additions & 4 deletions examples/02_FFT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Signal<float> LoadSunspotHistory() {
while (file.good()) {
float numSunspots = 0.0;
file >> numSunspots;
sunspotHistory.PushBack(numSunspots);
sunspotHistory.push_back(numSunspots);
}
return sunspotHistory;
}
Expand All @@ -38,17 +38,17 @@ int main() {
const Signal<float> sunspotHistory = LoadSunspotHistory();

// Apply the fourier transform to the time-domain data to reveal periodicity.
const Signal<float> window = BlackmanHarrisWindow<float, TIME_DOMAIN>(sunspotHistory.Size());
const Signal<float> window = BlackmanHarrisWindow<float, TIME_DOMAIN>(sunspotHistory.size());
const Spectrum<std::complex<float>> spectrum = Fft(sunspotHistory * window, FFT_HALF);
const Spectrum<float> amplitude = Abs(spectrum);

// Find the FFT bin with the highest amplitude. That will correspond to the frequency of the solar cycle.
// Since we know the solar cycle's period is less than 100 years, we can exclude frequencies below
// 0.01/year, thus also excluding the expected spike at DC.
const size_t firstBin = FourierFrequency2Bin(1.0 / 100, sunspotHistory.Size(), sampleRate);
const size_t firstBin = FourierFrequency2Bin(1.0 / 100, sunspotHistory.size(), sampleRate);
const auto maxBinIt = std::max_element(amplitude.begin() + firstBin, amplitude.end());
const size_t maxBin = maxBinIt - amplitude.begin();
const float solarCycleFrequency = (float)FourierBin2Frequency(maxBin, sunspotHistory.Size(), sampleRate);
const float solarCycleFrequency = (float)FourierBin2Frequency(maxBin, sunspotHistory.size(), sampleRate);
const float solarCyclePeriod = 1.0f / solarCycleFrequency;

// Should be about 11 years.
Expand Down
6 changes: 3 additions & 3 deletions examples/03_IIR_Filtering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,20 @@ std::optional<char> Detect(SignalView<const float> signal) {
std::array<bool, 4> containedTones2;

// Even though we will run 8 separate filters, we can reuse the same memory for output.
Signal<float> filtered(signal.Size());
Signal<float> filtered(signal.size());

// Due to the recursive nature of the IIR filters, they need a structure to store state.
CascadedForm<float> state{ filterOrder };

for (int i = 0; i < 4; ++i) {
state.Reset(); // The state is reset not to carry over garbage from the previous filtering.
state.reset(); // The state is reset not to carry over garbage from the previous filtering.
Filter(filtered, signal, filterBank1[i], state);
const float passed = RootMeanSquare(filtered);
containedTones1[i] = passed > threshold;
}

for (int i = 0; i < 4; ++i) {
state.Reset();
state.reset();
Filter(filtered, signal, filterBank2[i], state);
const float passed = RootMeanSquare(filtered);
containedTones2[i] = passed > threshold;
Expand Down
12 changes: 6 additions & 6 deletions examples/04_FIR_Filtering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ int main() {

size_t currentSample = 0;
PlayStereo(sampleRate, [left = AsView(left), right = AsView(right), &currentSample, &equalizer](SignalView<float> leftOut, SignalView<float> rightOut) -> size_t {
assert(leftOut.Size() == rightOut.Size());
const size_t validSize = std::min(left.Size() - currentSample, leftOut.Size());
equalizer.Filter(left.SubSignal(currentSample, validSize),
right.SubSignal(currentSample, validSize),
leftOut.SubSignal(0, validSize),
rightOut.SubSignal(0, validSize));
assert(leftOut.size() == rightOut.size());
const size_t validSize = std::min(left.size() - currentSample, leftOut.size());
equalizer.Filter(left.subsignal(currentSample, validSize),
right.subsignal(currentSample, validSize),
leftOut.subsignal(0, validSize),
rightOut.subsignal(0, validSize));
currentSample += validSize;
return validSize;
});
Expand Down
4 changes: 2 additions & 2 deletions examples/Tools/LoadSound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ StereoSound LoadStereoSound(const std::filesystem::path& file) {
}

Signal<float> interleaved(numFrames * numChannels);
soundFile.read(interleaved.Data(), interleaved.Size());
soundFile.read(interleaved.data(), interleaved.size());

Signal<float> leftChannel = Decimate(interleaved, 2);
Signal<float> rightChannel = Decimate(AsView(interleaved).SubSignal(1), 2);
Signal<float> rightChannel = Decimate(AsView(interleaved).subsignal(1), 2);

return { std::move(leftChannel), std::move(rightChannel), sampleRate };
}
12 changes: 6 additions & 6 deletions examples/Tools/PlaySound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ void PlayMono(uint64_t sampleRate, const PlayMonoCallback& callback) {
void PlayStereo(uint64_t sampleRate, SignalView<float> samplesLeft, SignalView<float> samplesRight) {
size_t currentSample = 0;
PlayStereo(sampleRate, [&samplesLeft, &samplesRight, &currentSample](SignalView<float> leftOut, SignalView<float> rightOut) -> size_t {
assert(leftOut.Size() == rightOut.Size());
const size_t validSize = std::min(samplesLeft.Size() - currentSample, leftOut.Size());
const auto leftChunk = samplesLeft.SubSignal(currentSample, validSize);
const auto rightChunk = samplesRight.SubSignal(currentSample, validSize);
assert(leftOut.size() == rightOut.size());
const size_t validSize = std::min(samplesLeft.size() - currentSample, leftOut.size());
const auto leftChunk = samplesLeft.subsignal(currentSample, validSize);
const auto rightChunk = samplesRight.subsignal(currentSample, validSize);
std::copy(leftChunk.begin(), leftChunk.end(), leftOut.begin());
std::copy(rightChunk.begin(), rightChunk.end(), rightOut.begin());
currentSample += validSize;
Expand All @@ -63,8 +63,8 @@ void PlayStereo(uint64_t sampleRate, SignalView<float> samplesLeft, SignalView<f
void PlayMono(uint64_t sampleRate, SignalView<float> samples) {
size_t currentSample = 0;
PlayMono(sampleRate, [&samples, &currentSample](SignalView<float> out) -> size_t {
const size_t validSize = std::min(samples.Size() - currentSample, out.Size());
const auto chunk = samples.SubSignal(currentSample, validSize);
const size_t validSize = std::min(samples.size() - currentSample, out.size());
const auto chunk = samples.subsignal(currentSample, validSize);
std::copy(chunk.begin(), chunk.end(), out.begin());
currentSample += validSize;
return validSize;
Expand Down
4 changes: 2 additions & 2 deletions include/dspbb/Filtering/FIR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ namespace impl {

template <class SignalR, class HalfbandDesc, std::enable_if_t<is_mutable_signal_v<SignalR>, int> = 0>
void FirFilterHilbert(SignalR&& out, const HalfbandDesc& halfbandDesc) {
if (out.Size() % 2 == 0) {
const size_t halfbandSize = out.Size() * 2 - 1;
if (out.size() % 2 == 0) {
const size_t halfbandSize = out.size() * 2 - 1;
std::decay_t<SignalR> halfband(halfbandSize);
DesignFilter(halfband, halfbandDesc);
fir::HalfbandToHilbertEven(out, halfband);
Expand Down
70 changes: 35 additions & 35 deletions include/dspbb/Filtering/FIR/BandTransforms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,30 @@ namespace dspbb::fir {

template <class SignalR, class SignalT, std::enable_if_t<is_mutable_signal_v<SignalR> && is_same_domain_v<SignalR, SignalT>, int> = 0>
void MirrorResponse(SignalR&& mirrored, const SignalT& filter) {
assert(mirrored.Size() == filter.Size());
assert(mirrored.size() == filter.size());
using R = typename signal_traits<std::decay_t<SignalR>>::type;
using T = typename signal_traits<std::decay_t<SignalT>>::type;
T sign = T(1);
for (size_t i = 0; i < filter.Size(); ++i, sign *= T(-1)) {
for (size_t i = 0; i < filter.size(); ++i, sign *= T(-1)) {
mirrored[i] = R(sign * filter[i]);
}
}

template <class SignalR, class SignalT, std::enable_if_t<is_mutable_signal_v<SignalR> && is_same_domain_v<SignalR, SignalT>, int> = 0>
void ComplementaryResponse(SignalR&& complementary, const SignalT& filter) {
assert(filter.Size() % 2 == 1);
assert(filter.size() % 2 == 1);
using R = typename signal_traits<std::decay_t<SignalR>>::type;
using T = typename signal_traits<std::decay_t<SignalT>>::type;
Multiply(complementary, filter, T(-1));
complementary[complementary.Size() / 2] += R(1);
complementary[complementary.size() / 2] += R(1);
}

template <class SignalR, class SignalT, class U, std::enable_if_t<is_mutable_signal_v<SignalR> && is_same_domain_v<SignalR, SignalT>, int> = 0>
void ShiftResponse(SignalR&& moved, const SignalT& filter, U normalizedFrequency) {
assert(moved.Size() == filter.Size());
const auto offset = static_cast<U>(filter.Size() / 2);
assert(moved.size() == filter.size());
const auto offset = static_cast<U>(filter.size() / 2);
const U scale = pi_v<U> * normalizedFrequency;
const size_t size = filter.Size();
const size_t size = filter.size();
for (size_t i = 0; i < size / 2; ++i) {
const U x = (U(i) - offset) * scale;
const U c = std::cos(x);
Expand All @@ -63,8 +63,8 @@ namespace impl {

template <class SignalR, class SignalT, std::enable_if_t<is_mutable_signal_v<SignalR> && is_same_domain_v<SignalR, SignalT>, int> = 0>
void HalfbandToHilbertOdd(SignalR& out, const SignalT& halfband) {
assert(halfband.Size() % 2 == 1);
assert(out.Size() == halfband.Size());
assert(halfband.size() % 2 == 1);
assert(out.size() == halfband.size());

using impl::kernelSize;
using R = typename std::decay_t<SignalR>::value_type;
Expand All @@ -74,35 +74,35 @@ void HalfbandToHilbertOdd(SignalR& out, const SignalT& halfband) {
constexpr size_t maxSizeSingleStep = kernelSize - 1;
const BasicSignalView<const T, Domain> kernel(impl::kernel<T>.begin(), impl::kernel<T>.end());

const size_t filterSize = halfband.Size();
const size_t filterSize = halfband.size();

if (halfband.Size() <= maxSizeSingleStep) {
if (halfband.size() <= maxSizeSingleStep) {
const size_t offset = kernelCenter - filterSize / 2;
const auto kernelRegion = kernel.SubSignal(offset, filterSize);
const auto kernelRegion = kernel.subsignal(offset, filterSize);
Multiply(out, halfband, kernelRegion);
}
else {
size_t tap = (filterSize / 2 - kernelCenter) % kernelSize;

Multiply(BasicSignalView<R, Domain>{ out.Data(), tap },
BasicSignalView<const T, Domain>{ halfband.Data(), tap },
kernel.SubSignal(kernelSize - tap));
Multiply(BasicSignalView<R, Domain>{ out.data(), tap },
BasicSignalView<const T, Domain>{ halfband.data(), tap },
kernel.subsignal(kernelSize - tap));
for (; tap + kernelSize < filterSize; tap += kernelSize) {
Multiply(BasicSignalView<R, Domain>{ out.Data() + tap, kernelSize },
BasicSignalView<const T, Domain>{ halfband.Data() + tap, kernelSize },
Multiply(BasicSignalView<R, Domain>{ out.data() + tap, kernelSize },
BasicSignalView<const T, Domain>{ halfband.data() + tap, kernelSize },
kernel);
}
const size_t lastChunkSize = filterSize - tap;
Multiply(BasicSignalView<R, Domain>{ out.Data() + tap, lastChunkSize },
BasicSignalView<const T, Domain>{ halfband.Data() + tap, lastChunkSize },
kernel.SubSignal(0, lastChunkSize));
Multiply(BasicSignalView<R, Domain>{ out.data() + tap, lastChunkSize },
BasicSignalView<const T, Domain>{ halfband.data() + tap, lastChunkSize },
kernel.subsignal(0, lastChunkSize));
}
}

template <class SignalR, class SignalT, std::enable_if_t<is_mutable_signal_v<SignalR>, int> = 0>
void HalfbandToHilbertEven(SignalR& out, const SignalT& halfband) {
assert(out.Size() % 2 == 0);
assert(out.Size() * 2 - 1 == halfband.Size());
assert(out.size() % 2 == 0);
assert(out.size() * 2 - 1 == halfband.size());

using impl::kernelSize;
using R = typename std::decay_t<SignalR>::value_type;
Expand All @@ -115,35 +115,35 @@ void HalfbandToHilbertEven(SignalR& out, const SignalT& halfband) {
const BasicSignalView<T, Domain> scratch(scratchStorage.begin(), scratchStorage.end());
const BasicSignalView<const T, Domain> kernel(impl::kernel<T>.begin(), impl::kernel<T>.end());

const size_t filterSize = halfband.Size();
const size_t filterSize = halfband.size();

if (halfband.Size() <= maxSizeSingleStep) {
if (halfband.size() <= maxSizeSingleStep) {
const size_t offset = kernelCenter - filterSize / 2;
const auto kernelRegion = kernel.SubSignal(offset, filterSize);
const auto scratchRegion = scratch.SubSignal(0, filterSize);
const auto kernelRegion = kernel.subsignal(offset, filterSize);
const auto scratchRegion = scratch.subsignal(0, filterSize);
Multiply(scratchRegion, halfband, kernelRegion);
Decimate(out, scratchRegion, 2);
}
else {
size_t tap = (filterSize / 2 - kernelCenter) % kernelSize;

Multiply(scratch.SubSignal(0, tap),
BasicSignalView<const T, Domain>{ halfband.Data(), tap },
kernel.SubSignal(kernelSize - tap));
Decimate(BasicSignalView<T, Domain>(out.begin(), (tap + 1) / 2), scratch.SubSignal(0, tap), 2);
Multiply(scratch.subsignal(0, tap),
BasicSignalView<const T, Domain>{ halfband.data(), tap },
kernel.subsignal(kernelSize - tap));
Decimate(BasicSignalView<T, Domain>(out.begin(), (tap + 1) / 2), scratch.subsignal(0, tap), 2);

for (; tap + kernelSize < filterSize; tap += kernelSize) {
Multiply(scratch,
BasicSignalView<const T, Domain>{ halfband.Data() + tap, kernelSize },
BasicSignalView<const T, Domain>{ halfband.data() + tap, kernelSize },
kernel);
Decimate(BasicSignalView<R, Domain>{ out.begin() + (tap + 1) / 2, (kernelSize + 1) / 2 }, scratch, 2);
}

const size_t lastChunkSize = filterSize - tap;
Multiply(scratch.SubSignal(0, lastChunkSize),
BasicSignalView<const T, Domain>{ halfband.Data() + tap, lastChunkSize },
kernel.SubSignal(0, lastChunkSize));
Decimate(BasicSignalView<R, Domain>{ out.begin() + (tap + 1) / 2, (lastChunkSize + 1) / 2 }, scratch.SubSignal(0, lastChunkSize), 2);
Multiply(scratch.subsignal(0, lastChunkSize),
BasicSignalView<const T, Domain>{ halfband.data() + tap, lastChunkSize },
kernel.subsignal(0, lastChunkSize));
Decimate(BasicSignalView<R, Domain>{ out.begin() + (tap + 1) / 2, (lastChunkSize + 1) / 2 }, scratch.subsignal(0, lastChunkSize), 2);
}
}

Expand Down
Loading

0 comments on commit 8af0df1

Please sign in to comment.