freedv-gui/src/pipeline/TxRxThread.h

137 lines
4.0 KiB
C++

//=========================================================================
// Name: TxRxThread.h
// Purpose: Implements the main processing thread for audio I/O.
//
// Authors: Mooneer Salem
// License:
//
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. This program is
// distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//
//=========================================================================
#ifndef AUDIO_PIPELINE__TX_RX_THREAD_H
#define AUDIO_PIPELINE__TX_RX_THREAD_H
#include <assert.h>
#include <functional>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include "AudioPipeline.h"
#include "util/IRealtimeHelper.h"
#include "util/Semaphore.h"
#include "util/sanitizers.h"
// Forward declarations
class LinkStep;
//#define ENABLE_PROCESSING_STATS
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// class txRxThread - tx/rx processing thread
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class TxRxThread
{
public:
TxRxThread(bool tx, int inputSampleRate, int outputSampleRate, std::shared_ptr<LinkStep> micAudioLink, std::shared_ptr<IRealtimeHelper> helper)
: m_tx(tx)
, m_run(1)
, pipeline_(nullptr)
, inputSampleRate_(inputSampleRate)
, outputSampleRate_(outputSampleRate)
, equalizedMicAudioLink_(micAudioLink)
, hasEooBeenSent_(false)
, helper_(helper)
, deferReset_(false)
{
assert(inputSampleRate_ > 0);
assert(outputSampleRate_ > 0);
auto numSamples = std::max(inputSampleRate_, outputSampleRate_);
inputSamples_ = std::make_unique<short[]>(numSamples);
assert(inputSamples_ != nullptr);
inputSamplesZeros_ = std::make_unique<short[]>(numSamples);
assert(inputSamplesZeros_ != nullptr);
memset(inputSamplesZeros_.get(), 0, numSamples * sizeof(short));
}
virtual ~TxRxThread()
{
// Free allocated buffer
inputSamples_ = nullptr;
}
void start()
{
thread_ = std::thread(std::bind(&TxRxThread::Entry, this));
}
void stop()
{
m_run = false;
if (thread_.joinable())
{
thread_.join();
}
}
// thread execution starts here
void *Entry() noexcept;
void waitForReady() { readySem_.wait(); }
void signalToStart() { startSem_.signal(); }
private:
bool m_tx;
std::atomic<bool> m_run;
std::unique_ptr<AudioPipeline> pipeline_;
int inputSampleRate_;
int outputSampleRate_;
std::shared_ptr<LinkStep> equalizedMicAudioLink_;
bool hasEooBeenSent_;
std::shared_ptr<IRealtimeHelper> helper_;
std::unique_ptr<short[]> inputSamples_;
std::unique_ptr<short[]> inputSamplesZeros_;
bool deferReset_;
std::thread thread_;
Semaphore readySem_;
Semaphore startSem_;
#if defined(ENABLE_PROCESSING_STATS)
int numTimeSamples_;
double minDuration_;
std::time_t minTime_;
double maxDuration_;
std::time_t maxTime_;
double sumDuration_;
double sumDoubleDuration_;
std::chrono::time_point<std::chrono::high_resolution_clock> timeStart_;
void resetStats_();
void startTimer_();
void endTimer_();
void reportStats_();
#endif // defined(ENABLE_PROCESSING_STATS)
void initializePipeline_();
void txProcessing_(IRealtimeHelper* helper) FREEDV_NONBLOCKING;
void rxProcessing_(IRealtimeHelper* helper) FREEDV_NONBLOCKING;
void clearFifos_() FREEDV_NONBLOCKING;
};
#endif // AUDIO_PIPELINE__TX_RX_THREAD_H