├── README.md
├── - Test
├── Peak_Tester
│ ├── Peak_Tester.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── project.pbxproj
│ └── Peak_Tester
│ │ └── main.cpp
├── IR_Manipulation_Tester
│ ├── IR_Manipulation_Tester.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── IR_Manipulation_Tester.xcscheme
│ │ └── project.pbxproj
│ └── IR_Manipulation_Tester
│ │ └── main.cpp
├── FFT_Tester
│ ├── FFT_Tester.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── FFT_Tester.xcscheme
│ │ └── project.pbxproj
│ └── FFT_Tester
│ │ └── main.cpp
└── Window_Tester
│ ├── Window_Tester.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
│ └── Window_Tester
│ └── main.cpp
├── .gitignore
├── HIRT_Multichannel_Convolution
├── ConvolveErrors.h
├── NToMonoConvolve.h
├── TimeDomainConvolve.h
├── NToMonoConvolve.cpp
├── Convolver.h
├── MonoConvolve.h
├── ConvolveSIMD.h
├── PartitionedConvolve.h
├── TimeDomainConvolve.cpp
├── Convolver.cpp
├── MemorySwap.h
└── MonoConvolve.cpp
├── Allocator.hpp
├── LICENSE
├── Interpolation.hpp
├── ThreadLocks.hpp
├── AudioFile
├── OAudioFile.h
├── BaseAudioFile.h
├── IAudioFile.h
└── BaseAudioFile.cpp
├── HISSTools_FFT
└── HISSTools_FFT.cpp
├── RandomGenerator.hpp
├── Statistics.hpp
├── PartialTracker.hpp
├── KernelSmoother.hpp
└── SpectralFunctions.hpp
/README.md:
--------------------------------------------------------------------------------
1 | # HISSTools_Library
2 |
3 | A C++ Library for DSP
4 |
--------------------------------------------------------------------------------
/- Test/Peak_Tester/Peak_Tester.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/- Test/IR_Manipulation_Tester/IR_Manipulation_Tester.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/- Test/FFT_Tester/FFT_Tester.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/- Test/Window_Tester/Window_Tester.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/- Test/FFT_Tester/FFT_Tester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/- Test/Peak_Tester/Peak_Tester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/- Test/Window_Tester/Window_Tester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/- Test/IR_Manipulation_Tester/IR_Manipulation_Tester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Build generated
2 | build/
3 | DerivedData/
4 |
5 | ## Outmoded source tracking
6 | CVS/
7 |
8 | ## Various settings
9 | *.pbxuser
10 | !default.pbxuser
11 | *.mode1
12 | !default.mode1
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata/
20 | _MaxSDK_/
21 |
22 | ## Latex
23 |
24 | *.aux
25 | *.synctex.gz
26 | *.toc
27 | *.log
28 | *.out
29 |
30 | ## Binaries
31 | externals/
32 |
33 | ## Other
34 | *.moved-aside
35 | *.xccheckout
36 | *.xcscmblueprint
37 |
38 | Icon?
39 | .DS_Stor*
40 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/ConvolveErrors.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | enum ConvolveError
5 | {
6 | CONVOLVE_ERR_NONE = 0,
7 | CONVOLVE_ERR_IN_CHAN_OUT_OF_RANGE = 1,
8 | CONVOLVE_ERR_OUT_CHAN_OUT_OF_RANGE = 2,
9 | CONVOLVE_ERR_MEM_UNAVAILABLE = 3,
10 | CONVOLVE_ERR_MEM_ALLOC_TOO_SMALL = 4,
11 | CONVOLVE_ERR_TIME_IMPULSE_TOO_LONG = 5,
12 | CONVOLVE_ERR_TIME_LENGTH_OUT_OF_RANGE = 6,
13 | CONVOLVE_ERR_PARTITION_LENGTH_TOO_LARGE = 7,
14 | CONVOLVE_ERR_FFT_SIZE_MAX_TOO_SMALL = 8,
15 | CONVOLVE_ERR_FFT_SIZE_MAX_TOO_LARGE = 9,
16 | CONVOLVE_ERR_FFT_SIZE_MAX_NON_POWER_OF_TWO = 10,
17 | CONVOLVE_ERR_FFT_SIZE_OUT_OF_RANGE = 11,
18 | CONVOLVE_ERR_FFT_SIZE_NON_POWER_OF_TWO = 12,
19 | };
20 |
--------------------------------------------------------------------------------
/Allocator.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef ALLOCATOR_HPP
3 | #define ALLOCATOR_HPP
4 |
5 | #include
6 |
7 | #include "SIMDSupport.hpp"
8 |
9 | namespace impl
10 | {
11 | typedef void *(*allocate_function)(size_t);
12 | typedef void (*free_function)(void *);
13 | };
14 |
15 | // A template for wrapping functions as an allocator
16 |
17 | template
18 | struct function_allocator
19 | {
20 | template
21 | T* allocate(size_t size) { return reinterpret_cast(alloc(size * sizeof(T))); }
22 |
23 | template
24 | void deallocate(T *ptr) { dealloc(ptr); }
25 | };
26 |
27 | using malloc_allocator = function_allocator;
28 |
29 | // Aligned allocator
30 |
31 | struct aligned_allocator
32 | {
33 | template
34 | T* allocate(size_t size) { return allocate_aligned(size); }
35 |
36 | template
37 | void deallocate(T *ptr) { deallocate_aligned(ptr); }
38 | };
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/NToMonoConvolve.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "MonoConvolve.h"
5 | #include "ConvolveErrors.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | namespace HISSTools
12 | {
13 | class NToMonoConvolve
14 | {
15 |
16 | public:
17 |
18 | NToMonoConvolve(uint32_t input_chans, uintptr_t maxLength, LatencyMode latency);
19 |
20 | ConvolveError resize(uint32_t inChan, uintptr_t impulse_length);
21 | ConvolveError set(uint32_t inChan, const float *input, uintptr_t impulse_length, bool resize);
22 | ConvolveError reset(uint32_t inChan);
23 |
24 | void process(const float * const* ins, float *out, float *temp, size_t numSamples, size_t active_in_chans);
25 |
26 | private:
27 |
28 | template
29 | ConvolveError doChannel(Method method, uint32_t inChan, Args...args);
30 |
31 | std::vector mConvolvers;
32 |
33 | uint32_t mNumInChans;
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/- Test/Peak_Tester/Peak_Tester/main.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // main.cpp
3 | // Peak_Tester
4 | //
5 | // Created by Alex Harker on 19/06/2021.
6 | // Copyright © 2021 AHarker. All rights reserved.
7 | //
8 |
9 | #include
10 |
11 | #include "PartialTracker.hpp"
12 |
13 | using Tracker = partial_tracker;
14 |
15 | void post_tracks(Tracker& tracker, int N)
16 | {
17 | for (int i = 0; i < N; i++)
18 | {
19 | track t = tracker.get_track(i);
20 |
21 | std::cout << "index " << i << "\n";
22 | std::cout << "active " << t.active() << "\n";
23 | std::cout << "state " << static_cast(t.m_state) << "\n";
24 | std::cout << "freq " << t.m_peak.freq() << "\n";
25 | std::cout << "amp " << t.m_peak.amp() << "\n";
26 | }
27 | }
28 |
29 | int main(int argc, const char * argv[])
30 | {
31 | Tracker tracker(12, 12);
32 | peak peaks[10];
33 |
34 | for (int i = 0; i < 10; i++)
35 | peaks[i] = peak((i + 1) * 10.0, 1.0);
36 |
37 | tracker.process(peaks, 10, 0.0);
38 |
39 | post_tracks(tracker, 12);
40 |
41 | for (int i = 0; i < 10; i++)
42 | peaks[i] = peak((10 - i) * 10.0 + 2, 1.0);
43 |
44 | tracker.process(peaks, 8, 0.0);
45 |
46 | post_tracks(tracker, 12);
47 |
48 | return 0;
49 | }
50 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/TimeDomainConvolve.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "ConvolveErrors.h"
5 |
6 | #include
7 |
8 | namespace HISSTools
9 | {
10 | class TimeDomainConvolve
11 | {
12 |
13 | public:
14 |
15 | TimeDomainConvolve(uintptr_t offset, uintptr_t length);
16 | ~TimeDomainConvolve();
17 |
18 | // Non-moveable and copyable
19 |
20 | TimeDomainConvolve(TimeDomainConvolve& obj) = delete;
21 | TimeDomainConvolve& operator = (TimeDomainConvolve& obj) = delete;
22 | TimeDomainConvolve(TimeDomainConvolve&& obj) = delete;
23 | TimeDomainConvolve& operator = (TimeDomainConvolve&& obj) = delete;
24 |
25 | ConvolveError setLength(uintptr_t length);
26 | void setOffset(uintptr_t offset);
27 |
28 | ConvolveError set(const float *input, uintptr_t length);
29 | void reset();
30 |
31 | bool process(const float *in, float *out, uintptr_t numSamples);
32 |
33 | private:
34 |
35 | // Internal buffers
36 |
37 | float *mImpulseBuffer;
38 | float *mInputBuffer;
39 |
40 | uintptr_t mInputPosition;
41 | uintptr_t mImpulseLength;
42 |
43 | uintptr_t mOffset;
44 | uintptr_t mLength;
45 |
46 | // Flags
47 |
48 | bool mReset;
49 | };
50 | }
51 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/NToMonoConvolve.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "NToMonoConvolve.h"
3 |
4 | HISSTools::NToMonoConvolve::NToMonoConvolve(uint32_t inChans, uintptr_t maxLength, LatencyMode latency)
5 | : mNumInChans(inChans)
6 | {
7 | for (uint32_t i = 0; i < mNumInChans; i++)
8 | mConvolvers.emplace_back(maxLength, latency);
9 | }
10 |
11 | template
12 | ConvolveError HISSTools::NToMonoConvolve::doChannel(Method method, uint32_t inChan, Args...args)
13 | {
14 | if (inChan < mNumInChans)
15 | return (mConvolvers[inChan].*method)(args...);
16 | else
17 | return CONVOLVE_ERR_IN_CHAN_OUT_OF_RANGE;
18 | }
19 |
20 | ConvolveError HISSTools::NToMonoConvolve::resize(uint32_t inChan, uintptr_t impulse_length)
21 | {
22 | return doChannel(&MonoConvolve::resize, inChan, impulse_length);
23 | }
24 |
25 | ConvolveError HISSTools::NToMonoConvolve::set(uint32_t inChan, const float *input, uintptr_t impulse_length, bool resize)
26 | {
27 | return doChannel(&MonoConvolve::set, inChan, input, impulse_length, resize);
28 | }
29 |
30 | ConvolveError HISSTools::NToMonoConvolve::reset(uint32_t inChan)
31 | {
32 | return doChannel(&MonoConvolve::reset, inChan);
33 | }
34 |
35 | void HISSTools::NToMonoConvolve::process(const float * const* ins, float *out, float *temp, size_t numSamples, size_t activeInChans)
36 | {
37 | // Zero output then convolve
38 |
39 | std::fill_n(out, numSamples, 0.f);
40 |
41 | for (uint32_t i = 0; i < mNumInChans && i < activeInChans ; i++)
42 | mConvolvers[i].process(ins[i], temp, out, numSamples, true);
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2019, Alex Harker
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/Convolver.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "MemorySwap.h"
5 | #include "NToMonoConvolve.h"
6 | #include "ConvolveErrors.h"
7 |
8 | #include
9 | #include
10 |
11 | namespace HISSTools
12 | {
13 | class Convolver
14 | {
15 | struct SIMDSettings
16 | {
17 | SIMDSettings();
18 | ~SIMDSettings();
19 |
20 | unsigned int mOldMXCSR;
21 | };
22 |
23 | public:
24 |
25 | Convolver(uint32_t numIns, uint32_t numOuts, LatencyMode latency);
26 | Convolver(uint32_t numIO, LatencyMode latency);
27 |
28 | virtual ~Convolver() throw();
29 |
30 | // Clear IRs
31 |
32 | void clear(bool resize);
33 | void clear(uint32_t inChan, uint32_t outChan, bool resize);
34 |
35 | // DSP Engine Reset
36 |
37 | void reset();
38 | ConvolveError reset(uint32_t inChan, uint32_t outChan);
39 |
40 | // Resize and set IR
41 |
42 | ConvolveError resize(uint32_t inChan, uint32_t outChan, uintptr_t impulseLength);
43 |
44 | ConvolveError set(uint32_t inChan, uint32_t outChan, const float* input, uintptr_t length, bool resize);
45 | ConvolveError set(uint32_t inChan, uint32_t outChan, const double* input, uintptr_t length, bool resize);
46 |
47 | // DSP
48 |
49 | void process(const double * const* ins, double** outs, size_t numIns, size_t numOuts, size_t numSamples);
50 | void process(const float * const* ins, float** outs, size_t numIns, size_t numOuts, size_t numSamples);
51 |
52 | private:
53 |
54 | void tempSetup(float* memPointer, uintptr_t maxFrameSize);
55 |
56 | // Data
57 |
58 | uint32_t mNumIns;
59 | uint32_t mNumOuts;
60 | bool mN2M;
61 |
62 | std::vector mInTemps;
63 | float* mTemp1;
64 | float* mTemp2;
65 |
66 | MemorySwap mTemporaryMemory;
67 |
68 | std::vector mConvolvers;
69 | };
70 | }
71 |
--------------------------------------------------------------------------------
/Interpolation.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef INTERPOLATION_HPP
3 | #define INTERPOLATION_HPP
4 |
5 | // Enumeration of interpolation types
6 |
7 | enum class InterpType { None, Linear, CubicHermite, CubicLagrange, CubicBSpline };
8 |
9 | // Linear
10 |
11 | template
12 | struct linear_interp
13 | {
14 | T operator()(const T& x, const T& y0, const T& y1) { return (y0 + x * ((y1 - y0))); }
15 | };
16 |
17 | // Cubic Hermite
18 |
19 | template
20 | struct cubic_hermite_interp
21 | {
22 | cubic_hermite_interp() : _5div2(2.5), _3div2(1.5), _1div2(0.5) {}
23 |
24 | T operator()(const T& x, const T& y0, const T& y1, const T& y2, const T& y3)
25 | {
26 | const T c0 = y1;
27 | const T c1 = _1div2 * (y2 - y0);
28 | const T c2 = y0 - _5div2 * y1 + y2 + y2 - _1div2 * y3;
29 | const T c3 = _1div2 * (y3 - y0) + _3div2 * (y1 - y2);
30 |
31 | return (((c3 * x + c2) * x + c1) * x + c0);
32 | }
33 |
34 | private:
35 |
36 | const T _5div2;
37 | const T _3div2;
38 | const T _1div2;
39 | };
40 |
41 | // Cubic Lagrange
42 |
43 | template
44 | struct cubic_lagrange_interp
45 | {
46 | cubic_lagrange_interp() : _1div3(T(1)/T(3)), _1div6(T(1)/T(6)), _1div2(0.5) {}
47 |
48 | T operator()(const T& x, const T& y0, const T& y1, const T& y2, const T& y3)
49 | {
50 | const T c0 = y1;
51 | const T c1 = y2 - _1div3 * y0 - _1div2 * y1 - _1div6 * y3;
52 | const T c2 = _1div2 * (y0 + y2) - y1;
53 | const T c3 = _1div6 * (y3 - y0) + _1div2 * (y1 - y2);
54 |
55 | return (((c3 * x + c2) * x + c1) * x + c0);
56 | }
57 |
58 | private:
59 |
60 | const T _1div3;
61 | const T _1div6;
62 | const T _1div2;
63 | };
64 |
65 | // Cubic B-spline
66 |
67 | template
68 | struct cubic_bspline_interp
69 | {
70 | cubic_bspline_interp() : _2div3(T(2)/T(3)), _1div6(T(1)/T(6)), _1div2(0.5) {}
71 |
72 | T operator()(const T& x, const T& y0, const T& y1, const T& y2, const T& y3)
73 | {
74 | const T y0py2 = y0 + y2;
75 | const T c0 = _1div6 * y0py2 + _2div3 * y1;
76 | const T c1 = _1div2 * (y2 - y0);
77 | const T c2 = _1div2 * y0py2 - y1;
78 | const T c3 = _1div2 * (y1 - y2) + _1div6 * (y3 - y0);
79 |
80 | return (((c3 * x + c2) * x + c1) * x + c0);
81 | }
82 |
83 | private:
84 |
85 | const T _2div3;
86 | const T _1div6;
87 | const T _1div2;
88 | };
89 |
90 | #endif /* Interpolation_h */
91 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/MonoConvolve.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "PartitionedConvolve.h"
5 | #include "TimeDomainConvolve.h"
6 | #include "ConvolveErrors.h"
7 | #include "MemorySwap.h"
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | enum LatencyMode
15 | {
16 | kLatencyZero,
17 | kLatencyShort,
18 | kLatencyMedium,
19 | } ;
20 |
21 | namespace HISSTools
22 | {
23 | class MonoConvolve
24 | {
25 | typedef MemorySwap::Ptr PartPtr;
26 | typedef std::unique_ptr PartUniquePtr;
27 |
28 | public:
29 |
30 | MonoConvolve(uintptr_t maxLength, LatencyMode latency);
31 | MonoConvolve(uintptr_t maxLength, bool zeroLatency, uint32_t A, uint32_t B = 0, uint32_t C = 0, uint32_t D = 0);
32 |
33 | // Moveable but not copyable
34 |
35 | MonoConvolve(MonoConvolve& obj) = delete;
36 | MonoConvolve& operator = (MonoConvolve& obj) = delete;
37 | MonoConvolve(MonoConvolve&& obj);
38 | MonoConvolve& operator = (MonoConvolve&& obj);
39 |
40 | void setResetOffset(intptr_t offset = -1);
41 |
42 | ConvolveError resize(uintptr_t length);
43 | ConvolveError set(const float *input, uintptr_t length, bool requestResize);
44 | ConvolveError reset();
45 |
46 | void process(const float *in, float *temp, float *out, uintptr_t numSamples, bool accumulate = false);
47 |
48 | void setPartitions(uintptr_t maxLength, bool zeroLatency, uint32_t A, uint32_t B = 0, uint32_t C = 0, uint32_t D = 0);
49 |
50 | private:
51 |
52 | void setResetOffset(PartPtr &part4, intptr_t offset = -1);
53 |
54 | size_t numSizes() { return mSizes.size(); }
55 |
56 | MemorySwap::AllocFunc mAllocator;
57 |
58 | std::vector mSizes;
59 |
60 | std::unique_ptr mTime1;
61 | std::unique_ptr mPart1;
62 | std::unique_ptr mPart2;
63 | std::unique_ptr mPart3;
64 |
65 | MemorySwap mPart4;
66 |
67 | uintptr_t mLength;
68 |
69 | intptr_t mPart4ResetOffset;
70 | bool mReset;
71 |
72 | // Random Number Generation
73 |
74 | std::default_random_engine mRandGenerator;
75 | std::uniform_int_distribution mRandDistribution;
76 | };
77 | }
78 |
--------------------------------------------------------------------------------
/ThreadLocks.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef THREADLOCKS_HPP
3 | #define THREADLOCKS_HPP
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #ifdef __linux__
11 |
12 | // Linux specific definitions
13 |
14 | namespace OS_Specific
15 | {
16 | inline void thread_nano_sleep()
17 | {
18 | std::this_thread::sleep_for(std::chrono::nanoseconds(100));
19 | }
20 | }
21 |
22 | #elif defined(__APPLE__)
23 |
24 | // OSX specific definitions
25 |
26 | namespace OS_Specific
27 | {
28 | inline void thread_nano_sleep()
29 | {
30 | std::this_thread::sleep_for(std::chrono::nanoseconds(100));
31 | }
32 | }
33 |
34 | #else
35 |
36 | // Windows OS specific definitions
37 |
38 | #include
39 |
40 | namespace OS_Specific
41 | {
42 | inline void thread_nano_sleep()
43 | {
44 | SwitchToThread();
45 | }
46 | }
47 |
48 | #endif
49 |
50 |
51 | class thread_lock
52 | {
53 | using Clock = std::chrono::steady_clock;
54 |
55 | public:
56 |
57 | thread_lock() {}
58 | ~thread_lock() { acquire(); }
59 |
60 | // Non-copyable
61 |
62 | thread_lock(const thread_lock&) = delete;
63 | thread_lock& operator=(const thread_lock&) = delete;
64 |
65 | void acquire()
66 | {
67 | for (int i = 0; i < 10; i++)
68 | if (attempt())
69 | return;
70 |
71 | auto timeOut = Clock::now() + std::chrono::nanoseconds(10000);
72 |
73 | while (Clock::now() < timeOut)
74 | if (attempt())
75 | return;
76 |
77 | while (!attempt())
78 | OS_Specific::thread_nano_sleep();
79 | }
80 |
81 | bool attempt() { return !m_atomic_lock.test_and_set(); }
82 | void release() { m_atomic_lock.clear(); }
83 |
84 | private:
85 |
86 | std::atomic_flag m_atomic_lock = ATOMIC_FLAG_INIT;
87 | };
88 |
89 |
90 | // A generic lock holder using RAII
91 |
92 | template
93 | class lock_hold
94 | {
95 | public:
96 |
97 | lock_hold() : m_lock(nullptr) {}
98 | lock_hold(thread_lock *lock) : m_lock(lock) { if (m_lock) m_lock->*acquire_method(); }
99 | ~lock_hold() { if (m_lock) m_lock->release(); }
100 |
101 | // Non-copyable
102 |
103 | lock_hold(const lock_hold&) = delete;
104 | lock_hold& operator=(const lock_hold&) = delete;
105 |
106 | void release()
107 | {
108 | if (m_lock)
109 | {
110 | (m_lock->*release_method)();
111 | m_lock = nullptr;
112 | }
113 | }
114 |
115 | private:
116 |
117 | thread_lock *m_lock;
118 | };
119 |
120 | #endif /* THREADLOCKS_HPP */
121 |
--------------------------------------------------------------------------------
/AudioFile/OAudioFile.h:
--------------------------------------------------------------------------------
1 | #ifndef _HISSTOOLS_OAUDIOFILE_
2 | #define _HISSTOOLS_OAUDIOFILE_
3 |
4 | #include "BaseAudioFile.h"
5 | #include
6 |
7 | namespace HISSTools
8 | {
9 | class OAudioFile : public BaseAudioFile
10 | {
11 | public:
12 | OAudioFile();
13 | OAudioFile(const std::string&, FileType, PCMFormat, uint16_t channels, double sr);
14 | OAudioFile(const std::string&, FileType, PCMFormat, uint16_t channels, double sr, Endianness);
15 |
16 | ~OAudioFile();
17 |
18 | void open(const std::string&, FileType, PCMFormat, uint16_t channels, double sr);
19 | void open(const std::string&, FileType, PCMFormat, uint16_t channels, double sr, Endianness);
20 | void close();
21 | bool isOpen();
22 | void seek(FrameCount position = 0);
23 | FrameCount getPosition();
24 |
25 | void writeInterleaved(const double* input, FrameCount numFrames);
26 | void writeInterleaved(const float* input, FrameCount numFrames);
27 |
28 | void writeChannel(const double* input, FrameCount numFrames, uint16_t channel);
29 | void writeChannel(const float* input, FrameCount numFrames, uint16_t channel);
30 | void writeRaw(const char *input, FrameCount numFrames) { writePCMData(input, numFrames); }
31 |
32 | protected:
33 |
34 | ByteCount getHeaderSize() const;
35 |
36 | private:
37 |
38 | ByteCount positionInternal();
39 | bool seekInternal(ByteCount position);
40 | bool seekRelativeInternal(ByteCount offset);
41 | bool writeInternal(const char* buffer, ByteCount bytes);
42 |
43 | bool putU64(uint64_t value, Endianness fileEndianness);
44 | bool putU32(uint32_t value, Endianness fileEndianness);
45 | bool putU24(uint32_t value, Endianness fileEndianness);
46 | bool putU16(uint32_t value, Endianness fileEndianness);
47 | bool putU08(uint32_t value);
48 |
49 | bool putPadByte();
50 |
51 | bool putExtended(double);
52 | bool putPString(const char* string);
53 |
54 | bool putTag(const char* tag);
55 | bool putChunk(const char* tag, uint32_t size);
56 |
57 | void writeWaveHeader();
58 | void writeAIFCHeader();
59 |
60 | uint32_t inputToU32(double input, int32_t bitDepth);
61 | uint8_t inputToU8(double input);
62 |
63 | bool resize(FrameCount numFrames);
64 | bool updateHeader();
65 | template void writeAudio(const T* input, FrameCount numFrames, int32_t channel = -1);
66 | bool writePCMData(const char* input, FrameCount numFrames);
67 |
68 | const char *getCompressionTag();
69 | const char *getCompressionString();
70 |
71 | // Data
72 |
73 | std::ofstream mFile;
74 | };
75 | }
76 |
77 | #endif /* _HISSTOOLS_OAUDIOFILE_ */
78 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/ConvolveSIMD.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | template
5 | struct SIMDVector
6 | {
7 | static constexpr int size = vec_size;
8 | typedef T scalar_type;
9 |
10 | SIMDVector() {}
11 | SIMDVector(U a) : mVal(a) {}
12 |
13 | U mVal;
14 | };
15 |
16 | #if defined __arm__ || defined __arm64__
17 |
18 | #include
19 |
20 | struct ARMFloat : public SIMDVector
21 | {
22 | ARMFloat() {}
23 | ARMFloat(uint32x4_t a) : SIMDVector(a) {}
24 | ARMFloat(float a) : SIMDVector(vdupq_n_f32(a)) {}
25 |
26 | friend ARMFloat operator + (const ARMFloat& a, const ARMFloat& b) { return vaddq_f32(a.mVal, b.mVal); }
27 | friend ARMFloat operator - (const ARMFloat& a, const ARMFloat& b) { return vsubq_f32(a.mVal, b.mVal); }
28 | friend ARMFloat operator * (const ARMFloat& a, const ARMFloat& b) { return vmulq_f32(a.mVal, b.mVal); }
29 |
30 | ARMFloat operator += (const ARMFloat& a)
31 | {
32 | *this = *this + a;
33 | return *this;
34 | }
35 |
36 | static ARMFloat unaligned_load(const float* ptr) { return vld1q_f32(ptr); }
37 |
38 | void unaligned_store(float* ptr)
39 | {
40 | vst1q_f32(ptr, mVal);
41 | }
42 |
43 | float sum()
44 | {
45 | float values[4];
46 | unaligned_store(values);
47 | return values[0] + values[1] + values[2] + values[3];
48 | }
49 | };
50 |
51 | typedef ARMFloat FloatVector;
52 |
53 | #else
54 |
55 | #ifdef __APPLE__
56 | #include
57 | #else
58 | #include
59 | #include
60 | #endif
61 |
62 | struct SSEFloat : public SIMDVector
63 | {
64 | SSEFloat() {}
65 | SSEFloat(__m128 a) : SIMDVector(a) {}
66 | SSEFloat(float a) : SIMDVector(_mm_set1_ps(a)) {}
67 |
68 | friend SSEFloat operator + (const SSEFloat& a, const SSEFloat& b) { return _mm_add_ps(a.mVal, b.mVal); }
69 | friend SSEFloat operator - (const SSEFloat& a, const SSEFloat& b) { return _mm_sub_ps(a.mVal, b.mVal); }
70 | friend SSEFloat operator * (const SSEFloat& a, const SSEFloat& b) { return _mm_mul_ps(a.mVal, b.mVal); }
71 |
72 | SSEFloat operator += (const SSEFloat& a)
73 | {
74 | *this = *this + a;
75 | return *this;
76 | }
77 |
78 | static SSEFloat unaligned_load(const float* ptr) { return _mm_loadu_ps(ptr); }
79 |
80 | void unaligned_store(float* ptr)
81 | {
82 | _mm_storeu_ps(ptr, mVal);
83 | }
84 |
85 | float sum()
86 | {
87 | float values[4];
88 | unaligned_store(values);
89 | return values[0] + values[1] + values[2] + values[3];
90 | }
91 | };
92 |
93 | typedef SSEFloat FloatVector;
94 |
95 | #endif
96 |
97 | #ifdef __APPLE__
98 | #define ALIGNED_MALLOC malloc
99 | #define ALIGNED_FREE free
100 | #elif defined _WIN32
101 | #include
102 | #define ALIGNED_MALLOC(x) _aligned_malloc(x, 16)
103 | #define ALIGNED_FREE(x) _aligned_free(x)
104 | #else
105 | #define ALIGNED_MALLOC(x) aligned_alloc(16, x);
106 | #define ALIGNED_FREE free
107 | #endif
108 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/PartitionedConvolve.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "../HISSTools_FFT/HISSTools_FFT.h"
5 |
6 | #include "ConvolveErrors.h"
7 |
8 | #include
9 | #include
10 |
11 | namespace HISSTools
12 | {
13 | class PartitionedConvolve
14 | {
15 | // N.B. MIN_FFT_SIZE_LOG2 should never be smaller than 4, as below code assumes loop unroll of vectors (4 vals) by 4 (== 16 or 2^4)
16 | // MAX_FFT_SIZE_LOG2 is perhaps conservative right now, but it is easy to increase this if necessary
17 |
18 | static constexpr int MIN_FFT_SIZE_LOG2 = 5;
19 | static constexpr int MAX_FFT_SIZE_LOG2 = 20;
20 |
21 | public:
22 |
23 | PartitionedConvolve(uintptr_t maxFFTSize, uintptr_t maxLength, uintptr_t offset, uintptr_t length);
24 | ~PartitionedConvolve();
25 |
26 | // Non-moveable and copyable
27 |
28 | PartitionedConvolve(PartitionedConvolve& obj) = delete;
29 | PartitionedConvolve& operator = (PartitionedConvolve& obj) = delete;
30 | PartitionedConvolve(PartitionedConvolve&& obj) = delete;
31 | PartitionedConvolve& operator = (PartitionedConvolve&& obj) = delete;
32 |
33 | ConvolveError setFFTSize(uintptr_t FFTSize);
34 | ConvolveError setLength(uintptr_t length);
35 | void setOffset(uintptr_t offset);
36 | void setResetOffset(intptr_t offset = -1);
37 |
38 | ConvolveError set(const float *input, uintptr_t length);
39 | void reset();
40 |
41 | bool process(const float *in, float *out, uintptr_t numSamples);
42 |
43 | private:
44 |
45 | uintptr_t getFFTSize() { return uintptr_t(1) << mFFTSizeLog2; }
46 | uintptr_t getMaxFFTSize() { return uintptr_t(1) << mMaxFFTSizeLog2; }
47 |
48 | void processPartition(FFT_SPLIT_COMPLEX_F in1, FFT_SPLIT_COMPLEX_F in2, FFT_SPLIT_COMPLEX_F out, uintptr_t numBins);
49 | ConvolveError setMaxFFTSize(uintptr_t max_fft_size);
50 | uintptr_t log2(uintptr_t value);
51 |
52 | // Parameters
53 |
54 | uintptr_t mOffset;
55 | uintptr_t mLength;
56 | uintptr_t mMaxImpulseLength;
57 |
58 | // FFT variables
59 |
60 | FFT_SETUP_F mFFTSetup;
61 |
62 | uintptr_t mMaxFFTSizeLog2;
63 | uintptr_t mFFTSizeLog2;
64 | uintptr_t mRWCounter;
65 |
66 | // Scheduling variables
67 |
68 | uintptr_t mInputPosition;
69 | uintptr_t mPartitionsDone;
70 | uintptr_t mLastPartition;
71 | uintptr_t mNumPartitions;
72 | uintptr_t mValidPartitions;
73 |
74 | // Internal buffers
75 |
76 | float *mFFTBuffers[4];
77 |
78 | FFT_SPLIT_COMPLEX_F mImpulseBuffer;
79 | FFT_SPLIT_COMPLEX_F mInputBuffer;
80 | FFT_SPLIT_COMPLEX_F mAccumBuffer;
81 | FFT_SPLIT_COMPLEX_F mPartitionTemp;
82 |
83 | // Flags
84 |
85 | intptr_t mResetOffset;
86 | bool mResetFlag;
87 |
88 | // Random number generation
89 |
90 | std::default_random_engine mRandGenerator;
91 | std::uniform_int_distribution mRandDistribution;
92 | };
93 | }
94 |
--------------------------------------------------------------------------------
/- Test/FFT_Tester/FFT_Tester.xcodeproj/xcshareddata/xcschemes/FFT_Tester.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/- Test/IR_Manipulation_Tester/IR_Manipulation_Tester.xcodeproj/xcshareddata/xcschemes/IR_Manipulation_Tester.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/AudioFile/BaseAudioFile.h:
--------------------------------------------------------------------------------
1 | #ifndef _HISSTOOLS_BASEAUDIOFILE_
2 | #define _HISSTOOLS_BASEAUDIOFILE_
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace HISSTools
10 | {
11 | class BaseAudioFile
12 | {
13 |
14 | public:
15 |
16 | typedef uint32_t FrameCount;
17 | typedef uintptr_t ByteCount;
18 |
19 | enum FileType
20 | {
21 | kAudioFileNone,
22 | kAudioFileAIFF,
23 | kAudioFileAIFC,
24 | kAudioFileWAVE
25 | };
26 | enum PCMFormat
27 | {
28 | kAudioFileInt8,
29 | kAudioFileInt16,
30 | kAudioFileInt24,
31 | kAudioFileInt32,
32 | kAudioFileFloat32,
33 | kAudioFileFloat64
34 | };
35 | enum Endianness
36 | {
37 | kAudioFileLittleEndian,
38 | kAudioFileBigEndian
39 | };
40 | enum NumberFormat
41 | {
42 | kAudioFileInt,
43 | kAudioFileFloat
44 | };
45 |
46 | enum Error
47 | {
48 | ERR_NONE = 0,
49 |
50 | ERR_MEM_COULD_NOT_ALLOCATE = 1 << 0,
51 |
52 | ERR_FILE_ERROR = 1 << 1,
53 | ERR_FILE_COULDNT_OPEN = 1 << 2,
54 | ERR_FILE_BAD_FORMAT = 1 << 3,
55 | ERR_FILE_UNKNOWN_FORMAT = 1 << 4,
56 | ERR_FILE_UNSUPPORTED_PCM_FORMAT = 1 << 5,
57 |
58 | ERR_AIFC_WRONG_VERSION = 1 << 6,
59 | ERR_AIFC_UNSUPPORTED_FORMAT = 1 << 7,
60 |
61 | ERR_WAVE_UNSUPPORTED_FORMAT = 1 << 8,
62 |
63 | ERR_FILE_COULDNT_WRITE = 1 << 9,
64 | };
65 |
66 | enum AiffVersion
67 | {
68 | AIFC_CURRENT_SPECIFICATION = 0xA2805140
69 | };
70 |
71 | BaseAudioFile();
72 | virtual ~BaseAudioFile();
73 |
74 | FileType getFileType() const;
75 | PCMFormat getPCMFormat() const;
76 | Endianness getHeaderEndianness() const;
77 | Endianness getAudioEndianness() const;
78 | double getSamplingRate() const;
79 | uint16_t getChannels() const;
80 | FrameCount getFrames() const;
81 | uint16_t getBitDepth() const;
82 | uint16_t getByteDepth() const;
83 | ByteCount getFrameByteCount() const;
84 | NumberFormat getNumberFormat() const;
85 |
86 | static std::string getErrorString(Error error);
87 | static std::vector extractErrorsFromFlags(int flags);
88 | std::vector getErrors() const;
89 |
90 | int getErrorFlags() const;
91 | bool getIsError() const;
92 | void clearErrorFlags();
93 |
94 | static uint16_t findBitDepth(PCMFormat);
95 | static NumberFormat findNumberFormat(PCMFormat);
96 |
97 | virtual void close();
98 | virtual bool isOpen() = 0;
99 | virtual void seek(FrameCount position) = 0;
100 | virtual FrameCount getPosition() = 0;
101 |
102 | protected:
103 |
104 | ByteCount getPCMOffset() const;
105 |
106 | void setFileType(FileType);
107 | void setPCMFormat(PCMFormat);
108 | void setHeaderEndianness(Endianness);
109 | void setAudioEndianness(Endianness);
110 | void setSamplingRate(double);
111 | void setChannels(uint16_t);
112 | void setFrames(FrameCount);
113 | void setPCMOffset(ByteCount);
114 |
115 | void setErrorFlags(int flags);
116 | void setErrorBit(Error error);
117 |
118 | private:
119 | FileType mFileType;
120 | PCMFormat mPCMFormat;
121 | Endianness mHeaderEndianness;
122 | Endianness mAudioEndianness;
123 |
124 | double mSamplingRate;
125 | uint16_t mNumChannels;
126 | FrameCount mNumFrames;
127 | size_t mPCMOffset;
128 |
129 | int mErrorFlags;
130 | };
131 | }
132 |
133 | #endif
134 |
--------------------------------------------------------------------------------
/AudioFile/IAudioFile.h:
--------------------------------------------------------------------------------
1 | #ifndef _HISSTOOLS_IAUDIOFILE_
2 | #define _HISSTOOLS_IAUDIOFILE_
3 |
4 | #include "BaseAudioFile.h"
5 | #include
6 |
7 | namespace HISSTools
8 | {
9 | // FIX - check types, errors and returns
10 |
11 | class IAudioFile : public BaseAudioFile
12 | {
13 | enum AiffTag
14 | {
15 | AIFC_TAG_UNKNOWN = 0x0,
16 | AIFC_TAG_VERSION = 0x1,
17 | AIFC_TAG_COMMON = 0x2,
18 | AIFC_TAG_AUDIO = 0x4
19 | };
20 | enum AifcCompression
21 | {
22 | AIFC_COMPRESSION_UNKNOWN,
23 | AIFC_COMPRESSION_NONE,
24 | AIFC_COMPRESSION_LITTLE_ENDIAN,
25 | AIFC_COMPRESSION_FLOAT
26 | };
27 |
28 | public:
29 |
30 | // Constructor and Destructor
31 |
32 | IAudioFile(const std::string& = std::string());
33 | ~IAudioFile();
34 |
35 | // File Open / Close
36 |
37 | void open(const std::string& i);
38 | void close();
39 | bool isOpen();
40 |
41 | // File Position
42 |
43 | void seek(FrameCount position = 0);
44 | FrameCount getPosition();
45 |
46 | // File Reading
47 |
48 | void readRaw(void* output, FrameCount numFrames);
49 |
50 | void readInterleaved(double* output, FrameCount numFrames);
51 | void readInterleaved(float* output, FrameCount numFrames);
52 |
53 | void readChannel(double* output, FrameCount numFrames, uint16_t channel);
54 | void readChannel(float* output, FrameCount numFrames, uint16_t channel);
55 |
56 | private:
57 |
58 | // Internal File Handling
59 |
60 | bool readInternal(char* buffer, ByteCount numBytes);
61 | bool seekInternal(ByteCount position);
62 | bool advanceInternal(ByteCount offset);
63 | ByteCount positionInternal();
64 |
65 | // Extracting Single Values
66 |
67 | uint64_t getU64(const char* bytes, Endianness fileEndianness) const;
68 | uint32_t getU32(const char* bytes, Endianness fileEndianness) const;
69 | uint32_t getU24(const char* bytes, Endianness fileEndianness) const;
70 | uint32_t getU16(const char* bytes, Endianness fileEndianness) const;
71 |
72 | // Conversion
73 |
74 | double extendedToDouble(const char* bytes) const;
75 | template void u32ToOutput(T* output, uint32_t value);
76 | template void u8ToOutput(T* output, uint8_t value);
77 | template void float32ToOutput(T* output, uint32_t value);
78 | template void float64ToOutput(T* output, uint64_t value);
79 |
80 | // Chunk Reading
81 |
82 | static bool matchTag(const char* a, const char* b);
83 | bool readChunkHeader(char* tag, uint32_t& chunkSize);
84 | bool findChunk(const char* searchTag, uint32_t& chunkSize);
85 | bool readChunk(char* data, uint32_t readSize, uint32_t chunkSize);
86 |
87 | // PCM Format Helpers
88 |
89 | static Error findPCMFormat(uint16_t, NumberFormat, PCMFormat&);
90 | void setPCMFormat(uint16_t bitDepth, NumberFormat format);
91 |
92 | // AIFF Helpers
93 |
94 | bool getAIFFChunkHeader(AiffTag& enumeratedTag, uint32_t& chunkSize);
95 | AifcCompression getAIFCCompression(const char* tag, uint16_t& bitDepth) const;
96 |
97 | // Parse Headers
98 |
99 | void parseHeader();
100 | void parseAIFFHeader(const char* fileSubtype);
101 | void parseWaveHeader(const char* fileType);
102 |
103 | // Internal Typed Audio Read
104 |
105 | template
106 | void readAudio(T* output, FrameCount numFrames, int32_t channel = -1);
107 |
108 | // Data
109 |
110 | std::ifstream mFile;
111 | char *mBuffer;
112 | };
113 | }
114 |
115 | #endif
116 |
--------------------------------------------------------------------------------
/- Test/IR_Manipulation_Tester/IR_Manipulation_Tester/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "../../../SpectralFunctions.hpp"
9 |
10 | // Output
11 |
12 | void tabbedOut(const std::string& name, const std::string& text, int tab = 25)
13 | {
14 | std::cout << std::setw(tab) << std::setfill(' ');
15 | std::cout.setf(std::ios::left);
16 | std::cout.unsetf(std::ios::right);
17 | std::cout << name;
18 | std::cout.unsetf(std::ios::left);
19 | std::cout << text << "\n";
20 | }
21 |
22 | template
23 | std::string to_string_with_precision(const T a_value, const int n = 4, bool fixed = true)
24 | {
25 | std::ostringstream out;
26 | if (fixed)
27 | out << std::setprecision(n) << std::fixed << a_value;
28 | else
29 | out << std::setprecision(n) << a_value;
30 |
31 | return out.str();
32 | }
33 |
34 | // Timing
35 |
36 | class Timer
37 | {
38 |
39 | public:
40 |
41 | Timer() : mStart(0), mStore1(0), mStore2(0) {}
42 |
43 | void start()
44 | {
45 | mStart = mach_absolute_time();
46 | };
47 |
48 | void stop()
49 | {
50 | uint64_t end = mach_absolute_time();
51 |
52 | mach_timebase_info_data_t info;
53 | mach_timebase_info(&info);
54 |
55 | uint64_t elapsed = ((end - mStart) * info.numer) / info.denom;
56 |
57 | mStore2 = mStore1;
58 | mStore1 += elapsed;
59 | }
60 |
61 | uint64_t finish(const std::string& msg)
62 | {
63 | tabbedOut(msg + " Elapsed ", to_string_with_precision(mStore1 / 1000000.0, 2), 35);
64 |
65 | uint64_t elapsed = mStore1;
66 |
67 | mStore2 = 0;
68 | mStore1 = 0;
69 |
70 | return elapsed;
71 | };
72 |
73 | void relative(const std::string& msg)
74 | {
75 | tabbedOut(msg + " Comparison ", to_string_with_precision(((double) mStore1 / (double) mStore2), 2), 35);
76 | }
77 |
78 | private:
79 |
80 | uint64_t mStart;
81 | uint64_t mStore1;
82 | uint64_t mStore2;
83 | };
84 |
85 |
86 | template
87 | void fillSplit(SPLIT split, uintptr_t fft_log2)
88 | {
89 | for (uintptr_t i =0; i < (1 << fft_log2); i++)
90 | {
91 | split.realp[i] = 1.0 - 2.0 * std::rand() / RAND_MAX;
92 | split.imagp[i] = 1.0 - 2.0 * std::rand() / RAND_MAX;
93 | }
94 | }
95 |
96 | template
97 | uint64_t timing_test(std::string test, uintptr_t fft_log2, double phase, bool zero, int testSize)
98 | {
99 | SETUP setup;
100 | SPLIT split;
101 |
102 | uintptr_t fft_size = 1 << fft_log2;
103 |
104 | split.realp = (T *) malloc(sizeof(T) * fft_size);
105 | split.imagp = (T *) malloc(sizeof(T) * fft_size);
106 |
107 | hisstools_create_setup(&setup, fft_log2);
108 |
109 | Timer timer;
110 |
111 | for (int i = 0; i < testSize; i++)
112 | {
113 | fillSplit(split, fft_log2);
114 | timer.start();
115 | ir_phase(setup, &split, &split, fft_size, phase, zero);
116 | timer.stop();
117 | }
118 |
119 | uint64_t time = timer.finish(test);
120 |
121 | free(split.realp);
122 | free(split.imagp);
123 | hisstools_destroy_setup(setup);
124 |
125 | return time;
126 | }
127 |
128 | int main(int argc, const char * argv[])
129 | {
130 | // insert code here...
131 | std::cout << "Double vector size is " << SIMDLimits::max_size << "\n";
132 |
133 | int fft_log2 = 14;
134 | int iter = 100;
135 |
136 | timing_test("Zero Mix", fft_log2, 0.1, true, iter);
137 | timing_test("Center Mix", fft_log2, 0.9, false, iter);
138 | timing_test("Zero Min", fft_log2, 0.0, true, iter);
139 | timing_test("Center Min", fft_log2, 0.0, false, iter);
140 | timing_test("Zero Max", fft_log2, 1.0, true, iter);
141 | timing_test("Center Max", fft_log2, 1.0, false, iter);
142 | timing_test("Zero Lin", fft_log2, 0.5, true, iter);
143 | timing_test("Center Lin", fft_log2, 0.5, false, iter);
144 |
145 | std::cout << "Float vector size is " << SIMDLimits::max_size << "\n";
146 |
147 | timing_test("Zero Mix", fft_log2, 0.1, true, iter);
148 | timing_test("Center Mix", fft_log2, 0.9, false, iter);
149 | timing_test("Zero Min", fft_log2, 0.0, true, iter);
150 | timing_test("Center Min", fft_log2, 0.0, false, iter);
151 | timing_test("Zero Max", fft_log2, 1.0, true, iter);
152 | timing_test("Center Max", fft_log2, 1.0, false, iter);
153 | timing_test("Zero Lin", fft_log2, 0.5, true, iter);
154 | timing_test("Center Lin", fft_log2, 0.5, false, iter);
155 |
156 | return 0;
157 | }
158 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/TimeDomainConvolve.cpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * TimeDomainConvolve
4 | *
5 | * TimeDomainConvolve performs real-time zero latency time-based convolution.
6 | *
7 | * Typically TimeDomainConvolve is suitable for use in conjunction with PartitionedConvolve for zero-latency convolution with longer impulses (time_domain_convolve use apple's vDSP and the IR length is limited to 2044 samples).
8 | * Note that in fact the algorithms process correlation with reversed impulse response coeffients - which is equivalent to convolution.
9 | *
10 | * Copyright 2012 Alex Harker. All rights reserved.
11 | *
12 | */
13 |
14 | #include "TimeDomainConvolve.h"
15 | #include "ConvolveSIMD.h"
16 |
17 | #include
18 |
19 | #ifdef __APPLE__
20 | #include
21 |
22 | uintptr_t padded_length(uintptr_t length)
23 | {
24 | return length;
25 | }
26 | #else
27 | uintptr_t padded_length(uintptr_t length)
28 | {
29 | return ((length + 15) >> 4) << 4;
30 | }
31 | #endif
32 |
33 | HISSTools::TimeDomainConvolve::TimeDomainConvolve(uintptr_t offset, uintptr_t length) : mInputPosition(0), mImpulseLength(0)
34 | {
35 | // Set default initial variables
36 |
37 | setOffset(offset);
38 | setLength(length);
39 |
40 | // Allocate impulse buffer and input bufferr
41 |
42 | mImpulseBuffer = (float *) ALIGNED_MALLOC(sizeof(float) * 2048);
43 | mInputBuffer = (float *) ALIGNED_MALLOC(sizeof(float) * 8192);
44 |
45 | // Zero buffers
46 |
47 | std::fill_n(mImpulseBuffer, 2048, 0.f);
48 | std::fill_n(mInputBuffer, 8192, 0.f);
49 | }
50 |
51 | HISSTools::TimeDomainConvolve::~TimeDomainConvolve()
52 | {
53 | ALIGNED_FREE(mImpulseBuffer);
54 | ALIGNED_FREE(mInputBuffer);
55 | }
56 |
57 | void HISSTools::TimeDomainConvolve::setOffset(uintptr_t offset)
58 | {
59 | mOffset = offset;
60 | }
61 |
62 | ConvolveError HISSTools::TimeDomainConvolve::setLength(uintptr_t length)
63 | {
64 | mLength = std::min(length, uintptr_t(2044));
65 |
66 | return length > 2044 ? CONVOLVE_ERR_TIME_LENGTH_OUT_OF_RANGE : CONVOLVE_ERR_NONE;
67 | }
68 |
69 | ConvolveError HISSTools::TimeDomainConvolve::set(const float *input, uintptr_t length)
70 | {
71 | mImpulseLength = 0;
72 |
73 | if (input && length > mOffset)
74 | {
75 | // Calculate impulse length
76 |
77 | mImpulseLength = std::min(length - mOffset, (mLength ? mLength : 2044));
78 |
79 | uintptr_t pad = padded_length(mImpulseLength) - mImpulseLength;
80 | std::fill_n(mImpulseBuffer, pad, 0.f);
81 | std::reverse_copy(input + mOffset, input + mOffset + mImpulseLength, mImpulseBuffer + pad);
82 | }
83 |
84 | reset();
85 |
86 | return (!mLength && (length - mOffset) > 2044) ? CONVOLVE_ERR_TIME_IMPULSE_TOO_LONG : CONVOLVE_ERR_NONE;
87 | }
88 |
89 | void HISSTools::TimeDomainConvolve::reset()
90 | {
91 | mReset = true;
92 | }
93 |
94 | #ifdef __APPLE__
95 | void convolve(const float *in, const float *impulse, float *output, uintptr_t N, uintptr_t L)
96 | {
97 | vDSP_conv(in + 1 - L, 1, impulse, 1, output, 1, N, L);
98 | }
99 | #else
100 | void convolve(const float *in, const float *impulse, float *output, uintptr_t N, uintptr_t L)
101 | {
102 | constexpr int size = FloatVector::size;
103 |
104 | L = padded_length(L);
105 |
106 | const FloatVector *impulse_vector = reinterpret_cast(impulse);
107 |
108 | for (uintptr_t i = 0; i < N; i++)
109 | {
110 | FloatVector outputAccum(0.f);
111 | const float *input = in - L + 1 + i - size;
112 |
113 | for (uintptr_t j = 0; j < L >> 2; j += 4)
114 | {
115 | // Load vals
116 |
117 | outputAccum += (impulse_vector[j + 0] * FloatVector::unaligned_load(input += size));
118 | outputAccum += (impulse_vector[j + 1] * FloatVector::unaligned_load(input += size));
119 | outputAccum += (impulse_vector[j + 2] * FloatVector::unaligned_load(input += size));
120 | outputAccum += (impulse_vector[j + 3] * FloatVector::unaligned_load(input += size));
121 | }
122 |
123 | *output++ = outputAccum.sum();
124 | }
125 | }
126 | #endif
127 |
128 | bool HISSTools::TimeDomainConvolve::process(const float *in, float *out, uintptr_t numSamples)
129 | {
130 | if (mReset)
131 | {
132 | std::fill_n(mInputBuffer, 8192, 0.f);
133 | mReset = false;
134 | }
135 |
136 | uintptr_t currentLoop;
137 |
138 | while ((currentLoop = (mInputPosition + numSamples) > 4096 ? (4096 - mInputPosition) : ((numSamples > 2048) ? 2048 : numSamples)))
139 | {
140 | // Copy input twice (allows us to read input out in one go)
141 |
142 | std::copy_n(in, currentLoop, mInputBuffer + mInputPosition);
143 | std::copy_n(in, currentLoop, mInputBuffer + mInputPosition + 4096);
144 |
145 | // Advance pointer
146 |
147 | mInputPosition += currentLoop;
148 | if (mInputPosition >= 4096)
149 | mInputPosition -= 4096;
150 |
151 | // Do convolution
152 |
153 | convolve(mInputBuffer + 4096 + (mInputPosition - currentLoop), mImpulseBuffer, out, currentLoop, mImpulseLength);
154 |
155 | // Updates
156 |
157 | in += currentLoop;
158 | out += currentLoop;
159 | numSamples -= currentLoop;
160 | }
161 |
162 | return mImpulseLength;
163 | }
164 |
--------------------------------------------------------------------------------
/- Test/Window_Tester/Window_Tester/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "../../../WindowFunctions.hpp"
11 | #include "../../../AudioFile/OAudioFile.h"
12 |
13 | // Output
14 |
15 | void tabbedOut(const std::string& name, const std::string& text, int tab = 25)
16 | {
17 | std::cout << std::setw(tab) << std::setfill(' ');
18 | std::cout.setf(std::ios::left);
19 | std::cout.unsetf(std::ios::right);
20 | std::cout << name;
21 | std::cout.unsetf(std::ios::left);
22 | std::cout << text << "\n";
23 | }
24 |
25 | template
26 | std::string to_string_with_precision(const T a_value, const int n = 4, bool fixed = true)
27 | {
28 | std::ostringstream out;
29 | if (fixed)
30 | out << std::setprecision(n) << std::fixed << a_value;
31 | else
32 | out << std::setprecision(n) << a_value;
33 |
34 | return out.str();
35 | }
36 |
37 | // Timing
38 |
39 | class Timer
40 | {
41 |
42 | public:
43 |
44 | Timer() : mStart(0), mStore1(0), mStore2(0) {}
45 |
46 | void start()
47 | {
48 | mStart = mach_absolute_time();
49 | };
50 |
51 | void stop()
52 | {
53 | uint64_t end = mach_absolute_time();
54 |
55 | mach_timebase_info_data_t info;
56 | mach_timebase_info(&info);
57 |
58 | uint64_t elapsed = ((end - mStart) * info.numer) / info.denom;
59 |
60 | mStore2 = mStore1;
61 | mStore1 = elapsed;
62 | }
63 |
64 | uint64_t finish(const std::string& msg)
65 | {
66 | tabbedOut(msg + " Elapsed ", to_string_with_precision(mStore1 / 1000000.0, 2), 35);
67 |
68 | uint64_t elapsed = mStore1;
69 |
70 | return elapsed;
71 | };
72 |
73 | void relative(const std::string& msg)
74 | {
75 | tabbedOut(msg + " Comparison ", to_string_with_precision(((double) mStore2 / (double) mStore1), 2), 35);
76 | }
77 |
78 | private:
79 |
80 | uint64_t mStart;
81 | uint64_t mStore1;
82 | uint64_t mStore2;
83 | };
84 |
85 | std::default_random_engine rand_engine;
86 |
87 | int random_integer(int min, int max)
88 | {
89 | return (rand_engine() % ((max + 1) - min)) + min;
90 | }
91 |
92 | bool check_symmetry()
93 | {
94 | const int size = random_integer(20, 300);
95 | int begin = random_integer(0, size / 2 + 2);
96 | int end = random_integer(size / 2 - 2, size);
97 |
98 | double window1[size];
99 | double window2[size];
100 |
101 | using namespace window_functions;
102 |
103 | triangle(window1, size, 0, size, params());
104 | triangle(window2, size, begin, end, params());
105 |
106 | for (int i = begin; i < end; i++)
107 | {
108 | if (window1[i] != window2[i - begin])
109 | {
110 | double relative_error = exp(fabs(log(window1[i] / window2[i - begin])));
111 |
112 | if (relative_error > 1.000000000001 || isnan(relative_error))
113 | return false;
114 | }
115 | }
116 |
117 | return true;
118 | }
119 |
120 | void check_window(const char* wind, window_functions::window_generator f, const window_functions::params &p)
121 | {
122 | constexpr int size = 32768;
123 | double window[size];
124 |
125 | f(window, size, 0, size, p);
126 |
127 | auto it = std::max_element(window, window + size);
128 | auto n = it - window;
129 | bool symmetry = true;
130 |
131 | for (int i = ((size >> 1) + 1); i < size; i++)
132 | {
133 | if (window[i] != window[size - i])
134 | {
135 | symmetry = false;
136 | break;
137 | }
138 | }
139 |
140 | std::cout << "** test " << wind << " window\n";
141 | std::cout << "element zero " << window[0] << "\n";
142 | std::cout << "middle element " << window[size >> 1] << "\n";
143 | std::cout << "max element " << *it << " [" << n << "]\n";
144 | std::cout << "symmetry " << symmetry << "\n";
145 | }
146 |
147 | int main(int argc, const char * argv[])
148 | {
149 | constexpr int size = 32768;
150 | constexpr int iter = 1024;
151 | constexpr int sym_iter = 32768;
152 | double window[size];
153 |
154 | rand_engine.seed(std::random_device()());
155 |
156 | using namespace window_functions;
157 |
158 | params ep;
159 | params tp(0.1, 0.9);
160 | params typ(0.1);
161 | params p(0.5, 0.5);
162 |
163 | check_window("parzen", &parzen, ep);
164 | check_window("welch", &welch, ep);
165 | check_window("sine", &sine, ep);
166 | check_window("hann", &hann, ep);
167 | check_window("triangle", &triangle, ep);
168 | check_window("trapezoid", &trapezoid, tp);
169 | check_window("tukey", &tukey, typ);
170 |
171 | for (int i = 0; i < iter; i++)
172 | sine(window, size, 0, size, params());
173 |
174 | Timer timer;
175 |
176 | timer.start();
177 | for (int i = 0; i < iter; i++)
178 | cosine_2_term(window, size, 0, size, p);
179 | timer.stop();
180 | timer.finish("Branch Speed Test");
181 |
182 | timer.start();
183 | for (int i = 0; i < iter; i++)
184 | hann(window, size, 0, size, params(0.2, 0.3));
185 | timer.stop();
186 | timer.finish("Non-branch Speed Test");
187 |
188 | timer.relative("Window Speed Test");
189 |
190 | for (int i = 0; i < sym_iter; i++)
191 | {
192 | if (!check_symmetry())
193 | {
194 | std::cout << "Symmetry copying failed!\n";
195 | break;
196 | }
197 |
198 | if (i == sym_iter - 1)
199 | std::cout << "Symmetry copying succeeded!\n";
200 | }
201 |
202 | indexed_generator, hann> gen;
203 |
204 | gen(0, window, size, 0, size, params(4));
205 |
206 | if (argc > 1)
207 | {
208 | HISSTools::OAudioFile file(argv[1], HISSTools::BaseAudioFile::kAudioFileWAVE, HISSTools::BaseAudioFile::kAudioFileFloat32, 1, 44100.0);
209 |
210 | if (file.isOpen())
211 | file.writeChannel(window, size, 0);
212 | }
213 | return 0;
214 | }
215 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/Convolver.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Convolver.h"
3 | #include "ConvolveSIMD.h"
4 |
5 | HISSTools::Convolver::Convolver(uint32_t numIns, uint32_t numOuts, LatencyMode latency)
6 | : mTemporaryMemory(0)
7 | {
8 | numIns = numIns < 1 ? 1 : numIns;
9 |
10 | mN2M = true;
11 | mNumIns = numIns;
12 | mNumOuts = numOuts;
13 |
14 | for (uint32_t i = 0; i < numIns; i++)
15 | mInTemps.push_back(nullptr);
16 |
17 | for (uint32_t i = 0; i < numOuts; i++)
18 | mConvolvers.push_back(new NToMonoConvolve(numIns, 16384, latency));
19 |
20 | mTemp1 = nullptr;
21 | mTemp2 = nullptr;
22 | }
23 |
24 | HISSTools::Convolver::Convolver(uint32_t numIO, LatencyMode latency)
25 | : mTemporaryMemory(0)
26 | {
27 | numIO = numIO < 1 ? 1 : numIO;
28 |
29 | mN2M = false;
30 | mNumIns = numIO;
31 | mNumOuts = numIO;
32 |
33 | for (uint32_t i = 0; i < numIO; i++)
34 | {
35 | mConvolvers.push_back(new NToMonoConvolve(1, 16384, latency));
36 | mInTemps.push_back(nullptr);
37 | }
38 |
39 | mTemp1 = nullptr;
40 | mTemp2 = nullptr;
41 | }
42 |
43 | HISSTools::Convolver::~Convolver() throw()
44 | {
45 | for (uint32_t i = 0; i < mNumOuts; i++)
46 | delete mConvolvers[i];
47 | }
48 |
49 | // Clear IRs
50 |
51 | void HISSTools::Convolver::clear(bool resize)
52 | {
53 | if (mN2M)
54 | {
55 | for (uint32_t i = 0; i < mNumOuts; i++)
56 | for (uint32_t j = 0; j < mNumIns; j++)
57 | clear(j, i, resize);
58 | }
59 | else
60 | {
61 | for (uint32_t i = 0; i < mNumOuts; i++)
62 | clear(i, i, resize);
63 | }
64 | }
65 |
66 | void HISSTools::Convolver::clear(uint32_t inChan, uint32_t outChan, bool resize)
67 | {
68 | set(inChan, outChan, (float *)nullptr, 0, resize);
69 | }
70 |
71 | // DSP Engine Reset
72 |
73 | void HISSTools::Convolver::reset()
74 | {
75 | if (mN2M)
76 | {
77 | for (uint32_t i = 0; i < mNumOuts; i++)
78 | for (uint32_t j = 0; j < mNumIns; j++)
79 | reset(j, i);
80 | }
81 | else
82 | {
83 | for (uint32_t i = 0; i < mNumOuts; i++)
84 | reset(i, i);
85 | }
86 | }
87 |
88 | ConvolveError HISSTools::Convolver::reset(uint32_t inChan, uint32_t outChan)
89 | {
90 | // For Parallel operation you must pass the same in/out channel
91 |
92 | if (!mN2M) inChan -= outChan;
93 |
94 | if (outChan < mNumOuts)
95 | return mConvolvers[outChan]->reset(inChan);
96 | else
97 | return CONVOLVE_ERR_OUT_CHAN_OUT_OF_RANGE;
98 | }
99 |
100 | // Resize and set IR
101 |
102 | ConvolveError HISSTools::Convolver::resize(uint32_t inChan, uint32_t outChan, uintptr_t length)
103 | {
104 | // For Parallel operation you must pass the same in/out channel
105 |
106 | if (!mN2M) inChan -= outChan;
107 |
108 | if (outChan < mNumOuts)
109 | return mConvolvers[outChan]->resize(inChan, length);
110 | else
111 | return CONVOLVE_ERR_IN_CHAN_OUT_OF_RANGE;
112 | }
113 |
114 | ConvolveError HISSTools::Convolver::set(uint32_t inChan, uint32_t outChan, const float* input, uintptr_t length, bool resize)
115 | {
116 | // For Parallel operation you must pass the same in/out channel
117 |
118 | if (!mN2M) inChan -= outChan;
119 |
120 | if (outChan < mNumOuts)
121 | return mConvolvers[outChan]->set(inChan, input, length, resize);
122 | else
123 | return CONVOLVE_ERR_OUT_CHAN_OUT_OF_RANGE;
124 | }
125 |
126 | ConvolveError HISSTools::Convolver::set(uint32_t inChan, uint32_t outChan, const double* input, uintptr_t impulseLength, bool resize)
127 | {
128 | std::vector inputFloat(impulseLength);
129 |
130 | for (unsigned long i = 0; i < impulseLength; i++)
131 | inputFloat[i] = static_cast(input[i]);
132 |
133 | return set(inChan, outChan, inputFloat.data(), impulseLength, resize);
134 | }
135 |
136 | // DSP
137 |
138 | void HISSTools::Convolver::process(const float * const* ins, float** outs, size_t numIns, size_t numOuts, size_t numSamples)
139 | {
140 | auto memPointer = mTemporaryMemory.grow((mNumIns + 2) * numSamples);
141 | tempSetup(memPointer.get(), memPointer.getSize());
142 |
143 | if (!memPointer.get())
144 | numIns = numOuts = 0;
145 |
146 | SIMDSettings settings;
147 |
148 | for (size_t i = 0; i < numOuts; i++)
149 | {
150 | const float *n2nIn[1] = { ins[i] };
151 |
152 | mConvolvers[i]->process(mN2M ? ins : n2nIn, outs[i], mTemp1, numSamples, mN2M ? numIns : 1);
153 | }
154 | }
155 |
156 | void HISSTools::Convolver::process(const double * const* ins, double** outs, size_t numIns, size_t numOuts, size_t numSamples)
157 | {
158 | auto memPointer = mTemporaryMemory.grow((mNumIns + 2) * numSamples);
159 | tempSetup(memPointer.get(), memPointer.getSize());
160 |
161 | if (!memPointer.get())
162 | numIns = numOuts = 0;
163 |
164 | numIns = numIns > mNumIns ? mNumIns : numIns;
165 | numOuts = numOuts > mNumOuts ? mNumOuts : numOuts;
166 |
167 | for (uintptr_t i = 0; i < numIns; i++)
168 | for (uintptr_t j = 0; j < numSamples; j++)
169 | mInTemps[i][j] = static_cast(ins[i][j]);
170 |
171 | SIMDSettings settings;
172 |
173 | for (uintptr_t i = 0; i < numOuts; i++)
174 | {
175 | const float *n2nIn[1] = { mInTemps[i] };
176 | const float * const *inTemps = mInTemps.data();
177 |
178 | mConvolvers[i]->process(mN2M ? inTemps : n2nIn, mTemp2, mTemp1, numSamples, mN2M ? numIns : 1);
179 |
180 | for (uintptr_t j = 0; j < numSamples; j++)
181 | outs[i][j] = mTemp2[j];
182 | }
183 | }
184 |
185 | void HISSTools::Convolver::tempSetup(float* memPointer, uintptr_t maxFrameSize)
186 | {
187 | maxFrameSize /= (mNumIns + 2);
188 | mInTemps[0] = memPointer;
189 |
190 | for (uint32_t i = 1; i < mNumIns; i++)
191 | mInTemps[i] = mInTemps[0] + (i * maxFrameSize);
192 |
193 | mTemp1 = mInTemps[mNumIns - 1] + maxFrameSize;
194 | mTemp2 = mTemp1 + maxFrameSize;
195 | }
196 |
197 | HISSTools::Convolver::SIMDSettings::SIMDSettings()
198 | {
199 | #if defined(__i386__) || defined(__x86_64__)
200 | mOldMXCSR = _mm_getcsr();
201 | _mm_setcsr(mOldMXCSR | 0x8040);
202 | #endif
203 | }
204 |
205 | HISSTools::Convolver::SIMDSettings::~SIMDSettings()
206 | {
207 | #if defined(__i386__) || defined(__x86_64__)
208 | _mm_setcsr(mOldMXCSR);
209 | #endif
210 | }
211 |
--------------------------------------------------------------------------------
/AudioFile/BaseAudioFile.cpp:
--------------------------------------------------------------------------------
1 | #include "BaseAudioFile.h"
2 |
3 | namespace HISSTools
4 | {
5 | BaseAudioFile::BaseAudioFile()
6 | {
7 | close();
8 | }
9 |
10 | BaseAudioFile::~BaseAudioFile()
11 | {
12 | }
13 |
14 | void BaseAudioFile::close()
15 | {
16 | setFileType(kAudioFileNone);
17 | BaseAudioFile::setPCMFormat(kAudioFileInt8);
18 | setHeaderEndianness(kAudioFileLittleEndian);
19 | setAudioEndianness(kAudioFileLittleEndian);
20 | setSamplingRate(0);
21 | setChannels(0);
22 | setFrames(0);
23 | setPCMOffset(0);
24 | clearErrorFlags();
25 | }
26 |
27 | BaseAudioFile::FileType BaseAudioFile::getFileType() const
28 | {
29 | return mFileType;
30 | }
31 |
32 | BaseAudioFile::PCMFormat BaseAudioFile::getPCMFormat() const
33 | {
34 | return mPCMFormat;
35 | }
36 |
37 | BaseAudioFile::Endianness BaseAudioFile::getHeaderEndianness() const
38 | {
39 | return mHeaderEndianness;
40 | }
41 |
42 | BaseAudioFile::Endianness BaseAudioFile::getAudioEndianness() const
43 | {
44 | return mAudioEndianness;
45 | }
46 |
47 | double BaseAudioFile::getSamplingRate() const
48 | {
49 | return mSamplingRate;
50 | }
51 |
52 | uint16_t BaseAudioFile::getChannels() const
53 | {
54 | return mNumChannels;
55 | }
56 |
57 | BaseAudioFile::FrameCount BaseAudioFile::getFrames() const
58 | {
59 | return mNumFrames;
60 | }
61 |
62 | BaseAudioFile::ByteCount BaseAudioFile::getPCMOffset() const
63 | {
64 | return mPCMOffset;
65 | }
66 |
67 | uint16_t BaseAudioFile::getBitDepth() const
68 | {
69 | return findBitDepth(getPCMFormat());
70 | }
71 |
72 | uint16_t BaseAudioFile::getByteDepth() const
73 | {
74 | return getBitDepth() / 8;
75 | }
76 |
77 | BaseAudioFile::ByteCount BaseAudioFile::getFrameByteCount() const
78 | {
79 | return getChannels() * getByteDepth();
80 | }
81 |
82 | BaseAudioFile::NumberFormat BaseAudioFile::getNumberFormat() const
83 | {
84 | return findNumberFormat(getPCMFormat());
85 | }
86 |
87 | int BaseAudioFile::getErrorFlags() const
88 | {
89 | return mErrorFlags;
90 | }
91 |
92 | std::string BaseAudioFile::getErrorString(Error error)
93 | {
94 | switch (error)
95 | {
96 | case ERR_MEM_COULD_NOT_ALLOCATE:
97 | return "mem could not allocate";
98 | case ERR_FILE_ERROR:
99 | return "file error";
100 | case ERR_FILE_COULDNT_OPEN:
101 | return "file couldn't open";
102 | case ERR_FILE_BAD_FORMAT:
103 | return "file bad format";
104 | case ERR_FILE_UNKNOWN_FORMAT:
105 | return "file unknown format";
106 | case ERR_FILE_UNSUPPORTED_PCM_FORMAT:
107 | return "file unsupported pcm format";
108 | case ERR_AIFC_WRONG_VERSION:
109 | return "aifc wrong version";
110 | case ERR_AIFC_UNSUPPORTED_FORMAT:
111 | return "aifc unsupported format";
112 | case ERR_WAVE_UNSUPPORTED_FORMAT:
113 | return "wave unsupported format";
114 | case ERR_FILE_COULDNT_WRITE:
115 | return "file couldn't write";
116 | default:
117 | return "no error";
118 | }
119 | }
120 | std::vector BaseAudioFile::extractErrorsFromFlags(int flags)
121 | {
122 | std::vector ret;
123 | for (int i = 0; i != sizeof(int) * 4; i++)
124 | {
125 | if (flags & (1 << i))
126 | ret.push_back(static_cast(i));
127 | }
128 | return ret;
129 | }
130 |
131 | std::vector BaseAudioFile::getErrors() const
132 | {
133 | return extractErrorsFromFlags(getErrorFlags());
134 | }
135 |
136 | bool BaseAudioFile::getIsError() const
137 | {
138 | return mErrorFlags != ERR_NONE;
139 | }
140 |
141 | void BaseAudioFile::clearErrorFlags()
142 | {
143 | setErrorFlags(ERR_NONE);
144 | }
145 |
146 | void BaseAudioFile::setFileType(FileType i)
147 | {
148 | mFileType = i;
149 | }
150 |
151 | void BaseAudioFile::setPCMFormat(PCMFormat i)
152 | {
153 | mPCMFormat = i;
154 | }
155 |
156 | void BaseAudioFile::setHeaderEndianness(Endianness i)
157 | {
158 | mHeaderEndianness = i;
159 | }
160 |
161 | void BaseAudioFile::setAudioEndianness(Endianness i)
162 | {
163 | mAudioEndianness = i;
164 | }
165 |
166 | void BaseAudioFile::setSamplingRate(double i)
167 | {
168 | mSamplingRate = i;
169 | }
170 |
171 | void BaseAudioFile::setChannels(uint16_t i)
172 | {
173 | mNumChannels = i;
174 | }
175 |
176 | void BaseAudioFile::setFrames(FrameCount i)
177 | {
178 | mNumFrames = i;
179 | }
180 |
181 | void BaseAudioFile::setPCMOffset(ByteCount i)
182 | {
183 | mPCMOffset = i;
184 | }
185 |
186 | void BaseAudioFile::setErrorFlags(int flags)
187 | {
188 | mErrorFlags = flags;
189 | }
190 |
191 | void BaseAudioFile::setErrorBit(Error error)
192 | {
193 | mErrorFlags |= error;
194 | }
195 |
196 | uint16_t BaseAudioFile::findBitDepth(PCMFormat i)
197 | {
198 | switch (i)
199 | {
200 | case kAudioFileInt8:
201 | return 8;
202 | case kAudioFileInt24:
203 | return 24;
204 | case kAudioFileInt32:
205 | return 32;
206 | case kAudioFileFloat32:
207 | return 32;
208 | case kAudioFileFloat64:
209 | return 64;
210 | case kAudioFileInt16:
211 | default:
212 | return 16;
213 | }
214 | }
215 |
216 | BaseAudioFile::NumberFormat BaseAudioFile::findNumberFormat(PCMFormat i)
217 | {
218 | switch (i)
219 | {
220 | case kAudioFileFloat32:
221 | case kAudioFileFloat64:
222 | return kAudioFileFloat;
223 |
224 | case kAudioFileInt8:
225 | case kAudioFileInt16:
226 | case kAudioFileInt24:
227 | case kAudioFileInt32:
228 | default:
229 | return kAudioFileInt;
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/MemorySwap.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "../ThreadLocks.hpp"
10 |
11 | #ifdef _WIN32
12 | #include
13 | #endif
14 |
15 | // FIX - locks around memory assignment - can be made more efficient by avoiding this at which point spinlocks will be justified....
16 | // Follow the HISSTools C++ design for this.... use separate freeing locks so the memory is always freed in the assignment thread
17 | // All memory assignments are aligned in order that the memory is suitable for vector ops etc.
18 |
19 | template
20 | class MemorySwap
21 | {
22 |
23 | public:
24 |
25 | // Alloc and free routine prototypes
26 |
27 | typedef std::function AllocFunc;
28 | typedef std::function FreeFunc;
29 |
30 | class Ptr
31 | {
32 | friend MemorySwap;
33 |
34 | public:
35 |
36 | Ptr(Ptr&& p)
37 | : mOwner(p.mOwner), mPtr(p.mPtr), mSize(p.mSize)
38 | {
39 | p.mOwner = nullptr;
40 | p.mPtr = nullptr;
41 | p.mSize = 0;
42 | }
43 |
44 | ~Ptr() { clear(); }
45 |
46 | void clear()
47 | {
48 | if (mOwner) mOwner->unlock();
49 | mOwner = nullptr;
50 | mPtr = nullptr;
51 | mSize = 0;
52 | }
53 |
54 | void swap(T *ptr, uintptr_t size)
55 | {
56 | update(&MemorySwap::set, ptr, size, nullptr);
57 | }
58 |
59 | void grow(uintptr_t size)
60 | {
61 | grow(&allocate, &deallocate, size);
62 | }
63 |
64 | void equal(uintptr_t size)
65 | {
66 | equal(&allocate, &deallocate, size);
67 | }
68 |
69 | void grow(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size)
70 | {
71 | updateAllocateIf(allocFunction, freeFunction, size, std::greater());
72 | }
73 |
74 | void equal(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size)
75 | {
76 | updateAllocateIf(allocFunction, freeFunction, size, std::not_equal_to());
77 | }
78 |
79 | T *get() { return mPtr; }
80 | uintptr_t getSize() { return mSize; }
81 |
82 | private:
83 |
84 | Ptr()
85 | : mOwner(nullptr), mPtr(nullptr), mSize(0)
86 | {}
87 |
88 | Ptr(MemorySwap *owner)
89 | : mOwner(owner), mPtr(mOwner ? mOwner->mPtr : nullptr), mSize(mOwner ? mOwner->mSize : 0)
90 | {}
91 |
92 | Ptr(const Ptr& p) = delete;
93 | Ptr operator = (const Ptr& p) = delete;
94 |
95 | template
96 | void updateAllocateIf(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size, Op op)
97 | {
98 | update(&MemorySwap::allocateIfLockHeld, allocFunction, freeFunction, size, op);
99 | }
100 |
101 | template
102 | void update(Op op, Args...args)
103 | {
104 | if (mOwner)
105 | {
106 | (mOwner->*op)(args...);
107 | mPtr = mOwner->mPtr;
108 | mSize = mOwner->mSize;
109 | }
110 | }
111 |
112 | MemorySwap *mOwner;
113 | T *mPtr;
114 | uintptr_t mSize;
115 | };
116 |
117 | // Constructor (standard allocation)
118 |
119 | MemorySwap(uintptr_t size)
120 | : mPtr(nullptr), mSize(0), mFreeFunction(nullptr)
121 | {
122 | if (size)
123 | set(allocate(size), size, &deallocate);
124 | }
125 |
126 | // Constructor (custom allocation)
127 |
128 | MemorySwap(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size)
129 | : mPtr(nullptr), mSize(0), mFreeFunction(nullptr)
130 | {
131 | if (size)
132 | set(allocFunction(size), size, freeFunction);
133 | }
134 |
135 | ~MemorySwap()
136 | {
137 | clear();
138 | }
139 |
140 | MemorySwap(const MemorySwap&) = delete;
141 | MemorySwap& operator = (const MemorySwap&) = delete;
142 |
143 | MemorySwap(MemorySwap&& obj)
144 | : mPtr(nullptr), mSize(0), mFreeFunction(nullptr)
145 | {
146 | *this = std::move(obj);
147 | obj.mPtr = nullptr;
148 | obj.mFreeFunction = nullptr;
149 | }
150 |
151 | MemorySwap& operator = (MemorySwap&& obj)
152 | {
153 | clear();
154 | obj.lock();
155 | mPtr = obj.mPtr;
156 | mSize = obj.mSize;
157 | mFreeFunction = obj.mFreeFunction;
158 | obj.mPtr = nullptr;
159 | obj.mFreeFunction = nullptr;
160 | obj.unlock();
161 |
162 | return *this;
163 | }
164 |
165 | // frees the memory immediately
166 |
167 | void clear()
168 | {
169 | swap(nullptr, 0);
170 | }
171 |
172 | // lock to get access to the memory struct and safely return the pointer
173 |
174 | Ptr access()
175 | {
176 | lock();
177 | return Ptr(this);
178 | }
179 |
180 | // This non-blocking routine will attempt to get the pointer but fail if the pointer is being accessed in another thread
181 |
182 | Ptr attempt()
183 | {
184 | return tryLock() ? Ptr(this) : Ptr();
185 | }
186 |
187 | Ptr swap(T *ptr, uintptr_t size)
188 | {
189 | lock();
190 | set(ptr, size, nullptr);
191 | return Ptr(this);
192 | }
193 |
194 | Ptr grow(uintptr_t size)
195 | {
196 | return grow(&allocate, &deallocate, size);
197 | }
198 |
199 | Ptr equal(uintptr_t size)
200 | {
201 | return equal(&allocate, &deallocate, size);
202 | }
203 |
204 | Ptr grow(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size)
205 | {
206 | return allocateIf(allocFunction, freeFunction, size, std::greater());
207 | }
208 |
209 | Ptr equal(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size)
210 | {
211 | return allocateIf(allocFunction, freeFunction, size, std::not_equal_to());
212 | }
213 |
214 | private:
215 |
216 | template
217 | Ptr allocateIf(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size, Op op)
218 | {
219 | lock();
220 | allocateIfLockHeld(allocFunction, freeFunction, size, op);
221 | return Ptr(this);
222 | }
223 |
224 | template
225 | void allocateIfLockHeld(AllocFunc allocFunction, FreeFunc freeFunction, uintptr_t size, Op op)
226 | {
227 | if (op(size, mSize))
228 | set(allocFunction(size), size, freeFunction);
229 | }
230 |
231 | void set(T *ptr, uintptr_t size, FreeFunc freeFunction)
232 | {
233 | if (mFreeFunction)
234 | mFreeFunction(mPtr);
235 |
236 | mPtr = ptr;
237 | mSize = ptr ? size : 0;
238 | mFreeFunction = freeFunction;
239 | }
240 |
241 | bool tryLock()
242 | {
243 | return mLock.attempt();
244 | }
245 |
246 | void lock()
247 | {
248 | mLock.acquire();
249 | }
250 |
251 | void unlock()
252 | {
253 | mLock.release();
254 | }
255 |
256 | #ifdef _WIN32
257 | static T* allocate(size_t size)
258 | {
259 | return static_cast(_aligned_malloc(size * sizeof(T), 16));
260 | }
261 |
262 | static void deallocate(T *ptr)
263 | {
264 | _aligned_free(ptr);
265 | }
266 | #else
267 | #ifdef __APPLE__
268 | static T* allocate(size_t size)
269 | {
270 | return reinterpret_cast(malloc(size * sizeof(T)));
271 | }
272 | #else
273 | static T* allocate(size_t size)
274 | {
275 | return reinterpret_cast(aligned_alloc(16, size * sizeof(T)));
276 | }
277 | #endif
278 |
279 | static void deallocate(T *ptr)
280 | {
281 | free(ptr);
282 | }
283 | #endif
284 |
285 | thread_lock mLock;
286 |
287 | T *mPtr;
288 | uintptr_t mSize;
289 | FreeFunc mFreeFunction;
290 | };
291 |
--------------------------------------------------------------------------------
/HISSTools_FFT/HISSTools_FFT.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "HISSTools_FFT.h"
3 | #include "HISSTools_FFT_Core.h"
4 |
5 | #if defined(USE_APPLE_FFT)
6 |
7 | // This file provides bindings to the relevant Apple or HISSTools template routines.
8 |
9 | // User FFT Routines
10 |
11 | void hisstools_fft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
12 | {
13 | vDSP_fft_zipD(setup, input, (vDSP_Stride) 1, log2n, FFT_FORWARD);
14 | }
15 |
16 | void hisstools_fft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
17 | {
18 | vDSP_fft_zip(setup, input, (vDSP_Stride) 1, log2n, FFT_FORWARD);
19 | }
20 |
21 | void hisstools_rfft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
22 | {
23 | vDSP_fft_zripD(setup, input, (vDSP_Stride) 1, log2n, FFT_FORWARD);
24 | }
25 |
26 | void hisstools_rfft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
27 | {
28 | vDSP_fft_zrip(setup, input, (vDSP_Stride) 1, log2n, FFT_FORWARD);
29 | }
30 |
31 | void hisstools_ifft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
32 | {
33 | vDSP_fft_zipD(setup, input, (vDSP_Stride) 1, log2n, FFT_INVERSE);
34 | }
35 |
36 | void hisstools_ifft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
37 | {
38 | vDSP_fft_zip(setup, input, (vDSP_Stride) 1, log2n, FFT_INVERSE);
39 | }
40 |
41 | void hisstools_rifft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
42 | {
43 | vDSP_fft_zripD(setup, input, (vDSP_Stride) 1, log2n, FFT_INVERSE);
44 | }
45 |
46 | void hisstools_rifft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
47 | {
48 | vDSP_fft_zrip(setup, input, (vDSP_Stride) 1, log2n, FFT_INVERSE);
49 | }
50 |
51 | // Zip and Unzip
52 |
53 | void hisstools_unzip(const double *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t log2n)
54 | {
55 | vDSP_ctozD((DOUBLE_COMPLEX *) input, (vDSP_Stride) 2, output, (vDSP_Stride) 1, (vDSP_Length) (1 << (log2n - 1)));
56 | }
57 |
58 | void hisstools_unzip(const float *input, FFT_SPLIT_COMPLEX_F *output, uintptr_t log2n)
59 | {
60 | vDSP_ctoz((COMPLEX *) input, (vDSP_Stride) 2, output, (vDSP_Stride) 1, (vDSP_Length) (1 << (log2n - 1)));
61 | }
62 |
63 | void hisstools_zip(const FFT_SPLIT_COMPLEX_D *input, double *output, uintptr_t log2n)
64 | {
65 | vDSP_ztocD(input, (vDSP_Stride) 1, (DOUBLE_COMPLEX *) output, (vDSP_Stride) 2, (vDSP_Length) (1 << (log2n - 1)));
66 | }
67 |
68 | void hisstools_zip(const FFT_SPLIT_COMPLEX_F *input, float *output, uintptr_t log2n)
69 | {
70 | vDSP_ztoc(input, (vDSP_Stride) 1, (COMPLEX *) output, (vDSP_Stride) 2, (vDSP_Length) (1 << (log2n - 1)));
71 | }
72 |
73 | // Setup Create / Destroy
74 |
75 | void hisstools_create_setup(FFT_SETUP_D *setup, uintptr_t max_fft_log_2)
76 | {
77 | *setup = vDSP_create_fftsetupD(max_fft_log_2, FFT_RADIX2);
78 | }
79 |
80 | void hisstools_create_setup(FFT_SETUP_F *setup, uintptr_t max_fft_log_2)
81 | {
82 | *setup = vDSP_create_fftsetup(max_fft_log_2, FFT_RADIX2);
83 | }
84 |
85 | void hisstools_destroy_setup(FFT_SETUP_D setup)
86 | {
87 | if (setup)
88 | vDSP_destroy_fftsetupD(setup);
89 | }
90 |
91 | void hisstools_destroy_setup(FFT_SETUP_F setup)
92 | {
93 | if (setup)
94 | vDSP_destroy_fftsetup(setup);
95 | }
96 |
97 | // Zip and Unzip
98 |
99 | template void unzipComplex(const float *input, FFT_SPLIT_COMPLEX_F *output, uintptr_t half_length)
100 | {
101 | vDSP_ctoz((COMPLEX *) input, (vDSP_Stride) 2, output, (vDSP_Stride) 1, half_length);
102 | }
103 |
104 | template void unzipComplex(const double *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t half_length)
105 | {
106 | vDSP_ctozD((DOUBLE_COMPLEX *) input, (vDSP_Stride) 2, output, (vDSP_Stride) 1, half_length);
107 | }
108 |
109 | #else
110 |
111 | // User FFT Routines
112 |
113 | void hisstools_fft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
114 | {
115 | hisstools_fft_impl::hisstools_fft(input, setup, log2n);
116 | }
117 |
118 | void hisstools_fft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
119 | {
120 | hisstools_fft_impl::hisstools_fft(input, setup, log2n);
121 | }
122 |
123 | void hisstools_rfft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
124 | {
125 | hisstools_fft_impl::hisstools_rfft(input, setup, log2n);
126 | }
127 |
128 | void hisstools_rfft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
129 | {
130 | hisstools_fft_impl::hisstools_rfft(input, setup, log2n);
131 | }
132 |
133 | void hisstools_ifft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
134 | {
135 | hisstools_fft_impl::hisstools_ifft(input, setup, log2n);
136 | }
137 |
138 | void hisstools_ifft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
139 | {
140 | hisstools_fft_impl::hisstools_ifft(input, setup, log2n);
141 | }
142 |
143 | void hisstools_rifft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, uintptr_t log2n)
144 | {
145 | hisstools_fft_impl::hisstools_rifft(input, setup, log2n);
146 | }
147 |
148 | void hisstools_rifft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, uintptr_t log2n)
149 | {
150 | hisstools_fft_impl::hisstools_rifft(input, setup, log2n);
151 | }
152 |
153 | // Zip and Unzip
154 |
155 | void hisstools_unzip(const double *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t log2n)
156 | {
157 | hisstools_fft_impl::unzip_complex(input, output, (uintptr_t) 1 << (log2n - (uintptr_t) 1));
158 | }
159 |
160 | void hisstools_unzip(const float *input, FFT_SPLIT_COMPLEX_F *output, uintptr_t log2n)
161 | {
162 | hisstools_fft_impl::unzip_complex(input, output, (uintptr_t) 1 << (log2n - (uintptr_t) 1));
163 | }
164 |
165 | void hisstools_zip(const FFT_SPLIT_COMPLEX_D *input, double *output, uintptr_t log2n)
166 | {
167 | hisstools_fft_impl::zip_complex(input, output, (uintptr_t) 1 << (log2n - (uintptr_t) 1));
168 | }
169 |
170 | void hisstools_zip(const FFT_SPLIT_COMPLEX_F *input, float *output, uintptr_t log2n)
171 | {
172 | hisstools_fft_impl::zip_complex(input, output, (uintptr_t) 1 << (log2n - (uintptr_t) 1));
173 | }
174 |
175 | // Setup Create / Destroy
176 |
177 | void hisstools_create_setup(FFT_SETUP_D *setup, uintptr_t max_fft_log_2)
178 | {
179 | *setup = static_cast(hisstools_fft_impl::create_setup(max_fft_log_2));
180 | }
181 |
182 | void hisstools_create_setup(FFT_SETUP_F *setup, uintptr_t max_fft_log_2)
183 | {
184 | *setup = static_cast(hisstools_fft_impl::create_setup(max_fft_log_2));
185 | }
186 |
187 | void hisstools_destroy_setup(FFT_SETUP_D setup)
188 | {
189 | hisstools_fft_impl::destroy_setup(setup);
190 | }
191 |
192 | void hisstools_destroy_setup(FFT_SETUP_F setup)
193 | {
194 | hisstools_fft_impl::destroy_setup(setup);
195 | }
196 |
197 | #endif
198 |
199 | // Unzip incorporating zero padding
200 |
201 | void hisstools_unzip_zero(const double *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t in_length, uintptr_t log2n)
202 | {
203 | hisstools_fft_impl::unzip_zero(input, output, in_length, log2n);
204 | }
205 |
206 | void hisstools_unzip_zero(const float *input, FFT_SPLIT_COMPLEX_F *output, uintptr_t in_length, uintptr_t log2n)
207 | {
208 | hisstools_fft_impl::unzip_zero(input, output, in_length, log2n);
209 | }
210 |
211 | // N.B This routine specifically deals with unzipping float data into a double precision complex split format
212 |
213 | void hisstools_unzip_zero(const float *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t in_length, uintptr_t log2n)
214 | {
215 | hisstools_fft_impl::unzip_zero(input, output, in_length, log2n);
216 | }
217 |
218 | // Convenience Real FFT Functions
219 |
220 | void hisstools_rfft(FFT_SETUP_D setup, const double *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t in_length, uintptr_t log2n)
221 | {
222 | hisstools_unzip_zero(input, output, in_length, log2n);
223 | hisstools_rfft(setup, output, log2n);
224 | }
225 |
226 | void hisstools_rfft(FFT_SETUP_F setup, const float *input, FFT_SPLIT_COMPLEX_F *output, uintptr_t in_length, uintptr_t log2n)
227 | {
228 | hisstools_unzip_zero(input, output, in_length, log2n);
229 | hisstools_rfft(setup, output, log2n);
230 | }
231 |
232 | void hisstools_rfft(FFT_SETUP_D setup, const float *input, FFT_SPLIT_COMPLEX_D *output, uintptr_t in_length, uintptr_t log2n)
233 | {
234 | hisstools_unzip_zero(input, output, in_length, log2n);
235 | hisstools_rfft(setup, output, log2n);
236 | }
237 |
238 | void hisstools_rifft(FFT_SETUP_D setup, FFT_SPLIT_COMPLEX_D *input, double *output, uintptr_t log2n)
239 | {
240 | hisstools_rifft(setup, input, log2n);
241 | hisstools_zip(input, output, log2n);
242 | }
243 |
244 | void hisstools_rifft(FFT_SETUP_F setup, FFT_SPLIT_COMPLEX_F *input, float *output, uintptr_t log2n)
245 | {
246 | hisstools_rifft(setup, input, log2n);
247 | hisstools_zip(input, output, log2n);
248 | }
249 |
--------------------------------------------------------------------------------
/HIRT_Multichannel_Convolution/MonoConvolve.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "MonoConvolve.h"
3 | #include "ConvolveSIMD.h"
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | // Free Utility
10 |
11 | void largeFree(HISSTools::PartitionedConvolve *largePartition)
12 | {
13 | delete largePartition;
14 | }
15 |
16 | // Standard Constructor
17 |
18 | HISSTools::MonoConvolve::MonoConvolve(uintptr_t maxLength, LatencyMode latency)
19 | : mAllocator(nullptr)
20 | , mPart4(0)
21 | , mLength(0)
22 | , mPart4ResetOffset(0)
23 | , mReset(false)
24 | , mRandGenerator(std::random_device()())
25 | {
26 | switch (latency)
27 | {
28 | case kLatencyZero: setPartitions(maxLength, true, 256, 1024, 4096, 16384); break;
29 | case kLatencyShort: setPartitions(maxLength, false, 256, 1024, 4096, 16384); break;
30 | case kLatencyMedium: setPartitions(maxLength, false, 1024, 4096, 16384); break;
31 | }
32 | }
33 |
34 | // Constructor (custom partitioning)
35 |
36 | HISSTools::MonoConvolve::MonoConvolve(uintptr_t maxLength, bool zeroLatency, uint32_t A, uint32_t B, uint32_t C, uint32_t D)
37 | : mAllocator(nullptr)
38 | , mPart4(0)
39 | , mLength(0)
40 | , mPart4ResetOffset(0)
41 | , mReset(false)
42 | , mRandGenerator(std::random_device()())
43 | {
44 | setPartitions(maxLength, zeroLatency, A, B, C, D);
45 | }
46 |
47 | // Move Constructor
48 |
49 | HISSTools::MonoConvolve::MonoConvolve(MonoConvolve&& obj)
50 | : mAllocator(obj.mAllocator)
51 | , mSizes(std::move(obj.mSizes))
52 | , mTime1(std::move(obj.mTime1))
53 | , mPart1(std::move(obj.mPart1))
54 | , mPart2(std::move(obj.mPart2))
55 | , mPart3(std::move(obj.mPart3))
56 | , mPart4(std::move(obj.mPart4))
57 | , mLength(obj.mLength)
58 | , mPart4ResetOffset(obj.mPart4ResetOffset)
59 | , mReset(true)
60 | {}
61 |
62 | // Move Assignment
63 |
64 | HISSTools::MonoConvolve& HISSTools::MonoConvolve::operator = (MonoConvolve&& obj)
65 | {
66 | mAllocator = obj.mAllocator;
67 | mSizes = std::move(obj.mSizes);
68 | mTime1 = std::move(obj.mTime1);
69 | mPart1 = std::move(obj.mPart1);
70 | mPart2 = std::move(obj.mPart2);
71 | mPart3 = std::move(obj.mPart3);
72 | mPart4 = std::move(obj.mPart4);
73 | mLength = obj.mLength;
74 | mPart4ResetOffset = obj.mPart4ResetOffset;
75 | mReset = true;
76 |
77 | return *this;
78 | }
79 |
80 | void HISSTools::MonoConvolve::setResetOffset(intptr_t offset)
81 | {
82 | PartPtr part4 = mPart4.access();
83 |
84 | setResetOffset(part4, offset);
85 | }
86 |
87 | void HISSTools::MonoConvolve::setResetOffset(PartPtr& part4, intptr_t offset)
88 | {
89 | if (offset < 0)
90 | offset = mRandDistribution(mRandGenerator);
91 |
92 | if (mPart1) mPart1.get()->setResetOffset(offset + (mSizes[numSizes() - 3] >> 3));
93 | if (mPart2) mPart2.get()->setResetOffset(offset + (mSizes[numSizes() - 2] >> 3));
94 | if (mPart3) mPart3.get()->setResetOffset(offset + (mSizes[numSizes() - 1] >> 3));
95 |
96 | if (part4.get()) part4.get()->setResetOffset(offset);
97 |
98 | mPart4ResetOffset = offset;
99 | }
100 |
101 | ConvolveError HISSTools::MonoConvolve::resize(uintptr_t length)
102 | {
103 | mLength = 0;
104 | PartPtr part4 = mPart4.equal(mAllocator, largeFree, length);
105 |
106 | if (part4.get())
107 | part4.get()->setResetOffset(mPart4ResetOffset);
108 |
109 | return part4.getSize() == length ? CONVOLVE_ERR_NONE : CONVOLVE_ERR_MEM_UNAVAILABLE;
110 | }
111 |
112 | template
113 | void setPart(T *obj, const float *input, uintptr_t length)
114 | {
115 | if (obj) obj->set(input, length);
116 | }
117 |
118 | ConvolveError HISSTools::MonoConvolve::set(const float *input, uintptr_t length, bool requestResize)
119 | {
120 | // Lock or resize first to ensure that audio finishes processing before we replace
121 |
122 | mLength = 0;
123 | PartPtr part4 = requestResize ? mPart4.equal(mAllocator, largeFree, length) : mPart4.access();
124 |
125 | if (part4.get())
126 | {
127 | setPart(mTime1.get(), input, length);
128 | setPart(mPart1.get(), input, length);
129 | setPart(mPart2.get(), input, length);
130 | setPart(mPart3.get(), input, length);
131 | setPart(part4.get(), input, length);
132 |
133 | part4.get()->setResetOffset(mPart4ResetOffset);
134 |
135 | mLength = length;
136 | reset();
137 | }
138 |
139 | return (length && !part4.get()) ? CONVOLVE_ERR_MEM_UNAVAILABLE : (length > part4.getSize()) ? CONVOLVE_ERR_MEM_ALLOC_TOO_SMALL : CONVOLVE_ERR_NONE;
140 | }
141 |
142 | template
143 | void resetPart(T *obj)
144 | {
145 | if (obj) obj->reset();
146 | }
147 |
148 | ConvolveError HISSTools::MonoConvolve::reset()
149 | {
150 | mReset = true;
151 | return CONVOLVE_ERR_NONE;
152 | }
153 |
154 | template
155 | bool isUnaligned(const T* ptr)
156 | {
157 | return reinterpret_cast(ptr) % 16;
158 | }
159 |
160 | template
161 | void sum(T *temp, T *out, uintptr_t numItems)
162 | {
163 | for (uintptr_t i = 0; i < numItems; i++, out++, temp++)
164 | *out = *out + *temp;
165 | }
166 |
167 | template
168 | void processAndSum(T *obj, const float *in, float *temp, float *out, uintptr_t numSamples, bool accumulate)
169 | {
170 | if (obj && obj->process(in, accumulate ? temp : out, numSamples) && accumulate)
171 | {
172 | if ((numSamples % 4) || isUnaligned(out) || isUnaligned(temp))
173 | sum(temp, out, numSamples);
174 | else
175 | sum(reinterpret_cast(temp), reinterpret_cast(out), numSamples / FloatVector::size);
176 | }
177 | }
178 |
179 | void HISSTools::MonoConvolve::process(const float *in, float *temp, float *out, uintptr_t numSamples, bool accumulate)
180 | {
181 | PartPtr part4 = mPart4.attempt();
182 |
183 | if (mLength && mLength <= part4.getSize())
184 | {
185 | if (mReset)
186 | {
187 | resetPart(mTime1.get());
188 | resetPart(mPart1.get());
189 | resetPart(mPart2.get());
190 | resetPart(mPart3.get());
191 | resetPart(part4.get());
192 | mReset = false;
193 | }
194 |
195 | processAndSum(mTime1.get(), in, temp, out, numSamples, accumulate);
196 | processAndSum(mPart1.get(), in, temp, out, numSamples, accumulate || mTime1);
197 | processAndSum(mPart2.get(), in, temp, out, numSamples, accumulate || mPart1);
198 | processAndSum(mPart3.get(), in, temp, out, numSamples, accumulate || mPart2);
199 | processAndSum(part4.get(), in, temp, out, numSamples, accumulate || mPart3);
200 | }
201 | }
202 |
203 | void HISSTools::MonoConvolve::setPartitions(uintptr_t maxLength, bool zeroLatency, uint32_t A, uint32_t B, uint32_t C, uint32_t D)
204 | {
205 | // Utilities
206 |
207 | auto checkAndStoreFFTSize = [this](int size, int prev)
208 | {
209 | if ((size >= (1 << 5)) && (size <= (1 << 20)) && size > prev)
210 | mSizes.push_back(size);
211 | else if (size)
212 | throw std::runtime_error("invalid FFT size or order");
213 | };
214 |
215 | auto createPart = [](PartUniquePtr& obj, uint32_t& offset, uint32_t size, uint32_t next)
216 | {
217 | obj.reset(new PartitionedConvolve(size, (next - size) >> 1, offset, (next - size) >> 1));
218 | offset += (next - size) >> 1;
219 | };
220 |
221 | // Sanity checks
222 |
223 | checkAndStoreFFTSize(A, 0);
224 | checkAndStoreFFTSize(B, A);
225 | checkAndStoreFFTSize(C, B);
226 | checkAndStoreFFTSize(D, C);
227 |
228 | if (!numSizes())
229 | throw std::runtime_error("no valid FFT sizes given");
230 |
231 | // Lock to ensure we have exclusive access
232 |
233 | PartPtr part4 = mPart4.access();
234 |
235 | uint32_t offset = zeroLatency ? mSizes[0] >> 1 : 0;
236 | uint32_t largestSize = mSizes[numSizes() - 1];
237 |
238 | // Allocate paritions in unique pointers
239 |
240 | if (zeroLatency) mTime1.reset(new TimeDomainConvolve(0, mSizes[0] >> 1));
241 | if (numSizes() == 4) createPart(mPart1, offset, mSizes[0], mSizes[1]);
242 | if (numSizes() > 2) createPart(mPart2, offset, mSizes[numSizes() - 3], mSizes[numSizes() - 2]);
243 | if (numSizes() > 1) createPart(mPart3, offset, mSizes[numSizes() - 2], mSizes[numSizes() - 1]);
244 |
245 | // Allocate the final resizeable partition
246 |
247 | mAllocator = [offset, largestSize](uintptr_t size)
248 | {
249 | return new HISSTools::PartitionedConvolve(largestSize, std::max(size, uintptr_t(largestSize)) - offset, offset, 0);
250 | };
251 |
252 | part4.equal(mAllocator, largeFree, maxLength);
253 |
254 | // Set offsets
255 |
256 | mRandDistribution = std::uniform_int_distribution(0, (mSizes.back() >> 1) - 1);
257 | setResetOffset(part4);
258 | }
259 |
--------------------------------------------------------------------------------
/- Test/FFT_Tester/FFT_Tester/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "HISSTools_FFT.h"
9 |
10 | // Output
11 |
12 | void tabbedOut(const std::string& name, const std::string& text, int tab = 25)
13 | {
14 | std::cout << std::setw(tab) << std::setfill(' ');
15 | std::cout.setf(std::ios::left);
16 | std::cout.unsetf(std::ios::right);
17 | std::cout << name;
18 | std::cout.unsetf(std::ios::left);
19 | std::cout << text << "\n";
20 | }
21 |
22 | template
23 | std::string to_string_with_precision(const T a_value, const int n = 4, bool fixed = true)
24 | {
25 | std::ostringstream out;
26 | if (fixed)
27 | out << std::setprecision(n) << std::fixed << a_value;
28 | else
29 | out << std::setprecision(n) << a_value;
30 |
31 | return out.str();
32 | }
33 |
34 | // Timing
35 |
36 | class Timer
37 | {
38 |
39 | public:
40 |
41 | Timer() : mStart(0), mStore(0) {}
42 |
43 | void start()
44 | {
45 | mStart = mach_absolute_time();
46 | };
47 |
48 | void stop()
49 | {
50 | uint64_t end = mach_absolute_time();
51 |
52 | mach_timebase_info_data_t info;
53 | mach_timebase_info(&info);
54 |
55 | uint64_t elapsed = ((end - mStart) * info.numer) / info.denom;
56 |
57 | mStore += elapsed;
58 | }
59 |
60 | uint64_t finish(const std::string& msg)
61 | {
62 | tabbedOut(msg + " Elapsed ", to_string_with_precision(mStore / 1000000.0, 2), 35);
63 |
64 | uint64_t elapsed = mStore1;
65 |
66 | mStore = 0;
67 |
68 | return elapsed;
69 | };
70 |
71 | private:
72 |
73 | uint64_t mStart;
74 | uint64_t mStore;
75 | };
76 |
77 | template
78 | void fillSplit(SPLIT split, int max_log2)
79 | {
80 | for (long i =0; i < (1 << max_log2); i++)
81 | {
82 | split.realp[i] = 1.0 - 2.0 * std::rand() / RAND_MAX;
83 | split.imagp[i] = 1.0 - 2.0 * std::rand() / RAND_MAX;
84 | }
85 | }
86 |
87 | template
88 | uint64_t crash_test(int min_log2, int max_log2)
89 | {
90 | SETUP setup;
91 | SPLIT split;
92 |
93 | split.realp = (T *) malloc(sizeof(T) * 1 << max_log2);
94 | split.imagp = (T *) malloc(sizeof(T) * 1 << max_log2);
95 |
96 | hisstools_create_setup(&setup, max_log2);
97 |
98 | Timer timer;
99 |
100 | for (int i = min_log2; i < max_log2; i++)
101 | {
102 | fillSplit(split, i);
103 | timer.start();
104 | hisstools_fft(setup, &split, i);
105 | timer.stop();
106 | }
107 |
108 |
109 | for (int i = min_log2; i < max_log2; i++)
110 | {
111 | fillSplit(split, i);
112 | timer.start();
113 | hisstools_ifft(setup, &split, i);
114 | timer.stop();
115 | }
116 |
117 | for (int i = min_log2; i < max_log2; i++)
118 | {
119 | fillSplit(split, i);
120 | timer.start();
121 | hisstools_rfft(setup, &split, i);
122 | timer.stop();
123 | }
124 |
125 | for (int i = min_log2; i < max_log2; i++)
126 | {
127 | fillSplit(split, i);
128 | timer.start();
129 | hisstools_rifft(setup, &split, i);
130 | timer.stop();
131 | }
132 |
133 | uint64_t time = timer.finish("FFT Multiple Tests");
134 |
135 | free(split.realp);
136 | free(split.imagp);
137 | hisstools_destroy_setup(setup);
138 |
139 | return time;
140 | }
141 |
142 | template
143 | uint64_t single_test(int size, void (*Fn)(SETUP, SPLIT *, uintptr_t))
144 | {
145 | SETUP setup;
146 | SPLIT split;
147 |
148 | split.realp = (T *) malloc(sizeof(T) * 1 << size);
149 | split.imagp = (T *) malloc(sizeof(T) * 1 << size);
150 |
151 | hisstools_create_setup(&setup, size);
152 |
153 | Timer timer;
154 |
155 | for (int i = 0; i < 10000; i++)
156 | {
157 | fillSplit(split, size);
158 |
159 | timer.start();
160 | Fn(setup, &split, size);
161 | timer.stop();
162 | }
163 |
164 | uint64_t time = timer.finish(std::string("FFT Single Tests ").append(std::to_string (1 << size)));
165 |
166 | free(split.realp);
167 | free(split.imagp);
168 | hisstools_destroy_setup(setup);
169 |
170 | return time;
171 | }
172 |
173 | template
174 | uint64_t matched_size_test(int min_log2, int max_log2)
175 | {
176 | uint64_t time = 0;
177 |
178 | std::cout << "---FFT---\n";
179 |
180 | for (int i = min_log2; i < max_log2; i++)
181 | time += single_test(i, &hisstools_fft);
182 |
183 | std::cout << "---iFFT---\n";
184 |
185 | for (int i = min_log2; i < max_log2; i++)
186 | time += single_test(i, &hisstools_ifft);
187 |
188 | std::cout << "---Real FFT---\n";
189 |
190 | for (int i = min_log2; i < max_log2; i++)
191 | time += single_test(i, &hisstools_rfft);
192 |
193 | std::cout << "---Real iFFT---\n";
194 |
195 | for (int i = min_log2; i < max_log2; i++)
196 | time += single_test(i, &hisstools_rifft);
197 |
198 | return time;
199 | }
200 |
201 | template
202 | bool zip_correctness_test(int min_log2, int max_log2)
203 | {
204 | SPLIT split;
205 |
206 | U *ptr = (U *) malloc(sizeof(U) * 1 << max_log2);
207 | split.realp = (T *) malloc(sizeof(T) * 1 << (max_log2 - 1));
208 | split.imagp = (T *) malloc(sizeof(T) * 1 << (max_log2 - 1));
209 |
210 | for (int i = min_log2; i < max_log2; i++)
211 | {
212 | for (int j = 0; j < (1 << i); j++)
213 | ptr[j] = j;
214 |
215 | hisstools_unzip(ptr, &split, i);
216 |
217 | for (int j = 0 ; j < (1 << (i - 1)); j++)
218 | {
219 | if (split.realp[j] != (j << 1))
220 | {
221 | std::cout << "zip error\n";
222 | return true;
223 | }
224 | if (i > 1 && split.imagp[j] != (j << 1) + 1)
225 | {
226 | std::cout << "zip error\n";
227 | return true;
228 | }
229 | }
230 |
231 | hisstools_zip(&split, ptr, i);
232 |
233 | for (int j = 0 ; j < (1 << (i - 1)); j++)
234 | {
235 | if (ptr[j] != j)
236 | {
237 | std::cout << "unzip error\n";
238 | return true;
239 | }
240 | }
241 | }
242 |
243 | free(ptr);
244 | free(split.realp);
245 | free(split.imagp);
246 |
247 | std::cout << "FFT Zip Tests Successful\n";
248 |
249 | return false;
250 | }
251 |
252 | template
253 | uint64_t zip_test(int min_log2, int max_log2)
254 | {
255 | SPLIT split;
256 |
257 | U *ptr = (U *) malloc(sizeof(U) * 1 << max_log2);
258 | split.realp = (T *) malloc(sizeof(T) * 1 << (max_log2 - 1));
259 | split.imagp = (T *) malloc(sizeof(T) * 1 << (max_log2 - 1));
260 |
261 | Timer timer;
262 | timer.start();
263 |
264 | for (int i = min_log2; i < max_log2; i++)
265 | hisstools_unzip(ptr, &split, i);
266 |
267 | for (int i = min_log2; i < max_log2; i++)
268 | hisstools_unzip_zero(ptr, &split, 1 << i, i);
269 |
270 | for (int i = min_log2; i < max_log2; i++)
271 | hisstools_zip(&split, ptr, i);
272 |
273 | timer.stop();
274 | uint64_t time = timer.finish("Zip Tests");
275 |
276 | free(ptr);
277 | free(split.realp);
278 | free(split.imagp);
279 |
280 | return time;
281 | }
282 |
283 |
284 | int main(int argc, const char * argv[])
285 | {
286 | uint64_t time = 0;
287 |
288 | std::cout << "****** DOUBLE ******\n";
289 |
290 | if (zip_correctness_test(1, 24))
291 | {
292 | std::cout << "Errors - did not complete tests\n";
293 | return -1;
294 | }
295 |
296 | std::cout << "****** FLOAT ******\n";
297 |
298 | if (zip_correctness_test(1, 24))
299 | {
300 | std::cout << "Errors - did not complete tests\n";
301 | return -1;
302 | }
303 |
304 | std::cout << "****** DOUBLE ******\n";
305 |
306 | time += crash_test(0, 22);
307 |
308 | std::cout << "****** FLOAT ******\n";
309 |
310 | time += crash_test(0, 22);
311 |
312 | std::cout << "****** DOUBLE ******\n";
313 |
314 | time += matched_size_test(6, 14);
315 |
316 | std::cout << "****** FLOAT ******\n";
317 |
318 | time += matched_size_test(6, 14);
319 |
320 | std::cout << "****** DOUBLE ******\n";
321 |
322 | time += zip_test(1, 24);
323 |
324 | std::cout << "****** FLOAT ******\n";
325 |
326 | time += zip_test(1, 24);
327 |
328 | tabbedOut("FFT Tests Total ", to_string_with_precision(time / 1000000.0, 2), 35);
329 |
330 | std::cout << "Finished Running\n";
331 | return 0;
332 | }
333 |
--------------------------------------------------------------------------------
/- Test/Peak_Tester/Peak_Tester.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B80A056B267E1C3000AB6A91 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B80A056A267E1C3000AB6A91 /* main.cpp */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | B80A0565267E1C3000AB6A91 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = /usr/share/man/man1/;
18 | dstSubfolderSpec = 0;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 1;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | B80A0567267E1C3000AB6A91 /* Peak_Tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Peak_Tester; sourceTree = BUILT_PRODUCTS_DIR; };
27 | B80A056A267E1C3000AB6A91 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; };
28 | B8474420267E1C7100DA966D /* PartialTracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = PartialTracker.hpp; path = ../../../PartialTracker.hpp; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | B80A0564267E1C3000AB6A91 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | B80A055E267E1C3000AB6A91 = {
43 | isa = PBXGroup;
44 | children = (
45 | B80A0569267E1C3000AB6A91 /* Peak_Tester */,
46 | B80A0568267E1C3000AB6A91 /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | B80A0568267E1C3000AB6A91 /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | B80A0567267E1C3000AB6A91 /* Peak_Tester */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | B80A0569267E1C3000AB6A91 /* Peak_Tester */ = {
59 | isa = PBXGroup;
60 | children = (
61 | B8474420267E1C7100DA966D /* PartialTracker.hpp */,
62 | B80A056A267E1C3000AB6A91 /* main.cpp */,
63 | );
64 | path = Peak_Tester;
65 | sourceTree = "";
66 | };
67 | /* End PBXGroup section */
68 |
69 | /* Begin PBXNativeTarget section */
70 | B80A0566267E1C3000AB6A91 /* Peak_Tester */ = {
71 | isa = PBXNativeTarget;
72 | buildConfigurationList = B80A056E267E1C3000AB6A91 /* Build configuration list for PBXNativeTarget "Peak_Tester" */;
73 | buildPhases = (
74 | B80A0563267E1C3000AB6A91 /* Sources */,
75 | B80A0564267E1C3000AB6A91 /* Frameworks */,
76 | B80A0565267E1C3000AB6A91 /* CopyFiles */,
77 | );
78 | buildRules = (
79 | );
80 | dependencies = (
81 | );
82 | name = Peak_Tester;
83 | productName = Peak_Tester;
84 | productReference = B80A0567267E1C3000AB6A91 /* Peak_Tester */;
85 | productType = "com.apple.product-type.tool";
86 | };
87 | /* End PBXNativeTarget section */
88 |
89 | /* Begin PBXProject section */
90 | B80A055F267E1C3000AB6A91 /* Project object */ = {
91 | isa = PBXProject;
92 | attributes = {
93 | LastUpgradeCheck = 0940;
94 | ORGANIZATIONNAME = AHarker;
95 | TargetAttributes = {
96 | B80A0566267E1C3000AB6A91 = {
97 | CreatedOnToolsVersion = 9.4.1;
98 | };
99 | };
100 | };
101 | buildConfigurationList = B80A0562267E1C3000AB6A91 /* Build configuration list for PBXProject "Peak_Tester" */;
102 | compatibilityVersion = "Xcode 9.3";
103 | developmentRegion = en;
104 | hasScannedForEncodings = 0;
105 | knownRegions = (
106 | en,
107 | );
108 | mainGroup = B80A055E267E1C3000AB6A91;
109 | productRefGroup = B80A0568267E1C3000AB6A91 /* Products */;
110 | projectDirPath = "";
111 | projectRoot = "";
112 | targets = (
113 | B80A0566267E1C3000AB6A91 /* Peak_Tester */,
114 | );
115 | };
116 | /* End PBXProject section */
117 |
118 | /* Begin PBXSourcesBuildPhase section */
119 | B80A0563267E1C3000AB6A91 /* Sources */ = {
120 | isa = PBXSourcesBuildPhase;
121 | buildActionMask = 2147483647;
122 | files = (
123 | B80A056B267E1C3000AB6A91 /* main.cpp in Sources */,
124 | );
125 | runOnlyForDeploymentPostprocessing = 0;
126 | };
127 | /* End PBXSourcesBuildPhase section */
128 |
129 | /* Begin XCBuildConfiguration section */
130 | B80A056C267E1C3000AB6A91 /* Debug */ = {
131 | isa = XCBuildConfiguration;
132 | buildSettings = {
133 | ALWAYS_SEARCH_USER_PATHS = NO;
134 | CLANG_ANALYZER_NONNULL = YES;
135 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
136 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
137 | CLANG_CXX_LIBRARY = "libc++";
138 | CLANG_ENABLE_MODULES = YES;
139 | CLANG_ENABLE_OBJC_ARC = YES;
140 | CLANG_ENABLE_OBJC_WEAK = YES;
141 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
142 | CLANG_WARN_BOOL_CONVERSION = YES;
143 | CLANG_WARN_COMMA = YES;
144 | CLANG_WARN_CONSTANT_CONVERSION = YES;
145 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
146 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
147 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
148 | CLANG_WARN_EMPTY_BODY = YES;
149 | CLANG_WARN_ENUM_CONVERSION = YES;
150 | CLANG_WARN_INFINITE_RECURSION = YES;
151 | CLANG_WARN_INT_CONVERSION = YES;
152 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
153 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
154 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
155 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
156 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
157 | CLANG_WARN_STRICT_PROTOTYPES = YES;
158 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
159 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
160 | CLANG_WARN_UNREACHABLE_CODE = YES;
161 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
162 | CODE_SIGN_IDENTITY = "-";
163 | COPY_PHASE_STRIP = NO;
164 | DEBUG_INFORMATION_FORMAT = dwarf;
165 | ENABLE_STRICT_OBJC_MSGSEND = YES;
166 | ENABLE_TESTABILITY = YES;
167 | GCC_C_LANGUAGE_STANDARD = gnu11;
168 | GCC_DYNAMIC_NO_PIC = NO;
169 | GCC_NO_COMMON_BLOCKS = YES;
170 | GCC_OPTIMIZATION_LEVEL = 0;
171 | GCC_PREPROCESSOR_DEFINITIONS = (
172 | "DEBUG=1",
173 | "$(inherited)",
174 | );
175 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
176 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
177 | GCC_WARN_UNDECLARED_SELECTOR = YES;
178 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
179 | GCC_WARN_UNUSED_FUNCTION = YES;
180 | GCC_WARN_UNUSED_VARIABLE = YES;
181 | MACOSX_DEPLOYMENT_TARGET = 10.13;
182 | MTL_ENABLE_DEBUG_INFO = YES;
183 | ONLY_ACTIVE_ARCH = YES;
184 | SDKROOT = macosx;
185 | };
186 | name = Debug;
187 | };
188 | B80A056D267E1C3000AB6A91 /* Release */ = {
189 | isa = XCBuildConfiguration;
190 | buildSettings = {
191 | ALWAYS_SEARCH_USER_PATHS = NO;
192 | CLANG_ANALYZER_NONNULL = YES;
193 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
194 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
195 | CLANG_CXX_LIBRARY = "libc++";
196 | CLANG_ENABLE_MODULES = YES;
197 | CLANG_ENABLE_OBJC_ARC = YES;
198 | CLANG_ENABLE_OBJC_WEAK = YES;
199 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
200 | CLANG_WARN_BOOL_CONVERSION = YES;
201 | CLANG_WARN_COMMA = YES;
202 | CLANG_WARN_CONSTANT_CONVERSION = YES;
203 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
204 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
205 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
206 | CLANG_WARN_EMPTY_BODY = YES;
207 | CLANG_WARN_ENUM_CONVERSION = YES;
208 | CLANG_WARN_INFINITE_RECURSION = YES;
209 | CLANG_WARN_INT_CONVERSION = YES;
210 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
211 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
212 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
213 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
214 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
215 | CLANG_WARN_STRICT_PROTOTYPES = YES;
216 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
217 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
218 | CLANG_WARN_UNREACHABLE_CODE = YES;
219 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
220 | CODE_SIGN_IDENTITY = "-";
221 | COPY_PHASE_STRIP = NO;
222 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
223 | ENABLE_NS_ASSERTIONS = NO;
224 | ENABLE_STRICT_OBJC_MSGSEND = YES;
225 | GCC_C_LANGUAGE_STANDARD = gnu11;
226 | GCC_NO_COMMON_BLOCKS = YES;
227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
229 | GCC_WARN_UNDECLARED_SELECTOR = YES;
230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
231 | GCC_WARN_UNUSED_FUNCTION = YES;
232 | GCC_WARN_UNUSED_VARIABLE = YES;
233 | MACOSX_DEPLOYMENT_TARGET = 10.13;
234 | MTL_ENABLE_DEBUG_INFO = NO;
235 | SDKROOT = macosx;
236 | };
237 | name = Release;
238 | };
239 | B80A056F267E1C3000AB6A91 /* Debug */ = {
240 | isa = XCBuildConfiguration;
241 | buildSettings = {
242 | CODE_SIGN_STYLE = Automatic;
243 | PRODUCT_NAME = "$(TARGET_NAME)";
244 | };
245 | name = Debug;
246 | };
247 | B80A0570267E1C3000AB6A91 /* Release */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | CODE_SIGN_STYLE = Automatic;
251 | PRODUCT_NAME = "$(TARGET_NAME)";
252 | };
253 | name = Release;
254 | };
255 | /* End XCBuildConfiguration section */
256 |
257 | /* Begin XCConfigurationList section */
258 | B80A0562267E1C3000AB6A91 /* Build configuration list for PBXProject "Peak_Tester" */ = {
259 | isa = XCConfigurationList;
260 | buildConfigurations = (
261 | B80A056C267E1C3000AB6A91 /* Debug */,
262 | B80A056D267E1C3000AB6A91 /* Release */,
263 | );
264 | defaultConfigurationIsVisible = 0;
265 | defaultConfigurationName = Release;
266 | };
267 | B80A056E267E1C3000AB6A91 /* Build configuration list for PBXNativeTarget "Peak_Tester" */ = {
268 | isa = XCConfigurationList;
269 | buildConfigurations = (
270 | B80A056F267E1C3000AB6A91 /* Debug */,
271 | B80A0570267E1C3000AB6A91 /* Release */,
272 | );
273 | defaultConfigurationIsVisible = 0;
274 | defaultConfigurationName = Release;
275 | };
276 | /* End XCConfigurationList section */
277 | };
278 | rootObject = B80A055F267E1C3000AB6A91 /* Project object */;
279 | }
280 |
--------------------------------------------------------------------------------
/RandomGenerator.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _RANDOMGENERATOR_HPP_
3 | #define _RANDOMGENERATOR_HPP_
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace random_generators
11 | {
12 | // Basic CMWC Generator
13 |
14 | // A complementary modulo with carry algorithm (proposed by George Marsaglia)
15 | // Details can be found in:
16 | // Marsaglia, G. (2003). "Random number generators". Journal of Modern Applied Statistical Methods 2
17 | // See - http://digitalcommons.wayne.edu/cgi/viewcontent.cgi?article=1725&context=jmasm
18 |
19 | // The memory requirement is 34 unsigned 32 bit integers (can be altered using cmwc_lag_size)
20 | // The period length is currently circa 2^1054 - 1 which shold be more than adequate for most purposes
21 |
22 | // N.B. cmwc_lag_size must be a power of two
23 | // N.B. cmwc_a_value should be a suitable value according to cmwc_lag_size
24 |
25 | class cmwc
26 | {
27 | static constexpr uint32_t cmwc_lag_size = 32;
28 | static constexpr uint64_t cmwc_a_value = 987655670LL;
29 |
30 | public:
31 |
32 | inline uint32_t operator()()
33 | {
34 | uint32_t i = m_increment;
35 | uint32_t c = m_carry;
36 | uint32_t x;
37 |
38 | uint64_t t;
39 |
40 | i = (i + 1) & (cmwc_lag_size - 1);
41 | t = cmwc_a_value * m_state[i] + c;
42 | c = (t >> 32);
43 | x = static_cast((t + c) & 0xFFFFFFFF);
44 |
45 | if (x < c)
46 | {
47 | x++;
48 | c++;
49 | }
50 |
51 | m_state[i] = (0xFFFFFFFE - x);
52 | m_increment = i;
53 | m_carry = c;
54 |
55 | return m_state[i];
56 | }
57 |
58 | // Seeding (specific / OS-specific random values)
59 |
60 | void seed(uint32_t *init)
61 | {
62 | m_increment = (cmwc_lag_size - 1);
63 | m_carry = 123;
64 |
65 | for (uint32_t i = 0; i < cmwc_lag_size; i++)
66 | m_state[i] = init[i];
67 | }
68 |
69 | void rand_seed()
70 | {
71 | uint32_t seeds[cmwc_lag_size];
72 |
73 | std::random_device rd;
74 |
75 | for (uint32_t i = 0; i < cmwc_lag_size; i++)
76 | seeds[i] = rd();
77 |
78 | seed(seeds);
79 | }
80 |
81 | // State
82 |
83 | uint32_t m_increment;
84 | uint32_t m_carry;
85 | uint32_t m_state[cmwc_lag_size];
86 | };
87 | }
88 |
89 | template
90 | class random_generator
91 | {
92 | public:
93 |
94 | class windowed_gaussian_params
95 | {
96 | friend random_generator;
97 |
98 | public:
99 |
100 | windowed_gaussian_params(double mean, double dev) : m_mean(mean), m_dev(dev)
101 | {
102 | constexpr double inf = HUGE_VAL;
103 |
104 | const double a = 1.0 / (dev * sqrt(2.0));
105 | const double b = -mean * a;
106 |
107 | m_lo = erf(b);
108 | m_hi = erf(a + b);
109 |
110 | // N.B. inf is fine as an input, but nan is not...
111 |
112 | m_lo = std::isnan(m_lo) ? erf(-inf) : m_lo;
113 | m_hi = std::isnan(m_hi) ? erf( inf) : m_hi;
114 | };
115 |
116 | double mean() const { return m_mean; }
117 | double dev() const { return m_dev; }
118 |
119 | private:
120 |
121 | double m_mean;
122 | double m_dev;
123 | double m_lo;
124 | double m_hi;
125 | };
126 |
127 | random_generator() { m_generator.rand_seed(); }
128 | random_generator(uint32_t *init) { m_generator.seed(init); }
129 |
130 | // Seeding (specific / random values)
131 |
132 | void seed(uint32_t *init) { m_generator.seed(init); }
133 | void rand_seed() { m_generator.rand_seed(); }
134 |
135 | // Generate a Single Pseudo-random Unsigned Integer (full range / in the range [0, n] / in the range [lo, hi])
136 |
137 | uint32_t rand_int()
138 | {
139 | return m_generator();
140 | }
141 |
142 | uint32_t rand_int(uint32_t n)
143 | {
144 | uint32_t used = n;
145 | uint32_t i;
146 |
147 | used |= used >> 1;
148 | used |= used >> 2;
149 | used |= used >> 4;
150 | used |= used >> 8;
151 | used |= used >> 16;
152 |
153 | do
154 | i = rand_int() & used; // toss unused bits shortens search
155 | while (i > n);
156 |
157 | return i;
158 | }
159 |
160 | int32_t rand_int(int32_t lo, int32_t hi)
161 | {
162 | return lo + rand_int(hi - lo);
163 | }
164 |
165 | // Generate a 32 bit Random Double (in the range [0,1] / in the range [0, n] / in the range [lo, hi])
166 |
167 | double rand_double() { return rand_int() * 2.32830643653869628906e-10; }
168 | double rand_double(double n) { return rand_double() * n; }
169 | double rand_double(double lo, double hi) { return lo + rand_double() * (hi - lo); }
170 |
171 | // Generate a 32 bit Random Double of Gaussian Distribution with given Mean / Deviation
172 |
173 | double rand_gaussian(double mean, double dev)
174 | {
175 | double x, y, R;
176 |
177 | rand_gaussians(x, y, R);
178 |
179 | return (R * x) * dev + mean;
180 | }
181 |
182 | // Generate two independent gaussians (Mean 0 and Deviation 1)
183 |
184 | void rand_gaussians(double& x, double& y)
185 | {
186 | double R;
187 |
188 | rand_gaussians(x, y, R);
189 |
190 | x *= R;
191 | y *= R;
192 | }
193 |
194 | double rand_windowed_gaussian(const windowed_gaussian_params& params)
195 | {
196 | const double r = ltqnorm(0.5 + 0.5 * rand_double(params.m_lo, params.m_hi)) * params.dev() + params.mean();
197 | return std::max(0.0, std::min(1.0, r));
198 | }
199 |
200 | double rand_windowed_gaussian(double mean, double dev)
201 | {
202 | const windowed_gaussian_params params(mean, dev);
203 | return rand_windowed_gaussian(params);
204 | }
205 |
206 | private:
207 |
208 | // Gaussian Helper
209 |
210 | void rand_gaussians(double& x, double& y, double& R)
211 | {
212 | x = 0.0;
213 | y = 0.0;
214 | R = 0.0;
215 |
216 | while (R >= 1.0 || R == 0.0)
217 | {
218 | x = rand_double(-1.0, 1.0);
219 | y = rand_double(-1.0, 1.0);
220 | R = (x * x) + (y * y);
221 | }
222 |
223 | R = sqrt((-2.0 * std::log(R)) / R);
224 | }
225 |
226 | // This is adapted from http://home.online.no/~pjacklam/notes/invnorm/impl/sprouse/ltqnorm.c
227 |
228 | /*
229 | * Lower tail quantile for standard normal distribution function.
230 | *
231 | * This function returns an approximation of the inverse cumulative
232 | * standard normal distribution function. I.e., given P, it returns
233 | * an approximation to the X satisfying P = Pr{Z <= X} where Z is a
234 | * random variable from the standard normal distribution.
235 | *
236 | * The algorithm uses a minimax approximation by rational functions
237 | * and the result has a relative error whose absolute value is less
238 | * than 1.15e-9.
239 | *
240 | * Author: Peter J. Acklam
241 | * Time-stamp: 2002-06-09 18:45:44 +0200
242 | * E-mail: jacklam@math.uio.no
243 | * WWW URL: http://www.math.uio.no/~jacklam
244 | *
245 | */
246 |
247 | double ltqnorm(double p)
248 | {
249 | /* Coefficients in rational approximations. */
250 |
251 | constexpr double a[] =
252 | {
253 | -3.969683028665376e+01,
254 | 2.209460984245205e+02,
255 | -2.759285104469687e+02,
256 | 1.383577518672690e+02,
257 | -3.066479806614716e+01,
258 | 2.506628277459239e+00
259 | };
260 |
261 | constexpr double b[] =
262 | {
263 | -5.447609879822406e+01,
264 | 1.615858368580409e+02,
265 | -1.556989798598866e+02,
266 | 6.680131188771972e+01,
267 | -1.328068155288572e+01
268 | };
269 |
270 | constexpr double c[] =
271 | {
272 | -7.784894002430293e-03,
273 | -3.223964580411365e-01,
274 | -2.400758277161838e+00,
275 | -2.549732539343734e+00,
276 | 4.374664141464968e+00,
277 | 2.938163982698783e+00
278 | };
279 |
280 | constexpr double d[] =
281 | {
282 | 7.784695709041462e-03,
283 | 3.224671290700398e-01,
284 | 2.445134137142996e+00,
285 | 3.754408661907416e+00
286 | };
287 |
288 | constexpr double low = 0.02425;
289 | constexpr double high = 0.97575;
290 |
291 | double q, r;
292 |
293 | errno = 0;
294 |
295 | if (p < 0 || p > 1)
296 | {
297 | errno = EDOM;
298 | return 0.0;
299 | }
300 | else if (p == 0)
301 | {
302 | errno = ERANGE;
303 | return -HUGE_VAL /* minus "infinity" */;
304 | }
305 | else if (p == 1)
306 | {
307 | errno = ERANGE;
308 | return HUGE_VAL /* "infinity" */;
309 | }
310 | else if (p < low)
311 | {
312 | /* Rational approximation for lower region */
313 |
314 | q = sqrt(-2.0*std::log(p));
315 | return (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
316 | ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
317 | }
318 | else if (p > high)
319 | {
320 | /* Rational approximation for upper region */
321 |
322 | q = sqrt(-2.0*std::log(1-p));
323 | return -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
324 | ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
325 | }
326 | else
327 | {
328 | /* Rational approximation for central region */
329 |
330 | q = p - 0.5;
331 | r = q*q;
332 | return (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q /
333 | (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1);
334 | }
335 | }
336 | // State
337 |
338 | Generator m_generator;
339 | };
340 |
341 | #endif
342 |
--------------------------------------------------------------------------------
/- Test/FFT_Tester/FFT_Tester.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B82AAC2C1F61FC0C0015CDCF /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B82AAC2B1F61FC0C0015CDCF /* main.cpp */; };
11 | B82AAC341F61FC1C0015CDCF /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B82AAC321F61FC1C0015CDCF /* HISSTools_FFT.cpp */; };
12 | B8378E1022BCC9FF004F8598 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8378E0F22BCC9FF004F8598 /* Accelerate.framework */; };
13 | /* End PBXBuildFile section */
14 |
15 | /* Begin PBXCopyFilesBuildPhase section */
16 | B82AAC261F61FC0C0015CDCF /* CopyFiles */ = {
17 | isa = PBXCopyFilesBuildPhase;
18 | buildActionMask = 2147483647;
19 | dstPath = /usr/share/man/man1/;
20 | dstSubfolderSpec = 0;
21 | files = (
22 | );
23 | runOnlyForDeploymentPostprocessing = 1;
24 | };
25 | /* End PBXCopyFilesBuildPhase section */
26 |
27 | /* Begin PBXFileReference section */
28 | B82AAC281F61FC0C0015CDCF /* FFT Tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "FFT Tester"; sourceTree = BUILT_PRODUCTS_DIR; };
29 | B82AAC2B1F61FC0C0015CDCF /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; };
30 | B82AAC321F61FC1C0015CDCF /* HISSTools_FFT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HISSTools_FFT.cpp; path = ../../../HISSTools_FFT/HISSTools_FFT.cpp; sourceTree = ""; };
31 | B82AAC331F61FC1C0015CDCF /* HISSTools_FFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HISSTools_FFT.h; path = ../../../HISSTools_FFT/HISSTools_FFT.h; sourceTree = ""; };
32 | B82AAC371F6217970015CDCF /* HISSTools_FFT_Core.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HISSTools_FFT_Core.h; path = ../../../HISSTools_FFT/HISSTools_FFT_Core.h; sourceTree = ""; };
33 | B8378E0F22BCC9FF004F8598 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
34 | /* End PBXFileReference section */
35 |
36 | /* Begin PBXFrameworksBuildPhase section */
37 | B82AAC251F61FC0C0015CDCF /* Frameworks */ = {
38 | isa = PBXFrameworksBuildPhase;
39 | buildActionMask = 2147483647;
40 | files = (
41 | B8378E1022BCC9FF004F8598 /* Accelerate.framework in Frameworks */,
42 | );
43 | runOnlyForDeploymentPostprocessing = 0;
44 | };
45 | /* End PBXFrameworksBuildPhase section */
46 |
47 | /* Begin PBXGroup section */
48 | B82AAC1F1F61FC0C0015CDCF = {
49 | isa = PBXGroup;
50 | children = (
51 | B82AAC2A1F61FC0C0015CDCF /* FFT_Tester */,
52 | B82AAC291F61FC0C0015CDCF /* Products */,
53 | B8378E0E22BCC9FE004F8598 /* Frameworks */,
54 | );
55 | sourceTree = "";
56 | };
57 | B82AAC291F61FC0C0015CDCF /* Products */ = {
58 | isa = PBXGroup;
59 | children = (
60 | B82AAC281F61FC0C0015CDCF /* FFT Tester */,
61 | );
62 | name = Products;
63 | sourceTree = "";
64 | };
65 | B82AAC2A1F61FC0C0015CDCF /* FFT_Tester */ = {
66 | isa = PBXGroup;
67 | children = (
68 | B82AAC331F61FC1C0015CDCF /* HISSTools_FFT.h */,
69 | B82AAC321F61FC1C0015CDCF /* HISSTools_FFT.cpp */,
70 | B82AAC371F6217970015CDCF /* HISSTools_FFT_Core.h */,
71 | B82AAC2B1F61FC0C0015CDCF /* main.cpp */,
72 | );
73 | path = FFT_Tester;
74 | sourceTree = "";
75 | };
76 | B8378E0E22BCC9FE004F8598 /* Frameworks */ = {
77 | isa = PBXGroup;
78 | children = (
79 | B8378E0F22BCC9FF004F8598 /* Accelerate.framework */,
80 | );
81 | name = Frameworks;
82 | sourceTree = "";
83 | };
84 | /* End PBXGroup section */
85 |
86 | /* Begin PBXNativeTarget section */
87 | B82AAC271F61FC0C0015CDCF /* FFT_Tester */ = {
88 | isa = PBXNativeTarget;
89 | buildConfigurationList = B82AAC2F1F61FC0C0015CDCF /* Build configuration list for PBXNativeTarget "FFT_Tester" */;
90 | buildPhases = (
91 | B82AAC241F61FC0C0015CDCF /* Sources */,
92 | B82AAC251F61FC0C0015CDCF /* Frameworks */,
93 | B82AAC261F61FC0C0015CDCF /* CopyFiles */,
94 | );
95 | buildRules = (
96 | );
97 | dependencies = (
98 | );
99 | name = FFT_Tester;
100 | productName = "FFT Tester";
101 | productReference = B82AAC281F61FC0C0015CDCF /* FFT Tester */;
102 | productType = "com.apple.product-type.tool";
103 | };
104 | /* End PBXNativeTarget section */
105 |
106 | /* Begin PBXProject section */
107 | B82AAC201F61FC0C0015CDCF /* Project object */ = {
108 | isa = PBXProject;
109 | attributes = {
110 | LastUpgradeCheck = 0830;
111 | ORGANIZATIONNAME = "Alex Harker";
112 | TargetAttributes = {
113 | B82AAC271F61FC0C0015CDCF = {
114 | CreatedOnToolsVersion = 8.3.3;
115 | ProvisioningStyle = Automatic;
116 | };
117 | };
118 | };
119 | buildConfigurationList = B82AAC231F61FC0C0015CDCF /* Build configuration list for PBXProject "FFT_Tester" */;
120 | compatibilityVersion = "Xcode 3.2";
121 | developmentRegion = English;
122 | hasScannedForEncodings = 0;
123 | knownRegions = (
124 | en,
125 | );
126 | mainGroup = B82AAC1F1F61FC0C0015CDCF;
127 | productRefGroup = B82AAC291F61FC0C0015CDCF /* Products */;
128 | projectDirPath = "";
129 | projectRoot = "";
130 | targets = (
131 | B82AAC271F61FC0C0015CDCF /* FFT_Tester */,
132 | );
133 | };
134 | /* End PBXProject section */
135 |
136 | /* Begin PBXSourcesBuildPhase section */
137 | B82AAC241F61FC0C0015CDCF /* Sources */ = {
138 | isa = PBXSourcesBuildPhase;
139 | buildActionMask = 2147483647;
140 | files = (
141 | B82AAC2C1F61FC0C0015CDCF /* main.cpp in Sources */,
142 | B82AAC341F61FC1C0015CDCF /* HISSTools_FFT.cpp in Sources */,
143 | );
144 | runOnlyForDeploymentPostprocessing = 0;
145 | };
146 | /* End PBXSourcesBuildPhase section */
147 |
148 | /* Begin XCBuildConfiguration section */
149 | B82AAC2D1F61FC0C0015CDCF /* Debug */ = {
150 | isa = XCBuildConfiguration;
151 | buildSettings = {
152 | ALWAYS_SEARCH_USER_PATHS = NO;
153 | CLANG_ANALYZER_NONNULL = YES;
154 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
155 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
156 | CLANG_CXX_LIBRARY = "libc++";
157 | CLANG_ENABLE_MODULES = YES;
158 | CLANG_ENABLE_OBJC_ARC = YES;
159 | CLANG_WARN_BOOL_CONVERSION = YES;
160 | CLANG_WARN_CONSTANT_CONVERSION = YES;
161 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
162 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
163 | CLANG_WARN_EMPTY_BODY = YES;
164 | CLANG_WARN_ENUM_CONVERSION = YES;
165 | CLANG_WARN_INFINITE_RECURSION = YES;
166 | CLANG_WARN_INT_CONVERSION = YES;
167 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
168 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
169 | CLANG_WARN_UNREACHABLE_CODE = YES;
170 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
171 | CODE_SIGN_IDENTITY = "-";
172 | COPY_PHASE_STRIP = NO;
173 | DEBUG_INFORMATION_FORMAT = dwarf;
174 | ENABLE_STRICT_OBJC_MSGSEND = YES;
175 | ENABLE_TESTABILITY = YES;
176 | GCC_C_LANGUAGE_STANDARD = gnu99;
177 | GCC_DYNAMIC_NO_PIC = NO;
178 | GCC_NO_COMMON_BLOCKS = YES;
179 | GCC_OPTIMIZATION_LEVEL = 0;
180 | GCC_PREPROCESSOR_DEFINITIONS = (
181 | "DEBUG=1",
182 | "$(inherited)",
183 | );
184 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
185 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
186 | GCC_WARN_UNDECLARED_SELECTOR = YES;
187 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
188 | GCC_WARN_UNUSED_FUNCTION = YES;
189 | GCC_WARN_UNUSED_VARIABLE = YES;
190 | MACOSX_DEPLOYMENT_TARGET = 10.12;
191 | MTL_ENABLE_DEBUG_INFO = YES;
192 | ONLY_ACTIVE_ARCH = YES;
193 | SDKROOT = macosx;
194 | };
195 | name = Debug;
196 | };
197 | B82AAC2E1F61FC0C0015CDCF /* Release */ = {
198 | isa = XCBuildConfiguration;
199 | buildSettings = {
200 | ALWAYS_SEARCH_USER_PATHS = NO;
201 | CLANG_ANALYZER_NONNULL = YES;
202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
204 | CLANG_CXX_LIBRARY = "libc++";
205 | CLANG_ENABLE_MODULES = YES;
206 | CLANG_ENABLE_OBJC_ARC = YES;
207 | CLANG_WARN_BOOL_CONVERSION = YES;
208 | CLANG_WARN_CONSTANT_CONVERSION = YES;
209 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
210 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
211 | CLANG_WARN_EMPTY_BODY = YES;
212 | CLANG_WARN_ENUM_CONVERSION = YES;
213 | CLANG_WARN_INFINITE_RECURSION = YES;
214 | CLANG_WARN_INT_CONVERSION = YES;
215 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
216 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
217 | CLANG_WARN_UNREACHABLE_CODE = YES;
218 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
219 | CODE_SIGN_IDENTITY = "-";
220 | COPY_PHASE_STRIP = NO;
221 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
222 | ENABLE_NS_ASSERTIONS = NO;
223 | ENABLE_STRICT_OBJC_MSGSEND = YES;
224 | GCC_C_LANGUAGE_STANDARD = gnu99;
225 | GCC_NO_COMMON_BLOCKS = YES;
226 | GCC_PREPROCESSOR_DEFINITIONS = "";
227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
229 | GCC_WARN_UNDECLARED_SELECTOR = YES;
230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
231 | GCC_WARN_UNUSED_FUNCTION = YES;
232 | GCC_WARN_UNUSED_VARIABLE = YES;
233 | MACOSX_DEPLOYMENT_TARGET = 10.12;
234 | MTL_ENABLE_DEBUG_INFO = NO;
235 | SDKROOT = macosx;
236 | };
237 | name = Release;
238 | };
239 | B82AAC301F61FC0C0015CDCF /* Debug */ = {
240 | isa = XCBuildConfiguration;
241 | buildSettings = {
242 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
243 | CLANG_X86_VECTOR_INSTRUCTIONS = avx;
244 | GCC_PREPROCESSOR_DEFINITIONS = (
245 | "NO_NATIVE_FFT=1",
246 | "$(inherited)",
247 | );
248 | PRODUCT_NAME = "$(TARGET_NAME)";
249 | };
250 | name = Debug;
251 | };
252 | B82AAC311F61FC0C0015CDCF /* Release */ = {
253 | isa = XCBuildConfiguration;
254 | buildSettings = {
255 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
256 | CLANG_X86_VECTOR_INSTRUCTIONS = avx;
257 | GCC_PREPROCESSOR_DEFINITIONS = (
258 | "$(inherited)",
259 | "NO_NATIVE_FFT=1",
260 | );
261 | PRODUCT_NAME = "$(TARGET_NAME)";
262 | };
263 | name = Release;
264 | };
265 | /* End XCBuildConfiguration section */
266 |
267 | /* Begin XCConfigurationList section */
268 | B82AAC231F61FC0C0015CDCF /* Build configuration list for PBXProject "FFT_Tester" */ = {
269 | isa = XCConfigurationList;
270 | buildConfigurations = (
271 | B82AAC2D1F61FC0C0015CDCF /* Debug */,
272 | B82AAC2E1F61FC0C0015CDCF /* Release */,
273 | );
274 | defaultConfigurationIsVisible = 0;
275 | defaultConfigurationName = Release;
276 | };
277 | B82AAC2F1F61FC0C0015CDCF /* Build configuration list for PBXNativeTarget "FFT_Tester" */ = {
278 | isa = XCConfigurationList;
279 | buildConfigurations = (
280 | B82AAC301F61FC0C0015CDCF /* Debug */,
281 | B82AAC311F61FC0C0015CDCF /* Release */,
282 | );
283 | defaultConfigurationIsVisible = 0;
284 | defaultConfigurationName = Release;
285 | };
286 | /* End XCConfigurationList section */
287 | };
288 | rootObject = B82AAC201F61FC0C0015CDCF /* Project object */;
289 | }
290 |
--------------------------------------------------------------------------------
/- Test/Window_Tester/Window_Tester.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B8C2DD6F24F94B28000EF2D0 /* OAudioFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8C2DD6E24F94B27000EF2D0 /* OAudioFile.cpp */; };
11 | B8C2DD7224F94C56000EF2D0 /* BaseAudioFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8C2DD7124F94C56000EF2D0 /* BaseAudioFile.cpp */; };
12 | B8E728FD24F8288B0041006F /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8E728FC24F8288B0041006F /* main.cpp */; };
13 | /* End PBXBuildFile section */
14 |
15 | /* Begin PBXCopyFilesBuildPhase section */
16 | B8E728F724F8288B0041006F /* CopyFiles */ = {
17 | isa = PBXCopyFilesBuildPhase;
18 | buildActionMask = 2147483647;
19 | dstPath = /usr/share/man/man1/;
20 | dstSubfolderSpec = 0;
21 | files = (
22 | );
23 | runOnlyForDeploymentPostprocessing = 1;
24 | };
25 | /* End PBXCopyFilesBuildPhase section */
26 |
27 | /* Begin PBXFileReference section */
28 | B8C2DD6E24F94B27000EF2D0 /* OAudioFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OAudioFile.cpp; path = ../../../AudioFile/OAudioFile.cpp; sourceTree = ""; };
29 | B8C2DD7024F94B30000EF2D0 /* WindowFunctions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = WindowFunctions.hpp; path = ../../../WindowFunctions.hpp; sourceTree = ""; };
30 | B8C2DD7124F94C56000EF2D0 /* BaseAudioFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BaseAudioFile.cpp; path = ../../../AudioFile/BaseAudioFile.cpp; sourceTree = ""; };
31 | B8E728F924F8288B0041006F /* Window_Tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Window_Tester; sourceTree = BUILT_PRODUCTS_DIR; };
32 | B8E728FC24F8288B0041006F /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | B8E728F624F8288B0041006F /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | B8E728F024F8288B0041006F = {
47 | isa = PBXGroup;
48 | children = (
49 | B8E728FB24F8288B0041006F /* Window_Tester */,
50 | B8E728FA24F8288B0041006F /* Products */,
51 | );
52 | sourceTree = "";
53 | };
54 | B8E728FA24F8288B0041006F /* Products */ = {
55 | isa = PBXGroup;
56 | children = (
57 | B8E728F924F8288B0041006F /* Window_Tester */,
58 | );
59 | name = Products;
60 | sourceTree = "";
61 | };
62 | B8E728FB24F8288B0041006F /* Window_Tester */ = {
63 | isa = PBXGroup;
64 | children = (
65 | B8C2DD7024F94B30000EF2D0 /* WindowFunctions.hpp */,
66 | B8E728FC24F8288B0041006F /* main.cpp */,
67 | B8C2DD6E24F94B27000EF2D0 /* OAudioFile.cpp */,
68 | B8C2DD7124F94C56000EF2D0 /* BaseAudioFile.cpp */,
69 | );
70 | path = Window_Tester;
71 | sourceTree = "";
72 | };
73 | /* End PBXGroup section */
74 |
75 | /* Begin PBXNativeTarget section */
76 | B8E728F824F8288B0041006F /* Window_Tester */ = {
77 | isa = PBXNativeTarget;
78 | buildConfigurationList = B8E7290024F8288B0041006F /* Build configuration list for PBXNativeTarget "Window_Tester" */;
79 | buildPhases = (
80 | B8E728F524F8288B0041006F /* Sources */,
81 | B8E728F624F8288B0041006F /* Frameworks */,
82 | B8E728F724F8288B0041006F /* CopyFiles */,
83 | );
84 | buildRules = (
85 | );
86 | dependencies = (
87 | );
88 | name = Window_Tester;
89 | productName = WindowTesting;
90 | productReference = B8E728F924F8288B0041006F /* Window_Tester */;
91 | productType = "com.apple.product-type.tool";
92 | };
93 | /* End PBXNativeTarget section */
94 |
95 | /* Begin PBXProject section */
96 | B8E728F124F8288B0041006F /* Project object */ = {
97 | isa = PBXProject;
98 | attributes = {
99 | LastUpgradeCheck = 0940;
100 | ORGANIZATIONNAME = AHarker;
101 | TargetAttributes = {
102 | B8E728F824F8288B0041006F = {
103 | CreatedOnToolsVersion = 9.4.1;
104 | };
105 | };
106 | };
107 | buildConfigurationList = B8E728F424F8288B0041006F /* Build configuration list for PBXProject "Window_Tester" */;
108 | compatibilityVersion = "Xcode 9.3";
109 | developmentRegion = en;
110 | hasScannedForEncodings = 0;
111 | knownRegions = (
112 | en,
113 | );
114 | mainGroup = B8E728F024F8288B0041006F;
115 | productRefGroup = B8E728FA24F8288B0041006F /* Products */;
116 | projectDirPath = "";
117 | projectRoot = "";
118 | targets = (
119 | B8E728F824F8288B0041006F /* Window_Tester */,
120 | );
121 | };
122 | /* End PBXProject section */
123 |
124 | /* Begin PBXSourcesBuildPhase section */
125 | B8E728F524F8288B0041006F /* Sources */ = {
126 | isa = PBXSourcesBuildPhase;
127 | buildActionMask = 2147483647;
128 | files = (
129 | B8C2DD7224F94C56000EF2D0 /* BaseAudioFile.cpp in Sources */,
130 | B8C2DD6F24F94B28000EF2D0 /* OAudioFile.cpp in Sources */,
131 | B8E728FD24F8288B0041006F /* main.cpp in Sources */,
132 | );
133 | runOnlyForDeploymentPostprocessing = 0;
134 | };
135 | /* End PBXSourcesBuildPhase section */
136 |
137 | /* Begin XCBuildConfiguration section */
138 | B8E728FE24F8288B0041006F /* Debug */ = {
139 | isa = XCBuildConfiguration;
140 | buildSettings = {
141 | ALWAYS_SEARCH_USER_PATHS = NO;
142 | CLANG_ANALYZER_NONNULL = YES;
143 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
144 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
145 | CLANG_CXX_LIBRARY = "libc++";
146 | CLANG_ENABLE_MODULES = YES;
147 | CLANG_ENABLE_OBJC_ARC = YES;
148 | CLANG_ENABLE_OBJC_WEAK = YES;
149 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
150 | CLANG_WARN_BOOL_CONVERSION = YES;
151 | CLANG_WARN_COMMA = YES;
152 | CLANG_WARN_CONSTANT_CONVERSION = YES;
153 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
154 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
155 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
156 | CLANG_WARN_EMPTY_BODY = YES;
157 | CLANG_WARN_ENUM_CONVERSION = YES;
158 | CLANG_WARN_INFINITE_RECURSION = YES;
159 | CLANG_WARN_INT_CONVERSION = YES;
160 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
161 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
162 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
163 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
164 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
165 | CLANG_WARN_STRICT_PROTOTYPES = YES;
166 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
167 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
168 | CLANG_WARN_UNREACHABLE_CODE = YES;
169 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
170 | CODE_SIGN_IDENTITY = "-";
171 | COPY_PHASE_STRIP = NO;
172 | DEBUG_INFORMATION_FORMAT = dwarf;
173 | ENABLE_STRICT_OBJC_MSGSEND = YES;
174 | ENABLE_TESTABILITY = YES;
175 | GCC_C_LANGUAGE_STANDARD = gnu11;
176 | GCC_DYNAMIC_NO_PIC = NO;
177 | GCC_NO_COMMON_BLOCKS = YES;
178 | GCC_OPTIMIZATION_LEVEL = 0;
179 | GCC_PREPROCESSOR_DEFINITIONS = (
180 | "DEBUG=1",
181 | "$(inherited)",
182 | );
183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185 | GCC_WARN_UNDECLARED_SELECTOR = YES;
186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187 | GCC_WARN_UNUSED_FUNCTION = YES;
188 | GCC_WARN_UNUSED_VARIABLE = YES;
189 | MACOSX_DEPLOYMENT_TARGET = 10.13;
190 | MTL_ENABLE_DEBUG_INFO = YES;
191 | ONLY_ACTIVE_ARCH = YES;
192 | SDKROOT = macosx;
193 | };
194 | name = Debug;
195 | };
196 | B8E728FF24F8288B0041006F /* Release */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | ALWAYS_SEARCH_USER_PATHS = NO;
200 | CLANG_ANALYZER_NONNULL = YES;
201 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
203 | CLANG_CXX_LIBRARY = "libc++";
204 | CLANG_ENABLE_MODULES = YES;
205 | CLANG_ENABLE_OBJC_ARC = YES;
206 | CLANG_ENABLE_OBJC_WEAK = YES;
207 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
208 | CLANG_WARN_BOOL_CONVERSION = YES;
209 | CLANG_WARN_COMMA = YES;
210 | CLANG_WARN_CONSTANT_CONVERSION = YES;
211 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
214 | CLANG_WARN_EMPTY_BODY = YES;
215 | CLANG_WARN_ENUM_CONVERSION = YES;
216 | CLANG_WARN_INFINITE_RECURSION = YES;
217 | CLANG_WARN_INT_CONVERSION = YES;
218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
219 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
220 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
222 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
223 | CLANG_WARN_STRICT_PROTOTYPES = YES;
224 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
225 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
226 | CLANG_WARN_UNREACHABLE_CODE = YES;
227 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
228 | CODE_SIGN_IDENTITY = "-";
229 | COPY_PHASE_STRIP = NO;
230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
231 | ENABLE_NS_ASSERTIONS = NO;
232 | ENABLE_STRICT_OBJC_MSGSEND = YES;
233 | GCC_C_LANGUAGE_STANDARD = gnu11;
234 | GCC_NO_COMMON_BLOCKS = YES;
235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
237 | GCC_WARN_UNDECLARED_SELECTOR = YES;
238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
239 | GCC_WARN_UNUSED_FUNCTION = YES;
240 | GCC_WARN_UNUSED_VARIABLE = YES;
241 | MACOSX_DEPLOYMENT_TARGET = 10.13;
242 | MTL_ENABLE_DEBUG_INFO = NO;
243 | SDKROOT = macosx;
244 | };
245 | name = Release;
246 | };
247 | B8E7290124F8288B0041006F /* Debug */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | CODE_SIGN_STYLE = Automatic;
251 | PRODUCT_NAME = "$(TARGET_NAME)";
252 | };
253 | name = Debug;
254 | };
255 | B8E7290224F8288B0041006F /* Release */ = {
256 | isa = XCBuildConfiguration;
257 | buildSettings = {
258 | CODE_SIGN_STYLE = Automatic;
259 | PRODUCT_NAME = "$(TARGET_NAME)";
260 | };
261 | name = Release;
262 | };
263 | /* End XCBuildConfiguration section */
264 |
265 | /* Begin XCConfigurationList section */
266 | B8E728F424F8288B0041006F /* Build configuration list for PBXProject "Window_Tester" */ = {
267 | isa = XCConfigurationList;
268 | buildConfigurations = (
269 | B8E728FE24F8288B0041006F /* Debug */,
270 | B8E728FF24F8288B0041006F /* Release */,
271 | );
272 | defaultConfigurationIsVisible = 0;
273 | defaultConfigurationName = Release;
274 | };
275 | B8E7290024F8288B0041006F /* Build configuration list for PBXNativeTarget "Window_Tester" */ = {
276 | isa = XCConfigurationList;
277 | buildConfigurations = (
278 | B8E7290124F8288B0041006F /* Debug */,
279 | B8E7290224F8288B0041006F /* Release */,
280 | );
281 | defaultConfigurationIsVisible = 0;
282 | defaultConfigurationName = Release;
283 | };
284 | /* End XCConfigurationList section */
285 | };
286 | rootObject = B8E728F124F8288B0041006F /* Project object */;
287 | }
288 |
--------------------------------------------------------------------------------
/- Test/IR_Manipulation_Tester/IR_Manipulation_Tester.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B822E66E22FB455100368AE7 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B822E66D22FB455100368AE7 /* main.cpp */; };
11 | B822E67922FC184700368AE7 /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B822E67822FC184700368AE7 /* HISSTools_FFT.cpp */; };
12 | B822E67C22FC185C00368AE7 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B822E67B22FC185C00368AE7 /* Accelerate.framework */; };
13 | /* End PBXBuildFile section */
14 |
15 | /* Begin PBXCopyFilesBuildPhase section */
16 | B822E66822FB455100368AE7 /* CopyFiles */ = {
17 | isa = PBXCopyFilesBuildPhase;
18 | buildActionMask = 2147483647;
19 | dstPath = /usr/share/man/man1/;
20 | dstSubfolderSpec = 0;
21 | files = (
22 | );
23 | runOnlyForDeploymentPostprocessing = 1;
24 | };
25 | /* End PBXCopyFilesBuildPhase section */
26 |
27 | /* Begin PBXFileReference section */
28 | B822E66A22FB455100368AE7 /* IR_Manipulation_Tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = IR_Manipulation_Tester; sourceTree = BUILT_PRODUCTS_DIR; };
29 | B822E66D22FB455100368AE7 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; };
30 | B822E67822FC184700368AE7 /* HISSTools_FFT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HISSTools_FFT.cpp; path = ../../../HISSTools_FFT/HISSTools_FFT.cpp; sourceTree = ""; };
31 | B822E67B22FC185C00368AE7 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
32 | B82A03F42302B61C00F887E7 /* SpectralFunctions.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SpectralFunctions.hpp; path = ../../../SpectralFunctions.hpp; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | B822E66722FB455100368AE7 /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | B822E67C22FC185C00368AE7 /* Accelerate.framework in Frameworks */,
41 | );
42 | runOnlyForDeploymentPostprocessing = 0;
43 | };
44 | /* End PBXFrameworksBuildPhase section */
45 |
46 | /* Begin PBXGroup section */
47 | B822E66122FB455100368AE7 = {
48 | isa = PBXGroup;
49 | children = (
50 | B822E66C22FB455100368AE7 /* IR_Manipulation_Tester */,
51 | B822E66B22FB455100368AE7 /* Products */,
52 | B822E67A22FC185B00368AE7 /* Frameworks */,
53 | );
54 | sourceTree = "";
55 | };
56 | B822E66B22FB455100368AE7 /* Products */ = {
57 | isa = PBXGroup;
58 | children = (
59 | B822E66A22FB455100368AE7 /* IR_Manipulation_Tester */,
60 | );
61 | name = Products;
62 | sourceTree = "";
63 | };
64 | B822E66C22FB455100368AE7 /* IR_Manipulation_Tester */ = {
65 | isa = PBXGroup;
66 | children = (
67 | B822E66D22FB455100368AE7 /* main.cpp */,
68 | B82A03F42302B61C00F887E7 /* SpectralFunctions.hpp */,
69 | B822E67822FC184700368AE7 /* HISSTools_FFT.cpp */,
70 | );
71 | path = IR_Manipulation_Tester;
72 | sourceTree = "";
73 | };
74 | B822E67A22FC185B00368AE7 /* Frameworks */ = {
75 | isa = PBXGroup;
76 | children = (
77 | B822E67B22FC185C00368AE7 /* Accelerate.framework */,
78 | );
79 | name = Frameworks;
80 | sourceTree = "";
81 | };
82 | /* End PBXGroup section */
83 |
84 | /* Begin PBXNativeTarget section */
85 | B822E66922FB455100368AE7 /* IR_Manipulation_Tester */ = {
86 | isa = PBXNativeTarget;
87 | buildConfigurationList = B822E67122FB455100368AE7 /* Build configuration list for PBXNativeTarget "IR_Manipulation_Tester" */;
88 | buildPhases = (
89 | B822E66622FB455100368AE7 /* Sources */,
90 | B822E66722FB455100368AE7 /* Frameworks */,
91 | B822E66822FB455100368AE7 /* CopyFiles */,
92 | );
93 | buildRules = (
94 | );
95 | dependencies = (
96 | );
97 | name = IR_Manipulation_Tester;
98 | productName = IR_Manipulation_Tester;
99 | productReference = B822E66A22FB455100368AE7 /* IR_Manipulation_Tester */;
100 | productType = "com.apple.product-type.tool";
101 | };
102 | /* End PBXNativeTarget section */
103 |
104 | /* Begin PBXProject section */
105 | B822E66222FB455100368AE7 /* Project object */ = {
106 | isa = PBXProject;
107 | attributes = {
108 | LastUpgradeCheck = 0920;
109 | ORGANIZATIONNAME = AHarker;
110 | TargetAttributes = {
111 | B822E66922FB455100368AE7 = {
112 | CreatedOnToolsVersion = 9.2;
113 | ProvisioningStyle = Automatic;
114 | };
115 | };
116 | };
117 | buildConfigurationList = B822E66522FB455100368AE7 /* Build configuration list for PBXProject "IR_Manipulation_Tester" */;
118 | compatibilityVersion = "Xcode 8.0";
119 | developmentRegion = en;
120 | hasScannedForEncodings = 0;
121 | knownRegions = (
122 | en,
123 | );
124 | mainGroup = B822E66122FB455100368AE7;
125 | productRefGroup = B822E66B22FB455100368AE7 /* Products */;
126 | projectDirPath = "";
127 | projectRoot = "";
128 | targets = (
129 | B822E66922FB455100368AE7 /* IR_Manipulation_Tester */,
130 | );
131 | };
132 | /* End PBXProject section */
133 |
134 | /* Begin PBXSourcesBuildPhase section */
135 | B822E66622FB455100368AE7 /* Sources */ = {
136 | isa = PBXSourcesBuildPhase;
137 | buildActionMask = 2147483647;
138 | files = (
139 | B822E67922FC184700368AE7 /* HISSTools_FFT.cpp in Sources */,
140 | B822E66E22FB455100368AE7 /* main.cpp in Sources */,
141 | );
142 | runOnlyForDeploymentPostprocessing = 0;
143 | };
144 | /* End PBXSourcesBuildPhase section */
145 |
146 | /* Begin XCBuildConfiguration section */
147 | B822E66F22FB455100368AE7 /* Debug */ = {
148 | isa = XCBuildConfiguration;
149 | buildSettings = {
150 | ALWAYS_SEARCH_USER_PATHS = NO;
151 | CLANG_ANALYZER_NONNULL = YES;
152 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
153 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
154 | CLANG_CXX_LIBRARY = "libc++";
155 | CLANG_ENABLE_MODULES = YES;
156 | CLANG_ENABLE_OBJC_ARC = YES;
157 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
158 | CLANG_WARN_BOOL_CONVERSION = YES;
159 | CLANG_WARN_COMMA = YES;
160 | CLANG_WARN_CONSTANT_CONVERSION = YES;
161 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
162 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
163 | CLANG_WARN_EMPTY_BODY = YES;
164 | CLANG_WARN_ENUM_CONVERSION = YES;
165 | CLANG_WARN_INFINITE_RECURSION = YES;
166 | CLANG_WARN_INT_CONVERSION = YES;
167 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
168 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
169 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
171 | CLANG_WARN_STRICT_PROTOTYPES = YES;
172 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
174 | CLANG_WARN_UNREACHABLE_CODE = YES;
175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
176 | CLANG_X86_VECTOR_INSTRUCTIONS = default;
177 | CODE_SIGN_IDENTITY = "-";
178 | COPY_PHASE_STRIP = NO;
179 | DEBUG_INFORMATION_FORMAT = dwarf;
180 | ENABLE_STRICT_OBJC_MSGSEND = YES;
181 | ENABLE_TESTABILITY = YES;
182 | GCC_C_LANGUAGE_STANDARD = gnu11;
183 | GCC_DYNAMIC_NO_PIC = NO;
184 | GCC_NO_COMMON_BLOCKS = YES;
185 | GCC_OPTIMIZATION_LEVEL = 0;
186 | GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
187 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
188 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
189 | GCC_WARN_UNDECLARED_SELECTOR = YES;
190 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
191 | GCC_WARN_UNUSED_FUNCTION = YES;
192 | GCC_WARN_UNUSED_VARIABLE = YES;
193 | MACOSX_DEPLOYMENT_TARGET = 10.12;
194 | MTL_ENABLE_DEBUG_INFO = YES;
195 | ONLY_ACTIVE_ARCH = YES;
196 | SDKROOT = macosx;
197 | };
198 | name = Debug;
199 | };
200 | B822E67022FB455100368AE7 /* Release */ = {
201 | isa = XCBuildConfiguration;
202 | buildSettings = {
203 | ALWAYS_SEARCH_USER_PATHS = NO;
204 | CLANG_ANALYZER_NONNULL = YES;
205 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
207 | CLANG_CXX_LIBRARY = "libc++";
208 | CLANG_ENABLE_MODULES = YES;
209 | CLANG_ENABLE_OBJC_ARC = YES;
210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
211 | CLANG_WARN_BOOL_CONVERSION = YES;
212 | CLANG_WARN_COMMA = YES;
213 | CLANG_WARN_CONSTANT_CONVERSION = YES;
214 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
215 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
216 | CLANG_WARN_EMPTY_BODY = YES;
217 | CLANG_WARN_ENUM_CONVERSION = YES;
218 | CLANG_WARN_INFINITE_RECURSION = YES;
219 | CLANG_WARN_INT_CONVERSION = YES;
220 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
221 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
224 | CLANG_WARN_STRICT_PROTOTYPES = YES;
225 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
227 | CLANG_WARN_UNREACHABLE_CODE = YES;
228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
229 | CLANG_X86_VECTOR_INSTRUCTIONS = default;
230 | CODE_SIGN_IDENTITY = "-";
231 | COPY_PHASE_STRIP = NO;
232 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
233 | ENABLE_NS_ASSERTIONS = NO;
234 | ENABLE_STRICT_OBJC_MSGSEND = YES;
235 | GCC_C_LANGUAGE_STANDARD = gnu11;
236 | GCC_NO_COMMON_BLOCKS = YES;
237 | GCC_PREPROCESSOR_DEFINITIONS = "";
238 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
239 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
240 | GCC_WARN_UNDECLARED_SELECTOR = YES;
241 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
242 | GCC_WARN_UNUSED_FUNCTION = YES;
243 | GCC_WARN_UNUSED_VARIABLE = YES;
244 | MACOSX_DEPLOYMENT_TARGET = 10.12;
245 | MTL_ENABLE_DEBUG_INFO = NO;
246 | SDKROOT = macosx;
247 | };
248 | name = Release;
249 | };
250 | B822E67222FB455100368AE7 /* Debug */ = {
251 | isa = XCBuildConfiguration;
252 | buildSettings = {
253 | CODE_SIGN_STYLE = Automatic;
254 | PRODUCT_NAME = "$(TARGET_NAME)";
255 | };
256 | name = Debug;
257 | };
258 | B822E67322FB455100368AE7 /* Release */ = {
259 | isa = XCBuildConfiguration;
260 | buildSettings = {
261 | CODE_SIGN_STYLE = Automatic;
262 | PRODUCT_NAME = "$(TARGET_NAME)";
263 | };
264 | name = Release;
265 | };
266 | /* End XCBuildConfiguration section */
267 |
268 | /* Begin XCConfigurationList section */
269 | B822E66522FB455100368AE7 /* Build configuration list for PBXProject "IR_Manipulation_Tester" */ = {
270 | isa = XCConfigurationList;
271 | buildConfigurations = (
272 | B822E66F22FB455100368AE7 /* Debug */,
273 | B822E67022FB455100368AE7 /* Release */,
274 | );
275 | defaultConfigurationIsVisible = 0;
276 | defaultConfigurationName = Release;
277 | };
278 | B822E67122FB455100368AE7 /* Build configuration list for PBXNativeTarget "IR_Manipulation_Tester" */ = {
279 | isa = XCConfigurationList;
280 | buildConfigurations = (
281 | B822E67222FB455100368AE7 /* Debug */,
282 | B822E67322FB455100368AE7 /* Release */,
283 | );
284 | defaultConfigurationIsVisible = 0;
285 | defaultConfigurationName = Release;
286 | };
287 | /* End XCConfigurationList section */
288 | };
289 | rootObject = B822E66222FB455100368AE7 /* Project object */;
290 | }
291 |
--------------------------------------------------------------------------------
/Statistics.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef STATISTICS_HPP
3 | #define STATISTICS_HPP
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace impl
11 | {
12 | // Helper functors
13 |
14 | struct pow2 { template T operator()(T a) const { return a * a; } };
15 | struct pow3 { template T operator()(T a) const { return a * a * a; } };
16 | struct pow4 { template T operator()(T a) const { return pow2()(pow2()(a)); } };
17 | struct absolute { template T operator()(T a) const { return std::abs(a); } };
18 | struct logarithm { template T operator()(T a) const { return std::log(a); } };
19 |
20 | struct indices { template double operator[](T a) const { return static_cast(a); } };
21 | struct log_indices { template double operator[](T a) const { return a ? std::log2(static_cast(a)) : 0.0; } };
22 |
23 | template
24 | struct modified_data
25 | {
26 | modified_data(T& data) : m_data(data) {}
27 | double operator[](size_t i) const { return Op()(m_data[i]); }
28 | const T m_data;
29 | };
30 |
31 | template
32 | struct modified_diff_data
33 | {
34 | modified_diff_data(T& data, double value) : m_data(data), m_value(value) {}
35 | double operator[](size_t i) const { return Op()(m_data[i] - m_value); }
36 | const T m_data;
37 | double m_value;
38 | };
39 |
40 | template
41 | struct indices_diff_op
42 | {
43 | indices_diff_op(double value) : m_value(value) {}
44 | double operator[](size_t i) const { return Op()(static_cast(i) - m_value); }
45 | double m_value;
46 | };
47 |
48 | template
49 | struct log_indices_diff_op
50 | {
51 | log_indices_diff_op(double value) : m_value(value) {}
52 | double operator[](size_t i) const { return Op()(log_indices()[i] - m_value); }
53 | double m_value;
54 | };
55 |
56 | template
57 | struct fixed_compare
58 | {
59 | fixed_compare(T value) : m_value(value) {}
60 | bool operator()(T a) { return Op()(a, m_value); }
61 | T m_value;
62 | };
63 | }
64 |
65 | // Length
66 |
67 | template
68 | double stat_length(const T input, size_t size)
69 | {
70 | return static_cast(size);
71 | }
72 |
73 | // Min / Max Values
74 |
75 | template
76 | double stat_min(const T input, size_t size)
77 | {
78 | return size ? *(std::min_element(input, input + size)) : std::numeric_limits::infinity();
79 | }
80 |
81 | template