mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-05 22:57:51 -04:00
Demod instance start/stop recording setup
This commit is contained in:
parent
c202d99a2a
commit
f8e51df8cd
@ -8,27 +8,28 @@ AudioSinkFileThread::AudioSinkFileThread() : AudioSinkThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioSinkFileThread::~AudioSinkFileThread() {
|
AudioSinkFileThread::~AudioSinkFileThread() {
|
||||||
if (outputFileHandler != nullptr) {
|
if (audioFileHandler != nullptr) {
|
||||||
outputFileHandler->closeFile();
|
audioFileHandler->closeFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSinkFileThread::sink(AudioThreadInputPtr input) {
|
void AudioSinkFileThread::sink(AudioThreadInputPtr input) {
|
||||||
if (!outputFileHandler) {
|
if (!audioFileHandler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// forward to output file handler
|
// forward to output file handler
|
||||||
outputFileHandler->writeToFile(input);
|
audioFileHandler->writeToFile(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSinkFileThread::inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) {
|
void AudioSinkFileThread::inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) {
|
||||||
// close, set new parameters, adjust file name sequence and re-open?
|
// close, set new parameters, adjust file name sequence and re-open?
|
||||||
if (!outputFileHandler) {
|
if (!audioFileHandler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
audioFileHandler->closeFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSinkFileThread::setOutput(AudioFile * output) {
|
void AudioSinkFileThread::setAudioFileHandler(AudioFile * output) {
|
||||||
outputFileHandler = output;
|
audioFileHandler = output;
|
||||||
outputFileHandler->setOutputFileName(sinkName);
|
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ public:
|
|||||||
void sink(AudioThreadInputPtr input);
|
void sink(AudioThreadInputPtr input);
|
||||||
void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps);
|
void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps);
|
||||||
|
|
||||||
void setOutput(AudioFile *output);
|
void setAudioFileHandler(AudioFile *output);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AudioFile *outputFileHandler = nullptr;
|
AudioFile *audioFileHandler = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ void AudioSinkThread::run() {
|
|||||||
inputRef.inputRate = inp->inputRate;
|
inputRef.inputRate = inp->inputRate;
|
||||||
inputRef.sampleRate = inp->sampleRate;
|
inputRef.sampleRate = inp->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sink(inp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,12 +51,3 @@ void AudioSinkThread::terminate() {
|
|||||||
IOThread::terminate();
|
IOThread::terminate();
|
||||||
inputQueuePtr->flush();
|
inputQueuePtr->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSinkThread::setSinkName(std::string sinkName_in) {
|
|
||||||
sinkName = sinkName_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AudioSinkThread::getSinkName() {
|
|
||||||
return sinkName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -18,12 +18,8 @@ public:
|
|||||||
virtual void sink(AudioThreadInputPtr input) = 0;
|
virtual void sink(AudioThreadInputPtr input) = 0;
|
||||||
virtual void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) = 0;
|
virtual void inputChanged(AudioThreadInput oldProps, AudioThreadInputPtr newProps) = 0;
|
||||||
|
|
||||||
virtual void setSinkName(std::string sinkName_in);
|
|
||||||
virtual std::string getSinkName();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::recursive_mutex m_mutex;
|
std::recursive_mutex m_mutex;
|
||||||
AudioThreadInputQueuePtr inputQueuePtr;
|
AudioThreadInputQueuePtr inputQueuePtr;
|
||||||
std::string sinkName;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0+
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include "DemodulatorInstance.h"
|
#include "DemodulatorInstance.h"
|
||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
#include "DemodulatorThread.h"
|
#include "DemodulatorThread.h"
|
||||||
#include "DemodulatorPreThread.h"
|
#include "DemodulatorPreThread.h"
|
||||||
|
#include "AudioSinkFileThread.h"
|
||||||
|
#include "AudioFileWAV.h"
|
||||||
|
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
#include "RigThread.h"
|
#include "RigThread.h"
|
||||||
@ -47,6 +50,7 @@ DemodulatorInstance::DemodulatorInstance() {
|
|||||||
active.store(false);
|
active.store(false);
|
||||||
squelch.store(false);
|
squelch.store(false);
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
|
recording.store(false);
|
||||||
deltaLock.store(false);
|
deltaLock.store(false);
|
||||||
deltaLockOfs.store(0);
|
deltaLockOfs.store(0);
|
||||||
currentOutputDevice.store(-1);
|
currentOutputDevice.store(-1);
|
||||||
@ -542,6 +546,21 @@ void DemodulatorInstance::setMuted(bool muted) {
|
|||||||
wxGetApp().getDemodMgr().setLastMuted(muted);
|
wxGetApp().getDemodMgr().setLastMuted(muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DemodulatorInstance::isRecording()
|
||||||
|
{
|
||||||
|
return recording.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::setRecording(bool recording_in)
|
||||||
|
{
|
||||||
|
if (!recording.load() && recording_in) {
|
||||||
|
startRecording();
|
||||||
|
}
|
||||||
|
else if (recording.load() && !recording_in) {
|
||||||
|
stopRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DemodVisualCue *DemodulatorInstance::getVisualCue() {
|
DemodVisualCue *DemodulatorInstance::getVisualCue() {
|
||||||
return &visualCue;
|
return &visualCue;
|
||||||
}
|
}
|
||||||
@ -599,6 +618,50 @@ ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DemodulatorInstance::startRecording() {
|
||||||
|
if (recording.load()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSinkFileThread *newSinkThread = new AudioSinkFileThread();
|
||||||
|
AudioFileWAV *afHandler = new AudioFileWAV();
|
||||||
|
|
||||||
|
std::stringstream fileName;
|
||||||
|
fileName << getLabel() << "_" << std::time(nullptr);
|
||||||
|
|
||||||
|
afHandler->setOutputFileName(fileName.str());
|
||||||
|
newSinkThread->setAudioFileHandler(afHandler);
|
||||||
|
|
||||||
|
audioSinkThread = newSinkThread;
|
||||||
|
t_AudioSink = new std::thread(&AudioSinkThread::threadMain, audioSinkThread);
|
||||||
|
|
||||||
|
demodulatorThread->setOutputQueue("AudioSink", audioSinkThread->getInputQueue("input"));
|
||||||
|
|
||||||
|
recording.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DemodulatorInstance::stopRecording() {
|
||||||
|
if (!recording.load()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
demodulatorThread->setOutputQueue("AudioSink", nullptr);
|
||||||
|
audioSinkThread->terminate();
|
||||||
|
|
||||||
|
t_AudioSink->join();
|
||||||
|
|
||||||
|
delete t_AudioSink;
|
||||||
|
delete audioSinkThread;
|
||||||
|
|
||||||
|
t_AudioSink = nullptr;
|
||||||
|
audioSinkThread = nullptr;
|
||||||
|
|
||||||
|
recording.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_DIGITAL_LAB
|
#if ENABLE_DIGITAL_LAB
|
||||||
ModemDigitalOutput *DemodulatorInstance::getOutput() {
|
ModemDigitalOutput *DemodulatorInstance::getOutput() {
|
||||||
if (activeOutput == nullptr) {
|
if (activeOutput == nullptr) {
|
||||||
|
@ -111,6 +111,9 @@ public:
|
|||||||
bool isMuted();
|
bool isMuted();
|
||||||
void setMuted(bool muted);
|
void setMuted(bool muted);
|
||||||
|
|
||||||
|
bool isRecording();
|
||||||
|
void setRecording(bool recording);
|
||||||
|
|
||||||
DemodVisualCue *getVisualCue();
|
DemodVisualCue *getVisualCue();
|
||||||
|
|
||||||
DemodulatorThreadInputQueuePtr getIQInputDataPipe();
|
DemodulatorThreadInputQueuePtr getIQInputDataPipe();
|
||||||
@ -132,6 +135,10 @@ public:
|
|||||||
void closeOutput();
|
void closeOutput();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startRecording();
|
||||||
|
void stopRecording();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DemodulatorThreadInputQueuePtr pipeIQInputData;
|
DemodulatorThreadInputQueuePtr pipeIQInputData;
|
||||||
DemodulatorThreadPostInputQueuePtr pipeIQDemodData;
|
DemodulatorThreadPostInputQueuePtr pipeIQDemodData;
|
||||||
@ -155,6 +162,8 @@ private:
|
|||||||
std::atomic_bool squelch;
|
std::atomic_bool squelch;
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
std::atomic_bool deltaLock;
|
std::atomic_bool deltaLock;
|
||||||
|
std::atomic_bool recording;
|
||||||
|
|
||||||
std::atomic_int deltaLockOfs;
|
std::atomic_int deltaLockOfs;
|
||||||
|
|
||||||
std::atomic_int currentOutputDevice;
|
std::atomic_int currentOutputDevice;
|
||||||
|
@ -43,6 +43,12 @@ void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBasePtr thread
|
|||||||
|
|
||||||
audioVisOutputQueue = std::static_pointer_cast<DemodulatorThreadOutputQueue>(threadQueue);
|
audioVisOutputQueue = std::static_pointer_cast<DemodulatorThreadOutputQueue>(threadQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name == "AudioSinkOutput") {
|
||||||
|
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
|
||||||
|
|
||||||
|
audioSinkOutputQueue = std::static_pointer_cast<AudioThreadInputQueue>(threadQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double DemodulatorThread::abMagnitude(float inphase, float quadrature) {
|
double DemodulatorThread::abMagnitude(float inphase, float quadrature) {
|
||||||
@ -310,6 +316,13 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capture audioSinkOutputQueue state in a local
|
||||||
|
DemodulatorThreadOutputQueuePtr localAudioSinkOutputQueue = nullptr;
|
||||||
|
{
|
||||||
|
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
|
||||||
|
localAudioSinkOutputQueue = audioSinkOutputQueue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ati != nullptr) {
|
if (ati != nullptr) {
|
||||||
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) {
|
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) {
|
||||||
//non-blocking push needed for audio out
|
//non-blocking push needed for audio out
|
||||||
@ -318,6 +331,13 @@ void DemodulatorThread::run() {
|
|||||||
std::cout << "DemodulatorThread::run() cannot push ati into audioOutputQueue, is full !" << std::endl;
|
std::cout << "DemodulatorThread::run() cannot push ati into audioOutputQueue, is full !" << std::endl;
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (localAudioSinkOutputQueue != nullptr) {
|
||||||
|
if (!audioSinkOutputQueue->try_push(ati)) {
|
||||||
|
std::cout << "DemodulatorThread::run() cannot push ati into audioSinkOutputQueue, is full !" << std::endl;
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ protected:
|
|||||||
DemodulatorThreadOutputQueuePtr audioVisOutputQueue = nullptr;
|
DemodulatorThreadOutputQueuePtr audioVisOutputQueue = nullptr;
|
||||||
DemodulatorThreadControlCommandQueuePtr threadQueueControl = nullptr;
|
DemodulatorThreadControlCommandQueuePtr threadQueueControl = nullptr;
|
||||||
|
|
||||||
|
DemodulatorThreadOutputQueuePtr audioSinkOutputQueue = nullptr;
|
||||||
|
|
||||||
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
|
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
|
||||||
std::mutex m_mutexAudioVisOutputQueue;
|
std::mutex m_mutexAudioVisOutputQueue;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user