Audacity 3.2.0
PowerSpectrumGetter.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 PowerSpectrumGetter.h
7
8 Matthieu Hodgkinson
9
10**********************************************************************/
11#pragma once
12
13struct PFFFT_Setup;
14
15#include <memory>
16#include <type_traits>
17#include <vector>
18#include "pffft.h"
19
20struct FFT_API PffftSetupDeleter {
21 void operator ()(PFFFT_Setup *p){ if (p) Pffft_destroy_setup(p); }
22private:
23 void Pffft_destroy_setup(PFFFT_Setup *);
24};
25using PffftSetupHolder = std::unique_ptr<PFFFT_Setup, PffftSetupDeleter>;
26
27struct FFT_API PffftAllocatorBase {
28 static void *Pffft_aligned_malloc(size_t nb_bytes);
29 static void Pffft_aligned_free(void *);
30};
31
33template<typename T> struct PffftAllocator
34 : std::allocator<T>, protected PffftAllocatorBase
35{
38 template<typename U> PffftAllocator(const PffftAllocator<U>&) {}
39
40 template<typename U> struct rebind { using other = PffftAllocator<U>; };
41 T* allocate(std::size_t n, const void *) {
42 return allocate(n);
43 }
44 T* allocate(std::size_t n) {
45 return static_cast<T*>(Pffft_aligned_malloc(n * sizeof(T)));
46 }
47 void deallocate(T *p, std::size_t n) {
48 if (p) Pffft_aligned_free(p);
49 }
50};
51
55{
56 // see source for pffft_aligned_malloc
57 static constexpr size_t ByteAlignment = 64;
58 static constexpr auto FloatAlignment = ByteAlignment / sizeof(float);
59
60 PffftAlignedCount() = default;
61
63 explicit PffftAlignedCount(size_t nFloats)
64 : value{
65 ((nFloats + (FloatAlignment) - 1) / FloatAlignment) * FloatAlignment }
66 {}
67
70
72 operator size_t() const { return value; }
73
74private:
75 size_t value{};
76};
77
78template<typename Integral>
79inline auto operator * (PffftAlignedCount x, Integral y)
80 -> std::enable_if_t<
81 std::is_unsigned_v<Integral> && sizeof(Integral) <= sizeof(size_t),
83{
84 return PffftAlignedCount(static_cast<size_t>(x) * y);
85}
86
87template<typename Integral>
88inline auto operator * (Integral x, PffftAlignedCount y)
89 -> std::enable_if_t<
90 std::is_unsigned_v<Integral> && sizeof(Integral) <= sizeof(size_t),
92{
93 return PffftAlignedCount(x * static_cast<size_t>(y));
94}
95
96struct PffftFloatVector;
97
99
105 PffftFloats() = default;
106 PffftFloats(const PffftFloats&) = default;
108
112 float *get() const noexcept { return p; }
113
115 p += c; return *this;
116 }
118 {
119 PffftFloats result(p);
120 return result += c;
121 }
123 {
124 PffftFloats result(p);
125 return result += c;
126 }
127
128 explicit operator bool() const noexcept { return p != nullptr; }
129
130private:
131 explicit PffftFloats(float *p) : p{ p } {}
133 float *p{};
134};
135
137
143 PffftConstFloats() = default;
147
151 const float *get() const noexcept { return p; }
152
154 p += c; return *this;
155 }
157 {
158 PffftConstFloats result(p);
159 return result += c;
160 }
162 {
163 PffftConstFloats result(p);
164 return result += c;
165 }
166
167 explicit operator bool() const noexcept { return p != nullptr; }
168
169private:
170 explicit PffftConstFloats(const float *p) : p{ p } {}
172 const float *p{};
173};
174
176
184struct FFT_API PffftFloatVector : std::vector<float, PffftAllocator<float>> {
185 using std::vector<float, PffftAllocator<float>>::vector;
187 PffftFloats aligned(PffftAlignedCount c = {});
189 PffftConstFloats aligned(PffftAlignedCount c = {}) const;
190
194 { return aligned(rowSize * nRow); }
195
198 PffftConstFloats aligned(PffftAlignedCount rowSize, size_t nRow) const
199 { return aligned(rowSize * nRow); }
200};
201
209{
210public:
211 explicit PowerSpectrumGetter(int fftSize);
213
221 void operator()(PffftFloats alignedBuffer, PffftFloats alignedOutput);
222
223private:
224 const int mFftSize;
227};
std::unique_ptr< PFFFT_Setup, PffftSetupDeleter > PffftSetupHolder
auto operator*(PffftAlignedCount x, Integral y) -> std::enable_if_t< std::is_unsigned_v< Integral > &&sizeof(Integral)<=sizeof(size_t), PffftAlignedCount >
Much faster that FFT.h's PowerSpectrum, at least in Short-Time Fourier Transform-like situations,...
PffftFloatVector mWork
PffftSetupHolder mSetup
PffftAlignedCount(size_t nFloats)
Construct from some number of floats, rounding up as needed.
PffftAlignedCount()=default
static constexpr size_t ByteAlignment
PffftAlignedCount(const PffftAlignedCount &)=default
PffftAlignedCount & operator=(const PffftAlignedCount &)=default
static constexpr auto FloatAlignment
static void Pffft_aligned_free(void *)
static void * Pffft_aligned_malloc(size_t nb_bytes)
Aligned memory is required by pffft, so this defines an allocator.
void deallocate(T *p, std::size_t n)
PffftAllocator(const PffftAllocator< U > &)
PffftAllocator(const PffftAllocator &)
T * allocate(std::size_t n)
T * allocate(std::size_t n, const void *)
A read-only pointer to an aligned range of floats.
PffftConstFloats(PffftFloats p)
friend PffftConstFloats operator+(PffftConstFloats p, PffftAlignedCount c)
PffftConstFloats operator+=(PffftAlignedCount c)
PffftConstFloats()=default
PffftConstFloats(const PffftConstFloats &)=default
PffftConstFloats & operator=(const PffftConstFloats &)=default
PffftConstFloats(const float *p)
const float * get() const noexcept
A vector of floats guaranteeing alignment as demanded by pffft.
PffftConstFloats aligned(PffftAlignedCount rowSize, size_t nRow) const
PffftFloats aligned(PffftAlignedCount rowSize, size_t nRow)
A pointer to an aligned range of floats.
PffftFloats(const PffftFloats &)=default
PffftFloats operator+=(PffftAlignedCount c)
friend PffftFloats operator+(PffftFloats p, PffftAlignedCount c)
PffftFloats & operator=(const PffftFloats &)=default
float * get() const noexcept
PffftFloats(float *p)
PffftFloats()=default