From 45ac1fbe1c48b90d369820fdde72f52d6eb17ae1 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Mon, 4 Apr 2022 19:22:11 +0100 Subject: [PATCH] Remove ringbuffer as no longer needed --- audiohandler.cpp | 43 ++-- audiohandler.h | 3 - ring/LICENSE | 21 -- ring/README.md | 10 - ring/ring.cpp | 290 --------------------------- ring/ring.h | 440 ----------------------------------------- wfserver.pro | 2 - wfview.pro | 2 - wfview.vcxproj | 385 +++++++++++++++++++++++++++--------- wfview.vcxproj.filters | 58 +++++- 10 files changed, 366 insertions(+), 888 deletions(-) delete mode 100644 ring/LICENSE delete mode 100644 ring/README.md delete mode 100644 ring/ring.cpp delete mode 100644 ring/ring.h diff --git a/audiohandler.cpp b/audiohandler.cpp index d926e6d..db4a68b 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -22,10 +22,6 @@ audioHandler::~audioHandler() stop(); } - if (ringBuf != Q_NULLPTR) { - delete ringBuf; - } - if (audioInput != Q_NULLPTR) { audioInput = Q_NULLPTR; delete audioInput; @@ -99,12 +95,15 @@ bool audioHandler::init(audioSetup setupIn) this->setVolume(setup.localAFgain); } - format.setSampleSize(16); +/* format.setSampleSize(16); format.setChannelCount(2); format.setSampleRate(INTERNAL_SAMPLE_RATE); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); + format.setSampleType(QAudioFormat::SignedInt); */ + format = setup.port.preferredFormat(); + qDebug(logAudio()) << "Preferred Format: SampleSize" << format.sampleSize() << "Channel Count" << format.channelCount() << + "Sample Rate" << format.sampleRate() << "Codec" << format.codec() << "Sample Type" << format.sampleType(); if (setup.port.isNull()) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "No audio device was found. You probably need to install libqt5multimedia-plugins."; @@ -139,7 +138,6 @@ bool audioHandler::init(audioSetup setupIn) else { audioOutput = new QAudioOutput(setup.port, format, this); - audioOutput->setBufferSize(getAudioSize(setup.latency, format)); isInitialized = true; } @@ -191,6 +189,8 @@ void audioHandler::start() connect(audioInput, &QAudioOutput::destroyed, audioDevice, &QIODevice::deleteLater, Qt::UniqueConnection); } else { + // Buffer size must be set before audio is started. + audioOutput->setBufferSize(getAudioSize(setup.latency, format)); audioDevice = audioOutput->start(); connect(audioOutput, &QAudioOutput::destroyed, audioDevice, &QIODevice::deleteLater, Qt::UniqueConnection); } @@ -294,23 +294,26 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (!livePacket.data.isEmpty()) { Eigen::VectorXf samplesF; - if (setup.format.sampleSize() == 16) + if (setup.format.sampleType() == QAudioFormat::SignedInt && setup.format.sampleSize() == 16) { VectorXint16 samplesI = Eigen::Map(reinterpret_cast(livePacket.data.data()), livePacket.data.size() / int(sizeof(qint16))); samplesF = samplesI.cast() / float(std::numeric_limits::max()); } - else + else if (setup.format.sampleType() == QAudioFormat::UnSignedInt && setup.format.sampleSize() == 8) { VectorXuint8 samplesI = Eigen::Map(reinterpret_cast(livePacket.data.data()), livePacket.data.size() / int(sizeof(quint8))); samplesF = samplesI.cast() / float(std::numeric_limits::max());; } + /* samplesF is now an Eigen Vector of the current samples in float format */ + // Set the max amplitude found in the vector + // Should it be before or after volume is applied? amplitude = samplesF.array().abs().maxCoeff(); // Set the volume samplesF *= volume; - // Convert mono to stereo + // Convert mono to stereo if required if (setup.format.channelCount() == 1) { Eigen::VectorXf samplesTemp(samplesF.size() * 2); Eigen::Map >(samplesTemp.data(), samplesF.size()) = samplesF; @@ -319,16 +322,31 @@ void audioHandler::incomingAudio(audioPacket inPacket) } - if (format.sampleType() == QAudioFormat::SignedInt) + if (format.sampleType() == QAudioFormat::UnSignedInt && format.sampleSize() == 8) + { + Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits::max()); + VectorXuint8 samplesI = samplesITemp.cast(); + livePacket.data = QByteArray(reinterpret_cast(samplesI.data()), int(samplesI.size()) * int(sizeof(quint8))); + } + if (format.sampleType() == QAudioFormat::SignedInt && format.sampleSize() == 16) { Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits::max()); VectorXint16 samplesI = samplesITemp.cast(); livePacket.data = QByteArray(reinterpret_cast(samplesI.data()), int(samplesI.size()) * int(sizeof(qint16))); } - else + else if (format.sampleType() == QAudioFormat::SignedInt && format.sampleSize() == 32) + { + Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits::max()); + VectorXint32 samplesI = samplesITemp.cast(); + livePacket.data = QByteArray(reinterpret_cast(samplesI.data()), int(samplesI.size()) * int(sizeof(qint32))); + } + else if (format.sampleType() == QAudioFormat::Float) { livePacket.data = QByteArray(reinterpret_cast(samplesF.data()), int(samplesF.size()) * int(sizeof(float))); } + else { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Unsupported Sample Type:" << format.sampleType(); + } if (resampleRatio != 1.0) { @@ -378,7 +396,6 @@ void audioHandler::changeLatency(const quint16 newSize) if (!setup.isinput) { stop(); - audioOutput->setBufferSize(getAudioSize(setup.latency, format)); start(); } qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Configured latency: " << setup.latency << "Buffer Duration:" << getAudioDuration(audioOutput->bufferSize(),format) <<"ms"; diff --git a/audiohandler.h b/audiohandler.h index 5647f92..8532d69 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -36,7 +36,6 @@ typedef signed short MY_TYPE; #include #include "resampler/speex_resampler.h" -#include "ring/ring.h" #ifdef Q_OS_WIN #include "opus.h" @@ -149,8 +148,6 @@ private: double resampleRatio; - wilt::Ring *ringBuf=Q_NULLPTR; - volatile bool ready = false; audioPacket tempBuf; quint16 currentLatency; diff --git a/ring/LICENSE b/ring/LICENSE deleted file mode 100644 index b9a4d39..0000000 --- a/ring/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Trevor Wilson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/ring/README.md b/ring/README.md deleted file mode 100644 index 2cdbbe9..0000000 --- a/ring/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Ring Library - -## Overview - -This library provides source for a multi-producer multi-consumer lock-free ring buffer. It provides a very simple interface for writing and reading from the buffer. The source includes a `Ring_` class, that provides the raw implementation and C-like facilities, as well as a templated `Ring` class for typed reads and writes. - - -## Contact - -If you have any questions, concerns, or recommendations please feel free to e-mail me at kmdreko@gmail.com. If you notice a bug or defect, create an issue to report it. diff --git a/ring/ring.cpp b/ring/ring.cpp deleted file mode 100644 index d50555d..0000000 --- a/ring/ring.cpp +++ /dev/null @@ -1,290 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// FILE: ring.cpp -// DATE: 2016-02-25 -// AUTH: Trevor Wilson -// DESC: Implements a lock-free, multi-consumer, multi-producer ring buffer -// class - -//////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2016 Trevor Wilson -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions : -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "ring.h" -using namespace wilt; - -#include -// - std::memcpy - -Ring_::Ring_() - : beg_(nullptr) - , end_(nullptr) -{ - std::atomic_init(&used_, static_cast(0)); - std::atomic_init(&free_, static_cast(0)); - std::atomic_init(&rbuf_, static_cast(0)); - std::atomic_init(&rptr_, static_cast(0)); - std::atomic_init(&wptr_, static_cast(0)); - std::atomic_init(&wbuf_, static_cast(0)); -} - -Ring_::Ring_(std::size_t size) - : beg_(new char[size]) - , end_(beg_ + size) -{ - std::atomic_init(&used_, static_cast(0)); - std::atomic_init(&free_, static_cast(size)); - std::atomic_init(&rbuf_, beg_); - std::atomic_init(&rptr_, beg_); - std::atomic_init(&wptr_, beg_); - std::atomic_init(&wbuf_, beg_); -} - -Ring_::Ring_(Ring_&& ring) - : beg_(ring.beg_) - , end_(ring.end_) -{ - std::atomic_init(&used_, ring.used_.load()); - std::atomic_init(&free_, ring.free_.load()); - std::atomic_init(&rbuf_, ring.rbuf_.load()); - std::atomic_init(&rptr_, ring.rptr_.load()); - std::atomic_init(&wptr_, ring.wptr_.load()); - std::atomic_init(&wbuf_, ring.wbuf_.load()); - - ring.beg_ = nullptr; - ring.end_ = nullptr; - - ring.used_.store(0); - ring.free_.store(0); - ring.rbuf_.store(nullptr); - ring.rptr_.store(nullptr); - ring.wptr_.store(nullptr); - ring.wbuf_.store(nullptr); -} - -Ring_& Ring_::operator= (Ring_&& ring) -{ - delete[] beg_; - - beg_ = ring.beg_; - end_ = ring.end_; - - used_.store(ring.used_.load()); - free_.store(ring.free_.load()); - rbuf_.store(ring.rbuf_.load()); - rptr_.store(ring.rptr_.load()); - wptr_.store(ring.wptr_.load()); - wbuf_.store(ring.wbuf_.load()); - - ring.beg_ = nullptr; - ring.end_ = nullptr; - - ring.used_.store(0); - ring.free_.store(0); - ring.rbuf_.store(nullptr); - ring.rptr_.store(nullptr); - ring.wptr_.store(nullptr); - ring.wbuf_.store(nullptr); - - return *this; -} - -Ring_::~Ring_() -{ - delete[] beg_; -} - -std::size_t Ring_::size() const -{ - // The 'used' space can be negative in an over-reserved case, but it can be - // clamped to 0 for simplicity. - - auto s = used_.load(); - return s < 0 ? 0 : static_cast(s); -} - -std::size_t Ring_::capacity() const -{ - return static_cast(end_ - beg_); -} - -void Ring_::read(void* data, std::size_t length) noexcept -{ - auto block = acquire_read_block_(length); - - copy_read_block_(block, (char*)data, length); - release_read_block_(block, length); -} - -void Ring_::write(const void* data, std::size_t length) noexcept -{ - auto block = acquire_write_block_(length); - - copy_write_block_(block, (const char*)data, length); - release_write_block_(block, length); -} - -bool Ring_::try_read(void* data, std::size_t length) noexcept -{ - auto block = try_acquire_read_block_(length); - if (block == nullptr) - return false; - - copy_read_block_(block, (char*)data, length); - release_read_block_(block, length); - - return true; -} - -bool Ring_::try_write(const void* data, std::size_t length) noexcept -{ - auto block = try_acquire_write_block_(length); - if (block == nullptr) - return false; - - copy_write_block_(block, (const char*)data, length); - release_write_block_(block, length); - - return true; -} - -char* Ring_::normalize_(char* ptr) -{ - return ptr < end_ ? ptr : ptr - capacity(); -} - -char* Ring_::acquire_read_block_(std::size_t length) -{ - auto size = static_cast(length); - while (true) // loop while conflict - { - auto old_rptr = rptr_.load(std::memory_order_consume); // read rptr - while (used_.load(std::memory_order_consume) < size) // check for data - ; // spin until success - - auto new_rptr = normalize_(old_rptr + size); // get block end - used_.fetch_sub(size); // reserve - if (rptr_.compare_exchange_strong(old_rptr, new_rptr)) // try commit - return old_rptr; // committed - - used_.fetch_add(size, std::memory_order_relaxed); // un-reserve - } -} - -char* Ring_::try_acquire_read_block_(std::size_t length) -{ - auto size = static_cast(length); - while (true) // loop while conflict - { - auto old_rptr = rptr_.load(std::memory_order_consume); // read rptr - if (used_.load(std::memory_order_consume) < size) // check for data - return nullptr; // return failure - - auto new_rptr = normalize_(old_rptr + size); // get block end - used_.fetch_sub(size); // reserve - if (rptr_.compare_exchange_strong(old_rptr, new_rptr)) // try commit - return old_rptr; // committed - - used_.fetch_add(size, std::memory_order_relaxed); // un-reserve - } -} - -void Ring_::copy_read_block_(const char* block, char* data, std::size_t length) -{ - if (block + length < end_) - { - std::memcpy(data, block, length); - } - else - { - auto first = end_ - block; - std::memcpy(data, block, first); - std::memcpy(data + first, beg_, length - first); - } -} - -void Ring_::release_read_block_(char* old_rptr, std::size_t length) -{ - auto new_rptr = normalize_(old_rptr + length); // get block end - while (rbuf_.load() != old_rptr) // check for earlier reads - ; // spin until reads complete - - rbuf_.store(new_rptr); // finish commit - free_.fetch_add(length, std::memory_order_relaxed); // add to free space -} - -char* Ring_::acquire_write_block_(std::size_t length) -{ - auto size = static_cast(length); - while (true) // loop while conflict - { - auto old_wbuf = wbuf_.load(std::memory_order_consume); // read wbuf - while (free_.load(std::memory_order_consume) < size) // check for space - ; // spin until success - - auto new_wbuf = normalize_(old_wbuf + size); // get block end - free_.fetch_sub(size); // reserve - if (wbuf_.compare_exchange_strong(old_wbuf, new_wbuf)) // try commit - return old_wbuf; // committed - - free_.fetch_add(size, std::memory_order_relaxed); // un-reserve - } -} - -char* Ring_::try_acquire_write_block_(std::size_t length) -{ - auto size = static_cast(length); - while (true) // loop while conflict - { - auto old_wbuf = wbuf_.load(std::memory_order_consume); // read wbuf - if (free_.load(std::memory_order_consume) < size) // check for space - return nullptr; // return failure - - auto new_wbuf = normalize_(old_wbuf + size); // get block end - free_.fetch_sub(size); // reserve - if (wbuf_.compare_exchange_strong(old_wbuf, new_wbuf)) // try commit - return old_wbuf; // committed - - free_.fetch_add(size, std::memory_order_relaxed); // un-reserve - } -} - -void Ring_::copy_write_block_(char* block, const char* data, std::size_t length) -{ - if (block + length < end_) - { - std::memcpy(block, data, length); - } - else - { - auto first = end_ - block; - std::memcpy(block, data, first); - std::memcpy(beg_, data + first, length - first); - } -} - -void Ring_::release_write_block_(char* old_wbuf, std::size_t length) -{ - auto new_wbuf = normalize_(old_wbuf + length); // get block end - while (wptr_.load() != old_wbuf) // wait for earlier writes - ; // spin until writes complete - - wptr_.store(new_wbuf); // finish commit - used_.fetch_add(length, std::memory_order_relaxed); // add to used space -} diff --git a/ring/ring.h b/ring/ring.h deleted file mode 100644 index 0f5be22..0000000 --- a/ring/ring.h +++ /dev/null @@ -1,440 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// FILE: ring.h -// DATE: 2016-02-25 -// AUTH: Trevor Wilson -// DESC: Defines a lock-free, multi-consumer, multi-producer ring buffer class - -//////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2016 Trevor Wilson -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions : -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef WILT_RING_H -#define WILT_RING_H - -#include -// - std::atomic -#include -// - std::size_t -// - std::ptrdiff_t -#include -// - ::new(ptr) -#include -// - std::is_nothrow_copy_constructible -// - std::is_nothrow_move_constructible -// - std::is_nothrow_move_assignable -// - std::is_nothrow_destructible -#include -// - std::move - -namespace wilt -{ - ////////////////////////////////////////////////////////////////////////////// - // This structure aims to access elements in a ring buffer from multiple - // concurrent readers and writers in a lock-free manner. - // - // The class works by allocating the array and storing two pointers (for the - // beginning and end of the allocated space). Two atomic pointers are used to - // track the beginning and end of the currently used storage space. To - // facilitate concurrent reads and writes, there's a read buffer pointer before - // the read pointer for data currently being read, and a corresponding write - // buffer pointer beyond the write pointer for data currently being written. - // These buffer pointers cannot overlap. Just using these pointers suffer from - // some minute inefficiencies and a few ABA problems. Therefore, atomic - // integers are used to store the currently used and currently free sizes. - // - // It allows multiple readers and multiple writers by implementing a reserve- - // commit system. A thread wanting to read will check the used size to see if - // there's enough data. If there is, it subtracts from the used size to - // 'reserve' the read. It then does a compare-exchange to 'commit' by - // increasing the read pointer. If that fails, then it backs out ('un- - // reserves') by adding back to the used size and tries again. If it - // succeeds, then it proceeds to read the data. In order to complete, the - // reader must update the read buffer pointer to where it just finished - // reading from. However, because other readers that started before may not be - // done yet, the reader must wait until the read buffer pointer points to - // where the read started. Only, then is the read buffer pointer updated, and - // the free size increased. So while this implementation is lock-free, it is - // not wait-free. This same principle works the same when writing (amended - // for the appropriate pointers). - // - // If two readers try to read at the same time and there is only enough data - // for one of them. The used size MAY be negative because they both 'reserve' - // the data. This is an over-reserved state. But the compare-exchange will - // only allow one reader to 'commit' to the read and the other will 'un- - // reserve' the read. - // - // |beg |rptr used=5 |wbuf - unused - // |----|----|++++|====|====|====|====|====|++++|----| + modifying - // free=3 |rbuf |wptr |end = used - // - // The diagram above shows a buffer of size 10 storing 5 bytes with a reader - // reading one byte and one writer reading one byte. - // - // Out of the box, the class works by reading and writing raw bytes from POD - // data types and arrays. A wrapper could allow for a nicer interface for - // pushing and popping elements. As it stands, this structure cannot be easily - // modified to store types of variable size. - - class Ring_ - { - private: - //////////////////////////////////////////////////////////////////////////// - // TYPE DEFINITIONS - //////////////////////////////////////////////////////////////////////////// - - typedef char* data_ptr; - typedef std::atomic size_type; - typedef std::atomic atom_ptr; - - private: - //////////////////////////////////////////////////////////////////////////// - // PRIVATE MEMBERS - //////////////////////////////////////////////////////////////////////////// - // Beginning and end pointers don't need to be atomic because they don't - // change. used_ and free_ can be negative in certain cases (and that's ok). - - data_ptr beg_; // pointer to beginning of data block - data_ptr end_; // pointer to end of data block - - alignas(64) - size_type used_; // size of unreserved used space - - alignas(64) - size_type free_; // size of unreserved free space - - alignas(64) - atom_ptr rbuf_; // pointer to beginning of data being read - atom_ptr rptr_; // pointer to beginning of data - - alignas(64) - atom_ptr wptr_; // pointer to end of data - atom_ptr wbuf_; // pointer to end of data being written - - public: - //////////////////////////////////////////////////////////////////////////// - // CONSTRUCTORS AND DESTRUCTORS - //////////////////////////////////////////////////////////////////////////// - - // Constructs a ring without a buffer (capacity() == 0) - Ring_(); - - // Constructs a ring with a buffer with a size - Ring_(std::size_t size); - - // Moves the buffer between rings, assumes no concurrent operations - Ring_(Ring_&& ring); - - // Moves the buffer between rings, assumes no concurrent operations on - // either ring. Deallocates the buffer - Ring_& operator= (Ring_&& ring); - - // No copying - Ring_(const Ring_&) = delete; - Ring_& operator= (const Ring_&) = delete; - - // Deallocates the buffer - ~Ring_(); - - public: - //////////////////////////////////////////////////////////////////////////// - // QUERY FUNCTIONS - //////////////////////////////////////////////////////////////////////////// - // Functions only report on the state of the ring - - // Returns the current amount of non-reserved used space (amount of written - // data that a read hasn't yet reserved). Over-reserved scenarios mean this - // number is not the ultimate source of truth with concurrent operations, - // but its the closest safe approximation. This, of course, doesn't report - // writes that have not completed. - std::size_t size() const; - - // Maximum amount of data that can be held - std::size_t capacity() const; - - public: - //////////////////////////////////////////////////////////////////////////// - // ACCESSORS AND MODIFIERS - //////////////////////////////////////////////////////////////////////////// - // All operations assume object has not been moved. Blocking operations run - // until operation is completed. Non-blocking operations fail if there is - // not enough space - - void read(void* data, std::size_t length) noexcept; - void write(const void* data, std::size_t length) noexcept; - bool try_read(void* data, std::size_t length) noexcept; - bool try_write(const void* data, std::size_t length) noexcept; - - protected: - //////////////////////////////////////////////////////////////////////////// - // PROTECTED FUNCTIONS - //////////////////////////////////////////////////////////////////////////// - // Helper functions - - // Wraps a pointer within the array. Assumes 'beg_ <= ptr < end_+capacity()' - char* normalize_(char*); - - char* acquire_read_block_(std::size_t length); - char* try_acquire_read_block_(std::size_t length); - void copy_read_block_(const char* block, char* data, std::size_t length); - void release_read_block_(char* block, std::size_t length); - - char* acquire_write_block_(std::size_t length); - char* try_acquire_write_block_(std::size_t length); - void copy_write_block_(char* block, const char* data, std::size_t length); - void release_write_block_(char* block, std::size_t length); - - char* begin_alloc_() { return beg_; } - const char* begin_alloc_() const { return beg_; } - char* end_alloc_() { return end_; } - const char* end_alloc_() const { return end_; } - char* begin_data_() { return rptr_; } - const char* begin_data_() const { return rptr_; } - char* end_data_() { return wptr_; } - const char* end_data_() const { return wptr_; } - - }; // class Ring_ - - template - class Ring : protected Ring_ - { - public: - //////////////////////////////////////////////////////////////////////////// - // CONSTRUCTORS AND DESTRUCTORS - //////////////////////////////////////////////////////////////////////////// - - // Constructs a ring without a buffer (capacity() == 0) - Ring(); - - // Constructs a ring with a buffer with a size - Ring(std::size_t size); - - // Moves the buffer between rings, assumes no concurrent operations - Ring(Ring&& ring); - - // Moves the buffer between rings, assumes no concurrent operations on - // either ring. Deallocates the buffer - Ring& operator= (Ring&& ring); - - // No copying - Ring(const Ring_&) = delete; - Ring& operator= (const Ring_&) = delete; - - // Deallocates the buffer, destructs stored data. - ~Ring(); - - public: - //////////////////////////////////////////////////////////////////////////// - // QUERY FUNCTIONS - //////////////////////////////////////////////////////////////////////////// - // Functions only report on the state of the ring - - // Returns the current amount of non-reserved used space (amount of written - // data that a read hasn't yet reserved). Over-reserved scenarios mean this - // number is not the ultimate source of truth with concurrent operations, - // but its the closest safe approximation. This, of course, doesn't report - // writes that have not completed. - std::size_t size() const; - - // Maximum amount of data that can be held - std::size_t capacity() const; - - public: - //////////////////////////////////////////////////////////////////////////// - // ACCESSORS AND MODIFIERS - //////////////////////////////////////////////////////////////////////////// - // All operations assume object has not been moved. Blocking operations run - // until operation is completed. Non-blocking operations fail if there is - // not enough space - - void read(T& data) noexcept; // blocking read - void write(const T& data) noexcept; // blocking write - void write(T&& data) noexcept; // blocking write - bool try_read(T& data) noexcept; // non-blocking read - bool try_write(const T& data) noexcept; // non-blocking write - bool try_write(T&& data) noexcept; // non-blocking write - - private: - //////////////////////////////////////////////////////////////////////////// - // PRIVATE HELPER FUNCTIONS - //////////////////////////////////////////////////////////////////////////// - - void destruct_(); - - }; // class Ring - - template - Ring::Ring() - : Ring_() - { } - - template - Ring::Ring(std::size_t size) - : Ring_(size * sizeof(T)) - { } - - template - Ring::Ring(Ring&& ring) - : Ring_(std::move(ring)) - { } - - template - Ring& Ring::operator= (Ring&& ring) - { - destruct_(); - - Ring_::operator= (ring); - - return *this; - } - - template - Ring::~Ring() - { - destruct_(); - } - - template - void Ring::destruct_() - { - if (size() == 0) - return; - - auto itr = begin_data_(); - auto end = end_data_(); - do - { - auto t = reinterpret_cast(itr); - t->~T(); - - itr = normalize_(itr + sizeof(T)); - } while (itr != end); - } - - template - std::size_t Ring::size() const - { - return Ring_::size() / sizeof(T); - } - - template - std::size_t Ring::capacity() const - { - return Ring_::capacity() / sizeof(T); - } - - template - void Ring::read(T& data) noexcept - { - static_assert(std::is_nothrow_move_assignable::value, "T move assignment must not throw"); - static_assert(std::is_nothrow_destructible::value, "T destructor must not throw"); - - auto block = acquire_read_block_(sizeof(T)); - - // critical section - auto t = reinterpret_cast(block); - data = std::move(*t); - t->~T(); - - release_read_block_(block, sizeof(T)); - } - - template - void Ring::write(const T& data) noexcept - { - static_assert(std::is_nothrow_copy_constructible::value, "T copy constructor must not throw"); - - auto block = acquire_write_block_(sizeof(T)); - - // critical section - new(block) T(data); - - release_write_block_(block, sizeof(T)); - } - - template - void Ring::write(T&& data) noexcept - { - static_assert(std::is_nothrow_move_constructible::value, "T move constructor must not throw"); - - auto block = acquire_write_block_(sizeof(T)); - - // critical section - new(block) T(std::move(data)); - - release_write_block_(block, sizeof(T)); - } - - template - bool Ring::try_read(T& data) noexcept - { - static_assert(std::is_nothrow_move_assignable::value, "T move assignment must not throw"); - static_assert(std::is_nothrow_destructible::value, "T destructor must not throw"); - - auto block = try_acquire_read_block_(sizeof(T)); - if (block == nullptr) - return false; - - // critical section - auto t = reinterpret_cast(block); - data = std::move(*t); - t->~T(); - - release_read_block_(block, sizeof(T)); - - return true; - } - - template - bool Ring::try_write(const T& data) noexcept - { - static_assert(std::is_nothrow_copy_constructible::value, "T copy constructor must not throw"); - - auto block = try_acquire_write_block_(sizeof(T)); - if (block == nullptr) - return false; - - // critical section - new(block) T(data); - - release_write_block_(block, sizeof(T)); - - return true; - } - - template - bool Ring::try_write(T&& data) noexcept - { - static_assert(std::is_nothrow_move_constructible::value, "T move constructor must not throw"); - - auto block = try_acquire_write_block_(sizeof(T)); - if (block == nullptr) - return false; - - // critical section - new(block) T(std::move(data)); - - release_write_block_(block, sizeof(T)); - - return true; - } - -} // namespace wilt - -#endif // !WILT_RING_H \ No newline at end of file diff --git a/wfserver.pro b/wfserver.pro index 0d7de1f..fe8be7e 100644 --- a/wfserver.pro +++ b/wfserver.pro @@ -147,7 +147,6 @@ SOURCES += main.cpp\ resampler/resample.c \ rigctld.cpp \ tcpserver.cpp \ - ring/ring.cpp HEADERS += servermain.h \ commhandler.h \ @@ -166,6 +165,5 @@ HEADERS += servermain.h \ repeaterattributes.h \ rigctld.h \ ulaw.h \ - ring/ring.h \ tcpserver.h \ audiotaper.h diff --git a/wfview.pro b/wfview.pro index 28f75e9..3d94b70 100644 --- a/wfview.pro +++ b/wfview.pro @@ -174,7 +174,6 @@ SOURCES += main.cpp\ resampler/resample.c \ repeatersetup.cpp \ rigctld.cpp \ - ring/ring.cpp \ transceiveradjustments.cpp \ selectradio.cpp \ tcpserver.cpp \ @@ -202,7 +201,6 @@ HEADERS += wfmain.h \ repeaterattributes.h \ rigctld.h \ ulaw.h \ - ring/ring.h \ transceiveradjustments.h \ audiotaper.h \ selectradio.h \ diff --git a/wfview.vcxproj b/wfview.vcxproj index 2954a6f..a495694 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -16,8 +16,7 @@ QtVS_v304 10.0.19041.0 10.0.19041.0 - $(MSBuildProjectDirectory)\QtMsBuild - + $(MSBuildProjectDirectory)\QtMsBuild v142 @@ -37,10 +36,7 @@ debug\ wfview - - - - + @@ -48,34 +44,8 @@ - - - - - - wfview-debug\ - wfview-debug\ - wfview - true - - - release\ - release\ - wfview - true - false - - - msvc2019 - core;network;gui;multimedia;widgets;serialport;printsupport - - - msvc2019 - core;network;gui;multimedia;widgets;serialport;printsupport - - - - + debug\debug\wfviewtruerelease\release\wfviewtruefalsemsvc2019core;network;gui;multimedia;widgets;serialport;printsupportmsvc2019core;network;gui;multimedia;widgets;serialport;printsupport + .;..\qcustomplot;..\opus\include;..\eigen;..\r8brain-free-src;resampler;release;/include;%(AdditionalIncludeDirectories) @@ -87,16 +57,14 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="8ec62fe";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="ac70ba5";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false - - + MultiThreadedDLL true true Level3 - true - + true ..\opus\win32\VS2015\Win32\Release\opus.lib;shell32.lib;%(AdditionalDependencies) ..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) @@ -117,28 +85,9 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"8ec62fe\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"ac70ba5\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(Configuration) - moc_%(Filename).cpp - - - default - Rcc'ing %(Identity)... - $(Configuration) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(ProjectDir) - ui_%(Filename).h - - + msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h .;..\qcustomplot;..\opus\include;..\eigen;..\r8brain-free-src;resampler;debug;/include;%(AdditionalIncludeDirectories) @@ -150,14 +99,13 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="8ec62fe";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="ac70ba5";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true true Level3 - true - + true ..\opus\win32\VS2015\Win32\Debug\opus.lib;shell32.lib;%(AdditionalDependencies) ..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) @@ -176,28 +124,9 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"8ec62fe\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFVIEW;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"ac70ba5\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(Configuration) - moc_%(Filename).cpp - - - default - Rcc'ing %(Identity)... - $(Configuration) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(ProjectDir) - ui_%(Filename).h - - + msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h @@ -215,7 +144,6 @@ - @@ -226,55 +154,207 @@ + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document true @@ -291,21 +371,121 @@ release\moc_predefs.h;%(Outputs) true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -339,16 +519,30 @@ - resources - resources - + + + + + + + + + + resourcesresources - style - style - + + + + + + + + + + stylestyle @@ -362,9 +556,6 @@ - - - - + \ No newline at end of file diff --git a/wfview.vcxproj.filters b/wfview.vcxproj.filters index d3be9c0..b7c023b 100644 --- a/wfview.vcxproj.filters +++ b/wfview.vcxproj.filters @@ -95,9 +95,6 @@ Source Files - - Source Files - Source Files @@ -127,9 +124,6 @@ Header Files - - Header Files - Header Files @@ -181,9 +175,6 @@ Header Files - - Header Files - Header Files @@ -213,12 +204,59 @@ + + + + + + + + + + Generated Files Generated Files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -375,6 +413,6 @@ - + \ No newline at end of file