diff --git a/.gitignore b/.gitignore index c30f610..a908ec7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode/ build/ -.old/ \ No newline at end of file +.old/ +unfinished/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c52d7bf..30ac9bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE "/") target_compile_options(${PROJECT_NAME} PRIVATE /std:c++20) - if (MSVC) # Lib path target_link_directories(${PROJECT_NAME} PUBLIC "C:/Program Files/PothosSDR/lib/") diff --git a/dsp/block.cpp b/dsp/block.cpp deleted file mode 100644 index 3a86c6c..0000000 --- a/dsp/block.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "block.h" -#include - -namespace dsp { - Block::Block() {} - - Block::~Block() { - // Stop the worker - stop(); - } - - void Block::start() { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Do nothing if the block is already running - if (_running) { return; } - - // Mark as running - _running = true; - - // Start the worker thread - workerThread = std::thread(&Block::worker, this); - } - - void Block::stop() { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Do nothing if the block is not running - if (!_running) { return; } - - // Set the receive stop flag on all input streams - for (const auto& input : inputs) { - input->stopReceiver(); - } - - // Set the send stop flag on all output streams - for (const auto& output : outputs) { - output->stopSender(); - } - - // Wait for the thread to exist - if (workerThread.joinable()) { workerThread.join(); } - - // Clear the receive stop flag on all input streams - for (const auto& input : inputs) { - input->clearRecvStop(); - } - - // Clear the send stop flag on all output streams - for (const auto& output : outputs) { - output->clearSendStop(); - } - - // Mark as not running - _running = false; - } - - bool Block::running() const { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Return run state - return _running; - } - - void Block::registerInput(StopNotifier* input) { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Save to the input list - inputs.push_back(input); - } - - void Block::unregisterInput(StopNotifier* input) { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Find the notifier - auto it = std::find(inputs.begin(), inputs.end(), input); - if (it == inputs.end()) { return; } - - // Remove it from the list - inputs.erase(it); - } - - void Block::registerOutput(StopNotifier* output) { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Save to the output list - outputs.push_back(output); - } - - void Block::unregisterOutput(StopNotifier* output) { - // Acquire worker variables - std::lock_guard lck(workerMtx); - - // Find the notifier - auto it = std::find(outputs.begin(), outputs.end(), output); - if (it == outputs.end()) { return; } - - // Remove it from the list - inputs.erase(it); - } - - void Block::worker() { - // Call the run function repeatedly - while (run()); - } -} \ No newline at end of file diff --git a/dsp/block.h b/dsp/block.h deleted file mode 100644 index 7b8bdd4..0000000 --- a/dsp/block.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include -#include -#include - -namespace dsp { - /** - * Interface to be used by any blocking class (stream, mailbox, etc...) to allow cancelling an operation. - */ - class StopNotifier { - public: - /** - * Notify the sending thread that it should stop. - */ - virtual void stopSender() = 0; - - /** - * Clear the sender stop flag to allow restarting the sender thread. - */ - virtual void clearSendStop() = 0; - - /** - * Notify the receiving thread that it should stop. - */ - virtual void stopReceiver() = 0; - - /** - * Clear the receiver stop flag to allow restarting the sender thread. - */ - virtual void clearRecvStop() = 0; - }; - - /** - * General DSP block class handling the worker thread start/stop operations. - * All input and output stop notifiers (usually streams) of the derived blocks must be registered using the appropriate functions. - * This class is thread-safe. - */ - class Block { - public: - // Default constructor - Block(); - - // Destructor - virtual ~Block(); - - /** - * Start the block's worker thread. - */ - void start(); - - /** - * Stop the block's worker thread. - */ - void stop(); - - /** - * Check wether or not the block's worker thread is running. - */ - bool running() const; - - protected: - /** - * Register an input stop notifier. - * @param input Input stop notifier to register. - */ - void registerInput(StopNotifier* input); - - /** - * Unregister an input stop notifier. - * @param input Input stop notifier to unregister. - */ - void unregisterInput(StopNotifier* input); - - /** - * Register an output stop notifier. - * @param input Output stop notifier to register. - */ - void registerOutput(StopNotifier* output); - - /** - * Unregister an output stop notifier. - * @param input Output stop notifier to unregister. - */ - void unregisterOutput(StopNotifier* output); - - // TODO: Pause/Resume for when inputs/outputs change to avoid needing to restart a thread - - /** - * Run the DSP code. - * @return False if the worker thread should stop. True otherwise. - */ - virtual bool run() = 0; - - private: - /** - * Worker thread function. - */ - void worker(); - - // Worker variables - mutable std::mutex workerMtx; - std::thread workerThread; - std::vector inputs; - std::vector outputs; - bool _running = false; - }; -} \ No newline at end of file diff --git a/dsp/buffer.cpp b/dsp/buffer.cpp index 3b846c0..b28c875 100644 --- a/dsp/buffer.cpp +++ b/dsp/buffer.cpp @@ -25,10 +25,10 @@ namespace dsp { template Buffer::Buffer(const Buffer& b) { // Allocate buffer - realloc(b.count); + realloc(b.capacity); // Copy data over - memcpy(buffer, b.buffer, b.count * sizeof(T)); + memcpy(buffer, b.buffer, b.capacity * sizeof(T)); } template @@ -55,6 +55,9 @@ namespace dsp { // Copy over the data memcpy(buffer, b.buffer, capacity * sizeof(T)); + + // Return self + return *this; } template @@ -69,22 +72,26 @@ namespace dsp { // Neutralize the original b.buffer = NULL; b.capacity = 0; + + // Return self + return *this; } template void Buffer::realloc(size_t size, ReallocBehavior behavior) { // Select the desired behavior + T* newbuf; switch (behavior) { case REALLOC_DISCARD: // Free the current buffer volk_free(buffer); // Allocate a new buffer - buffer = volk_malloc(size * sizeof(T)); + buffer = (T*)volk_malloc(size * sizeof(T), volk_get_alignment()); break; case REALLOC_KEEP: // Allocate a new buffer - T* newbuf = volk_malloc(size * sizeof(T)); + newbuf = (T*)volk_malloc(size * sizeof(T), volk_get_alignment()); // Copy the existing data memcpy(newbuf, buffer, std::min(capacity, size)); @@ -97,13 +104,15 @@ namespace dsp { volk_free(buffer); // Allocate a new buffer - buffer = volk_malloc(size * sizeof(T)); + buffer = (T*)volk_malloc(size * sizeof(T), volk_get_alignment()); // Zero-out the new buffer memset(buffer, 0, size); break; case REALLOC_KEEP_AND_ZERO: - + // TODO + return; + break; } // Update the current capacity diff --git a/dsp/complex.h b/dsp/complex.h index f78c9b3..7287b02 100644 --- a/dsp/complex.h +++ b/dsp/complex.h @@ -55,6 +55,8 @@ namespace dsp { re = b; } + // TODO: Define in-place operators + /** * Real component. */ diff --git a/dsp/constants.h b/dsp/constants.h new file mode 100644 index 0000000..813220e --- /dev/null +++ b/dsp/constants.h @@ -0,0 +1,5 @@ +#pragma once +#include + +#define DSP_PI ((float)3.141592653589793) +#define DSP_SQRT2 ((float)1.414213562373095) \ No newline at end of file diff --git a/dsp/demod/fm.cpp b/dsp/demod/fm.cpp deleted file mode 100644 index e123bcb..0000000 --- a/dsp/demod/fm.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "fm.h" -#define _USE_MATH_DEFINES -#include - -namespace dsp::demod { - FM_s::FM_s() {} - - FM_s::FM_s(float deviation, float samplerate) { - // Save the settings - this->deviation = deviation; - this->samplerate = samplerate; - - // Update the normalization factor - normFact = samplerate / (2.0f * M_PI * deviation); - } - - float FM_s::getDeviation() const { - // Acquire the settings mutex - std::lock_guard lck(settingsMtx); - - // Return the deviation - return deviation; - } - - void FM_s::setDeviation(float deviation) { - // Acquire the settings mutex - std::lock_guard lck(settingsMtx); - - // Update the deviation - this->deviation = deviation; - - // Update the normalization factor - normFact = samplerate / (2.0f * M_PI * deviation); - } - - float FM_s::getSamplerate() const { - // Acquire the settings mutex - std::lock_guard lck(settingsMtx); - - // Return the samplerate - return samplerate; - } - - void FM_s::setSamplerate(float samplerate) { - // Acquire the settings mutex - std::lock_guard lck(settingsMtx); - - // Update the samplerate - this->samplerate = samplerate; - - // Update the normalization factor - normFact = samplerate / (2.0f * M_PI * deviation); - } - - void FM_s::reset() { - // Acquire the settings mutex - std::lock_guard lck(settingsMtx); - - // Set the current phase to zero - phase = 0.0f; - } - - int FM_s::process(const Complex* in, float* out, int count) { - for (int i = 0; i < count; i++) { - // Get the current phase - float cphase = in[i].phase(); - - // Compute the difference with the last phase - // TODO - //out[i] = math::normalizePhase(cphase - phase) * normFact; - - // Save the current phase for the next iteration - phase = cphase; - } - return count; - } - - FM::FM() {} - - FM::FM(float deviation, float samplerate) : - FM_s(deviation, samplerate), - ProcessorAsync(this) - {} - - FM::FM(Stream* in, float deviation, float samplerate) : - FM_s(deviation, samplerate), - ProcessorAsync(this, in) - {} - - FM::FM(Stream* in, Stream* out, float deviation, float samplerate) : - FM_s(deviation, samplerate), - ProcessorAsync(this, in, out) - {} -} \ No newline at end of file diff --git a/dsp/demod/fm.h b/dsp/demod/fm.h deleted file mode 100644 index 9870afd..0000000 --- a/dsp/demod/fm.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once -#include "../processor.h" -#include "../complex.h" - -namespace dsp::demod { - /** - * FM demodulator (Synchronous). - * This class is thread-safe except for `process()`. - */ - class FM_s : public ProcessorSync { - public: - // Default constructor - FM_s(); - - /** - * Create an FM demodulator. - * @param deviation Deviation of the FM signal in Hz. - * @param samplerate Samplerate of the signal in Hz. - */ - FM_s(float deviation, float samplerate); - - /** - * Get the deviation. - * @return Deviation of the FM signal in Hz. - */ - float getDeviation() const; - - /** - * Set the deviation. - * @param deviation Deviation of the FM signal in Hz. - */ - void setDeviation(float deviation); - - /** - * Get the samplerate. - * @return Samplerate of the signal in Hz. - */ - float getSamplerate() const; - - /** - * Set the samplerate. - * @param deviation Samplerate of the signal in Hz. - */ - void setSamplerate(float samplerate); - - /** - * Reset the state of the demodulator. - */ - void reset(); - - /** - * Demodulate a FM-modulated signal. A lock must be acquired using `getLock()` prior to invoking if settings could be set from another thread. - * @param in Modulated signal buffer. - * @param out Demodulated signal buffer. - * @param count Number of samples in the input buffer. - * @return Number of samples in the output buffer. Will always be equal to the number of samples in the input buffer. - */ - int process(const Complex* in, float* out, int count); - - private: - float deviation = 0.0f; - float samplerate = 0.0f; - float normFact = 1.0f; - float phase = 0.0f; - }; - - /** - * FM demodulator. - * This class is thread-safe. - */ - class FM : public FM_s, public ProcessorAsync { - public: - // Default constructor - FM(); - - /** - * Create an FM demodulator. - * @param deviation Deviation of the FM signal in Hz. - * @param samplerate Samplerate of the signal in Hz. - */ - FM(float deviation, float samplerate); - - /** - * Create an FM demodulator. - * @param in Modulated signal stream. - * @param deviation Deviation of the FM signal in Hz. - * @param samplerate Samplerate of the signal in Hz. - */ - FM(Stream* in, float deviation, float samplerate); - - /** - * Create an FM demodulator. - * @param in Modulated signal stream. - * @param out Demodulated signal stream. - * @param deviation Deviation of the FM signal in Hz. - * @param samplerate Samplerate of the signal in Hz. - */ - FM(Stream* in, Stream* out, float deviation, float samplerate); - }; -} \ No newline at end of file diff --git a/dsp/filter/fir.cpp b/dsp/filter/fir.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/dsp/filter/fir.h b/dsp/filter/fir.h deleted file mode 100644 index 8c0435b..0000000 --- a/dsp/filter/fir.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include "../processor.h" -#include "../taps.h" - -namespace dsp::filter { - /** - * Finite Inpulse Response filter (Synchronous). - * This class is thread-safe except for `process()`. - */ - template - class FIR_s : public ProcessorSync { - public: - /** - * Create a FIR filter. - * @param taps Filter taps. - */ - FIR_s(const Taps& taps); - - /** - * Get the filter taps. - * @return Filter taps. - */ - Taps getTaps(); - - /** - * Set the filter taps. - * @param taps Filter taps. - */ - void setTaps(const Taps& taps); - - /** - * Reset the state of the filter. - */ - void reset(); - - /** - * Filter samples. - * @param in Input sample buffer. - * @param out Filtered sample buffer. - * @param count Number of samples in the input buffer. - * @return Number of samples in the output buffer. Will always be equal to the number of samples in the input buffer. - */ - int process(const SAMP_T* in, SAMP_T* out, int count); - - private: - Taps taps; - }; - - /** - * Finite Inpulse Response filter. - * This class is thread-safe except for `process()`. - */ - template - class FIR : public FIR_s, public ProcessorAsync { - public: - /** - * Create a FIR filter. - * @param taps Filter taps. - */ - FIR(const Taps& taps); - - /** - * Create a FIR filter. - * @param in Input samples. - * @param taps Filter taps. - */ - FIR(Stream* in, const Taps& taps); - - /** - * Create a FIR filter. - * @param in Input samples. - * @param in Filtered samples. - * @param taps Filter taps. - */ - FIR(Stream* in, Stream* out, const Taps& taps); - }; -} \ No newline at end of file diff --git a/dsp/processor.h b/dsp/processor.h deleted file mode 100644 index bef6de0..0000000 --- a/dsp/processor.h +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once -#include -#include "block.h" -#include "stream.h" - -namespace dsp { - // TODO: Deal with the fact that always locking will be slow in hier blocks... - - /** - * Class representing a DSP kernel taking one input and one output. - * Dervied classes must be thread-safe by locking the provided `settingsMtx` mutex in any function changing settings. - */ - template - class ProcessorKernel { - public: - // Destructor - virtual ~ProcessorKernel() {} - - // TODO: Copy/Move Constructor/Operator - - /** - * Acquire a lock to the settings of the kernel. Mandatory if settings are changed in a different thread than the processing function. - * @return Lock to the settings of the block. - */ - inline std::lock_guard getLock() const { - return std::lock_guard(settingsMtx); - } - - /** - * Process samples. This function is NOT thread-safe. - * @param in Input buffer. - * @param out Output buffer. - * @param count Number of samples in the input buffer. - * @return Number of samples in the output buffer. - */ - virtual int process(const IN* in, OUT* out, int count) = 0; - - protected: - /** - * Mutex to be used for kernel settings. - */ - mutable std::recursive_mutex settingsMtx; - }; - - template - class ProcessorBlock : public Block { - public: - // Default constructor - ProcessorBlock() { - // TODO: Maybe something to do to prevent bad shit if started? - } - - /** - * TODO - */ - ProcessorBlock(ProcessorSync* proc) { - // Save the pointer to the processor - this->proc = proc; - - // Set the streams - setInput(NULL); - setOutput(NULL); - } - - /** - * TODO - */ - ProcessorBlock(ProcessorSync* proc, Stream* in) { - // Save the pointer to the processor - this->proc = proc; - - // Set the streams - setInput(in); - setOutput(NULL); - } - - /** - * TODO - */ - ProcessorBlock(ProcessorSync* proc, Stream* in, Stream* out) { - // Save the pointer to the processor - this->proc = proc; - - // Set the streams - setInput(in); - setOutput(out); - } - - // Destructor - virtual ~ProcessorBlock() {} - - /** - * Set the input stream. - * @param in Input stream. - */ - void setInput(Stream* in) { - // TODO: Lock - - // If the current input if it already was registered - unregisterInput(_in); - - // TODO: Manage allocating and freeing streams - - // Update the input - _in = in; - - // Register the new input - registerInput(_in); - } - - /** - * Set the output stream. - * @param in Output stream. - */ - void setOutput(Stream* out) { - // TODO: Lock - - // If the current output if it already was registered - unregisterOutput(_out); - - // TODO: Manage allocating and freeing streams - - // Update the output - _out = out; - - // Register the new output - registerOutput(_out); - } - - Stream* in() const { - // TODO: Lock - return _in; - } - - Stream* out() const { - // TODO: Lock - return _out; - } - - private: - bool run() { - // Read samples - auto bufSet = _in->recv(); - if (!bufSet.samples) { return true; } - - // Process samples - { - auto lck = proc->getLock(); - proc->process(NULL/*TODO*/, NULL/*TODO*/, 0/*TODO*/); - } - - // TODO: Write samples - - // TODO - return false; - } - - ProcessorKernel* proc; - Stream* _in = NULL; - Stream* _out = NULL; - bool ownInput = false; - bool ownOutput = false; - }; -} \ No newline at end of file diff --git a/dsp/stream.h b/dsp/stream.h index a7bfd95..22a8e60 100644 --- a/dsp/stream.h +++ b/dsp/stream.h @@ -1,7 +1,33 @@ #pragma once #include #include -#include "block.h" +//#include "block.h" + + /** + * Interface to be used by any blocking class (stream, mailbox, etc...) to allow cancelling an operation. + */ + class StopNotifier { + public: + /** + * Notify the sending thread that it should stop. + */ + virtual void stopSender() = 0; + + /** + * Clear the sender stop flag to allow restarting the sender thread. + */ + virtual void clearSendStop() = 0; + + /** + * Notify the receiving thread that it should stop. + */ + virtual void stopReceiver() = 0; + + /** + * Clear the receiver stop flag to allow restarting the sender thread. + */ + virtual void clearRecvStop() = 0; + }; namespace dsp { /** diff --git a/dsp/taps.cpp b/dsp/taps.cpp index c2c7c46..8f3918c 100644 --- a/dsp/taps.cpp +++ b/dsp/taps.cpp @@ -8,7 +8,6 @@ namespace dsp { template Taps::Taps(const T* taps, size_t count) : Buffer(taps, count) {} - template class Buffer; - template class Buffer; - template class Buffer; + template class Taps; + template class Taps; } \ No newline at end of file diff --git a/dsp/window.cpp b/dsp/window.cpp index 2237763..fc0c153 100644 --- a/dsp/window.cpp +++ b/dsp/window.cpp @@ -1,16 +1,68 @@ #include "window.h" +#include "complex.h" +#include namespace dsp { + Window::Window() { + // Define the window with the default error + define(); + } + + Window::Window(const Window& b) { + // Copy the definition + def = b.def; + } + + Window::Window(Window&& b) { + // Move the definition + def = std::move(b.def); + } + Window::~Window() {} - void Window::generate(float* data, size_t len) const { - for (size_t i = 0; i < len; i++) { + Window& Window::operator=(const Window& b) { + // Copy the definition + def = b.def; + } + Window& Window::operator=(Window&& b) { + // Move the definition + def = std::move(b.def); + } + + void Window::generate(float* data, size_t len) const { + // Compute the linear map ratio + float ratio = 1.0f / ((float)(len + 1)); + + // Iterate over all taps + for (size_t i = 0; i < len; i++) { + // Evaluate the window at the adimensional parameter + data[i] = def(((float)(i + 1)) * ratio); } } template void Window::apply(T* data, size_t len) const { - // TODO + // Compute the linear map ratio + float ratio = 1.0f / ((float)(len + 1)); + + // Iterate over all taps + for (size_t i = 0; i < len; i++) { + // Evaluate the window at the adimensional parameter + data[i] *= def(((float)(i + 1)) * ratio); + } + } + template void Window::apply(float* data, size_t len) const; + //template void Window::apply(Complex* data, size_t len) const; + + void Window::define() { + // Ensure an error is thrown if the undefined window is used + def = Window::undefined; + } + + float Window::undefined(float x) { + // Called when a window function was not defined + throw std::runtime_error("Undefined window"); + return 0; } } \ No newline at end of file diff --git a/dsp/window.h b/dsp/window.h index 564cfa9..66ec178 100644 --- a/dsp/window.h +++ b/dsp/window.h @@ -1,20 +1,37 @@ #pragma once #include - -// TODO: Make something better, this sucks to use - +#include namespace dsp { + /** + * Window function. + * This class is NOT thread-safe. + */ class Window { public: + // Default constructor + Window(); + + // Copy constructor + Window(const Window& b); + + // Move constructor + Window(Window&& b); + // Virtual destructor virtual ~Window(); + // Copy assignement operator + Window& operator=(const Window& b); + + // Move assignement operator + Window& operator=(Window&& b); + /** * Compute the value of the window function. * @param x Point at which to compute the window at. Must be bounded between 0 and 1. * @return Value of the window bounded between 0 and 1. */ - virtual float operator()(float x) const = 0; + inline float operator()(float x) { return def(x); } /** * Generate a window of a given length. @@ -30,5 +47,21 @@ namespace dsp { */ template void apply(T* data, size_t len) const; + + protected: + /** + * Define the window function by setting the `def` member. + * MUST be overriden by all window functions. + */ + virtual void define(); + + /** + * The window function itself. + * This member MUST be initialized by all window functions. + */ + std::function def; + + private: + static float undefined(float x); }; } \ No newline at end of file diff --git a/dsp/window/all.h b/dsp/window/all.h new file mode 100644 index 0000000..4827e0c --- /dev/null +++ b/dsp/window/all.h @@ -0,0 +1,5 @@ +#pragma once +#include "hann.h" +#include "rectangular.h" +#include "triangular.h" +#include "welch.h" \ No newline at end of file diff --git a/dsp/window/hann.cpp b/dsp/window/hann.cpp new file mode 100644 index 0000000..dfc8b3c --- /dev/null +++ b/dsp/window/hann.cpp @@ -0,0 +1,15 @@ +#include "hann.h" +#include "../constants.h" + +namespace dsp::window { + Hann::Hann() { + define(); + } + + void Hann::define() { + def = [](float x) { + float y = sinf(DSP_PI*x); + return y*y; + }; + } +} \ No newline at end of file diff --git a/dsp/window/hann.h b/dsp/window/hann.h new file mode 100644 index 0000000..9a4b375 --- /dev/null +++ b/dsp/window/hann.h @@ -0,0 +1,12 @@ +#pragma once +#include "../window.h" + +namespace dsp::window { + class Hann : public Window { + public: + Hann(); + + private: + void define(); + }; +} \ No newline at end of file diff --git a/dsp/window/rectangular.cpp b/dsp/window/rectangular.cpp new file mode 100644 index 0000000..0fe0b49 --- /dev/null +++ b/dsp/window/rectangular.cpp @@ -0,0 +1,11 @@ +#include "rectangular.h" + +namespace dsp::window { + Rectangular::Rectangular() { + define(); + } + + void Rectangular::define() { + def = [](float x) { return 1.0f; }; + } +} \ No newline at end of file diff --git a/dsp/window/rectangular.h b/dsp/window/rectangular.h index ba71766..ff8c210 100644 --- a/dsp/window/rectangular.h +++ b/dsp/window/rectangular.h @@ -4,11 +4,9 @@ namespace dsp::window { class Rectangular : public Window { public: - /** - * Compute the value of the window function. - * @param x Point at which to compute the window at. Must be bounded between 0 and 1. - * @return Value of the window bounded between 0 and 1. - */ - inline float operator()(float x) const { return 1.0f; } + Rectangular(); + + private: + void define(); }; } \ No newline at end of file diff --git a/dsp/window/triangular.cpp b/dsp/window/triangular.cpp new file mode 100644 index 0000000..95983e2 --- /dev/null +++ b/dsp/window/triangular.cpp @@ -0,0 +1,12 @@ +#include "triangular.h" +#include + +namespace dsp::window { + Triangular::Triangular() { + define(); + } + + void Triangular::define() { + def = [](float x) { return 1.0f - fabsf(2.0f*x - 1.0f); }; + } +} \ No newline at end of file diff --git a/dsp/window/triangular.h b/dsp/window/triangular.h new file mode 100644 index 0000000..8e54bfd --- /dev/null +++ b/dsp/window/triangular.h @@ -0,0 +1,12 @@ +#pragma once +#include "../window.h" + +namespace dsp::window { + class Triangular : public Window { + public: + Triangular(); + + private: + void define(); + }; +} \ No newline at end of file diff --git a/dsp/window/welch.cpp b/dsp/window/welch.cpp new file mode 100644 index 0000000..16a95e3 --- /dev/null +++ b/dsp/window/welch.cpp @@ -0,0 +1,14 @@ +#include "welch.h" + +namespace dsp::window { + Welch::Welch() { + define(); + } + + void Welch::define() { + def = [](float x) { + float y = 2.0f*x - 1.0f; + return 1.0f - y*y; + }; + } +} \ No newline at end of file diff --git a/dsp/window/welch.h b/dsp/window/welch.h new file mode 100644 index 0000000..3098577 --- /dev/null +++ b/dsp/window/welch.h @@ -0,0 +1,12 @@ +#pragma once +#include "../window.h" + +namespace dsp::window { + class Welch : public Window { + public: + Welch(); + + private: + void define(); + }; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 9a63aba..8a2be71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,18 +1,26 @@ #include -#include "dsp/buffer.h" -#include "dsp/taps.h" -#include "dsp/complex.h" -#include +#include "dsp/window.h" +#include "dsp/window/all.h" -void testFunc(const float* buf, size_t len) { - -}; +void testFunc(dsp::Window win) { + printf("win(0.0) = %f\n", win(0.0)); + printf("win(0.5) = %f\n", win(0.5)); + printf("win(1.0) = %f\n", win(1.0)); +} int main() { - float* test; - dsp::Taps taps; + try { + testFunc(dsp::window::Hann()); - testFunc(((const dsp::Taps&)taps).data(), taps.size()); + dsp::Window win = dsp::window::Triangular(); + dsp::Window win2 = dsp::window::Hann(); - return 0; + win = dsp::window::Hann(); + + return 0; + } + catch (const std::exception& e) { + fprintf(stderr, "ERROR: %s\n", e.what()); + return -1; + } } \ No newline at end of file