mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 09:18:54 -05:00
DemodAnalyzer: implemented record audio. Part of #1330
This commit is contained in:
parent
93a238503c
commit
2c02a9bcf1
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 92 KiB |
Binary file not shown.
@ -220,6 +220,10 @@ bool DemodAnalyzer::handleMessage(const Message& cmd)
|
||||
m_sampleRate = report.getSampleRate();
|
||||
m_scopeVis.setLiveRate(m_sampleRate);
|
||||
|
||||
if (m_running) {
|
||||
m_worker->applySampleRate(m_sampleRate);
|
||||
}
|
||||
|
||||
DSPSignalNotification *msg = new DSPSignalNotification(0, m_sampleRate);
|
||||
m_spectrumVis.getInputMessageQueue()->push(msg);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "feature/featureuiset.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
@ -206,6 +207,11 @@ void DemodAnalyzerGUI::displaySettings()
|
||||
setTitle(m_settings.m_title);
|
||||
blockApplySettings(true);
|
||||
ui->log2Decim->setCurrentIndex(m_settings.m_log2Decim);
|
||||
ui->record->setChecked(m_settings.m_recordToFile);
|
||||
ui->fileNameText->setText(m_settings.m_fileRecordName);
|
||||
ui->showFileDialog->setEnabled(!m_settings.m_recordToFile);
|
||||
ui->recordSilenceTime->setValue(m_settings.m_recordSilenceTime);
|
||||
ui->recordSilenceText->setText(tr("%1").arg(m_settings.m_recordSilenceTime / 10.0, 0, 'f', 1));
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
@ -327,6 +333,47 @@ void DemodAnalyzerGUI::on_log2Decim_currentIndexChanged(int index)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DemodAnalyzerGUI::on_record_toggled(bool checked)
|
||||
{
|
||||
ui->showFileDialog->setEnabled(!checked);
|
||||
m_settings.m_recordToFile = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DemodAnalyzerGUI::on_showFileDialog_clicked(bool checked)
|
||||
{
|
||||
(void) checked;
|
||||
QFileDialog fileDialog(
|
||||
this,
|
||||
tr("Save record file"),
|
||||
m_settings.m_fileRecordName,
|
||||
tr("WAV Files (*.wav)")
|
||||
);
|
||||
|
||||
fileDialog.setOptions(QFileDialog::DontUseNativeDialog);
|
||||
fileDialog.setFileMode(QFileDialog::AnyFile);
|
||||
QStringList fileNames;
|
||||
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
fileNames = fileDialog.selectedFiles();
|
||||
|
||||
if (fileNames.size() > 0)
|
||||
{
|
||||
m_settings.m_fileRecordName = fileNames.at(0);
|
||||
ui->fileNameText->setText(m_settings.m_fileRecordName);
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DemodAnalyzerGUI::on_recordSilenceTime_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_recordSilenceTime = value;
|
||||
ui->recordSilenceText->setText(tr("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DemodAnalyzerGUI::tick()
|
||||
{
|
||||
m_channelPowerAvg(m_demodAnalyzer->getMagSqAvg());
|
||||
@ -379,4 +426,7 @@ void DemodAnalyzerGUI::makeUIConnections()
|
||||
QObject::connect(ui->channels, qOverload<int>(&QComboBox::currentIndexChanged), this, &DemodAnalyzerGUI::on_channels_currentIndexChanged);
|
||||
QObject::connect(ui->channelApply, &QPushButton::clicked, this, &DemodAnalyzerGUI::on_channelApply_clicked);
|
||||
QObject::connect(ui->log2Decim, qOverload<int>(&QComboBox::currentIndexChanged), this, &DemodAnalyzerGUI::on_log2Decim_currentIndexChanged);
|
||||
QObject::connect(ui->record, &ButtonSwitch::toggled, this, &DemodAnalyzerGUI::on_record_toggled);
|
||||
QObject::connect(ui->showFileDialog, &QPushButton::clicked, this, &DemodAnalyzerGUI::on_showFileDialog_clicked);
|
||||
QObject::connect(ui->recordSilenceTime, &QSlider::valueChanged, this, &DemodAnalyzerGUI::on_recordSilenceTime_valueChanged);
|
||||
}
|
||||
|
@ -93,6 +93,9 @@ private slots:
|
||||
void on_channels_currentIndexChanged(int index);
|
||||
void on_channelApply_clicked();
|
||||
void on_log2Decim_currentIndexChanged(int index);
|
||||
void on_record_toggled(bool checked);
|
||||
void on_showFileDialog_clicked(bool checked);
|
||||
void on_recordSilenceTime_valueChanged(int value);
|
||||
void updateStatus();
|
||||
void tick();
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>739</width>
|
||||
<height>778</height>
|
||||
<height>785</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -37,7 +37,7 @@
|
||||
<x>0</x>
|
||||
<y>10</y>
|
||||
<width>718</width>
|
||||
<height>41</height>
|
||||
<height>70</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
@ -72,6 +72,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="startStop">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>start/stop acquisition</string>
|
||||
</property>
|
||||
@ -195,12 +201,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="sinkSampleRateText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Analyzer (sink) sample rate</string>
|
||||
</property>
|
||||
@ -249,6 +249,119 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="fileNameLayout">
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="record">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start/stop recording</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/record_off.png</normaloff>:/record_off.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="showFileDialog">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/preset-load.png</normaloff>:/preset-load.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fileNameText">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Current recording file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="recordSilenceTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Silence time (s) before recording is stopoed. 0 for continuous recording.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="recordSilenceText">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Silence time (s) before recording is stopoed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>10.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="spectrumContainer" native="true">
|
||||
|
@ -83,6 +83,9 @@ void DemodAnalyzerSettings::resetToDefaults()
|
||||
m_reverseAPIFeatureSetIndex = 0;
|
||||
m_reverseAPIFeatureIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_fileRecordName.clear();
|
||||
m_recordToFile = false;
|
||||
m_recordSilenceTime = 0;
|
||||
}
|
||||
|
||||
QByteArray DemodAnalyzerSettings::serialize() const
|
||||
@ -112,6 +115,9 @@ QByteArray DemodAnalyzerSettings::serialize() const
|
||||
|
||||
s.writeS32(13, m_workspaceIndex);
|
||||
s.writeBlob(14, m_geometryBytes);
|
||||
s.writeString(15, m_fileRecordName);
|
||||
s.writeBool(16, m_recordToFile);
|
||||
s.writeS32(17, m_recordSilenceTime);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -170,6 +176,9 @@ bool DemodAnalyzerSettings::deserialize(const QByteArray& data)
|
||||
|
||||
d.readS32(13, &m_workspaceIndex, 0);
|
||||
d.readBlob(14, &m_geometryBytes);
|
||||
d.readString(15, &m_fileRecordName);
|
||||
d.readBool(16, &m_recordToFile, false);
|
||||
d.readS32(17, &m_recordSilenceTime, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -49,6 +49,9 @@ struct DemodAnalyzerSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIFeatureSetIndex;
|
||||
uint16_t m_reverseAPIFeatureIndex;
|
||||
QString m_fileRecordName;
|
||||
bool m_recordToFile;
|
||||
int m_recordSilenceTime; //!< 100's ms
|
||||
Serializable *m_spectrumGUI;
|
||||
Serializable *m_scopeGUI;
|
||||
Serializable *m_rollupState;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "dsp/scopevis.h"
|
||||
#include "dsp/datafifo.h"
|
||||
#include "dsp/wavfilerecord.h"
|
||||
|
||||
#include "demodanalyzerworker.h"
|
||||
|
||||
@ -28,7 +29,11 @@ MESSAGE_CLASS_DEFINITION(DemodAnalyzerWorker::MsgConnectFifo, Message)
|
||||
DemodAnalyzerWorker::DemodAnalyzerWorker() :
|
||||
m_dataFifo(nullptr),
|
||||
m_msgQueueToFeature(nullptr),
|
||||
m_sampleBufferSize(0)
|
||||
m_sampleBufferSize(0),
|
||||
m_wavFileRecord(nullptr),
|
||||
m_recordSilenceNbSamples(0),
|
||||
m_recordSilenceCount(0),
|
||||
m_nbBytes(0)
|
||||
{
|
||||
qDebug("DemodAnalyzerWorker::DemodAnalyzerWorker");
|
||||
}
|
||||
@ -47,12 +52,15 @@ void DemodAnalyzerWorker::reset()
|
||||
void DemodAnalyzerWorker::startWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_wavFileRecord = new WavFileRecord(m_sinkSampleRate);
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
}
|
||||
|
||||
void DemodAnalyzerWorker::stopWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
delete m_wavFileRecord;
|
||||
m_wavFileRecord = nullptr;
|
||||
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
}
|
||||
|
||||
@ -74,6 +82,13 @@ void DemodAnalyzerWorker::feedPart(
|
||||
nbBytes = 2;
|
||||
}
|
||||
|
||||
if ((nbBytes != m_nbBytes) && m_wavFileRecord)
|
||||
{
|
||||
m_wavFileRecord->stopRecording();
|
||||
m_wavFileRecord->setMono(nbBytes == 2);
|
||||
}
|
||||
|
||||
m_nbBytes = nbBytes;
|
||||
int countSamples = (end - begin) / nbBytes;
|
||||
|
||||
if (countSamples > m_sampleBufferSize)
|
||||
@ -93,6 +108,62 @@ void DemodAnalyzerWorker::feedPart(
|
||||
vbegin.push_back(m_sampleBuffer.begin());
|
||||
m_scopeVis->feed(vbegin, countSamples/(1<<m_settings.m_log2Decim));
|
||||
}
|
||||
|
||||
if (m_settings.m_recordToFile && m_wavFileRecord)
|
||||
{
|
||||
for (int is = 0; is < countSamples/(1<<m_settings.m_log2Decim); is++)
|
||||
{
|
||||
const Sample& sample = m_sampleBuffer[is];
|
||||
|
||||
if ((sample.m_real == 0) && (sample.m_imag == 0))
|
||||
{
|
||||
if (m_recordSilenceNbSamples <= 0)
|
||||
{
|
||||
writeSampleToFile(sample);
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
else if (m_recordSilenceCount < m_recordSilenceNbSamples)
|
||||
{
|
||||
writeSampleToFile(sample);
|
||||
m_recordSilenceCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->startRecording();
|
||||
}
|
||||
writeSampleToFile(sample);
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DemodAnalyzerWorker::writeSampleToFile(const Sample& sample)
|
||||
{
|
||||
if (SDR_RX_SAMP_SZ == 16)
|
||||
{
|
||||
if (m_nbBytes == 2) {
|
||||
m_wavFileRecord->writeMono(sample.m_real);
|
||||
} else {
|
||||
m_wavFileRecord->write(sample.m_real, sample.m_imag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nbBytes == 2) {
|
||||
m_wavFileRecord->writeMono(sample.m_real >> 8);
|
||||
} else {
|
||||
m_wavFileRecord->write(sample.m_real >> 8, sample.m_imag >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DemodAnalyzerWorker::decimate(int countSamples)
|
||||
@ -190,11 +261,95 @@ void DemodAnalyzerWorker::applySettings(const DemodAnalyzerSettings& settings, b
|
||||
<< " m_title: " << settings.m_title
|
||||
<< " m_rgbColor: " << settings.m_rgbColor
|
||||
<< " m_log2Decim: " << settings.m_log2Decim
|
||||
<< " m_fileRecordName: " << settings.m_fileRecordName
|
||||
<< " m_recordToFile: " << settings.m_recordToFile
|
||||
<< " m_recordSilenceTime: " << settings.m_recordSilenceTime
|
||||
<< " force: " << force;
|
||||
|
||||
if ((m_settings.m_fileRecordName != settings.m_fileRecordName) || force)
|
||||
{
|
||||
if (m_wavFileRecord)
|
||||
{
|
||||
QStringList dotBreakout = settings.m_fileRecordName.split(QLatin1Char('.'));
|
||||
|
||||
if (dotBreakout.size() > 1)
|
||||
{
|
||||
QString extension = dotBreakout.last();
|
||||
|
||||
if (extension != "wav") {
|
||||
dotBreakout.last() = "wav";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dotBreakout.append("wav");
|
||||
}
|
||||
|
||||
QString newFileRecordName = dotBreakout.join(QLatin1Char('.'));
|
||||
QString fileBase;
|
||||
FileRecordInterface::guessTypeFromFileName(newFileRecordName, fileBase);
|
||||
qDebug("DemodAnalyzerWorker::applySettings: newFileRecordName: %s fileBase: %s", qPrintable(newFileRecordName), qPrintable(fileBase));
|
||||
m_wavFileRecord->setFileName(fileBase);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_recordToFile != settings.m_recordToFile) || force)
|
||||
{
|
||||
if (m_wavFileRecord)
|
||||
{
|
||||
if (settings.m_recordToFile)
|
||||
{
|
||||
if (!m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->startRecording();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
}
|
||||
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_recordSilenceTime != settings.m_recordSilenceTime)
|
||||
|| (m_settings.m_log2Decim != settings.m_log2Decim) || force)
|
||||
{
|
||||
m_recordSilenceNbSamples = (settings.m_recordSilenceTime * (m_sinkSampleRate / (1<<settings.m_log2Decim))) / 10; // time in 100'ś ms
|
||||
m_recordSilenceCount = 0;
|
||||
|
||||
if (m_wavFileRecord)
|
||||
{
|
||||
if (m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
|
||||
m_wavFileRecord->setSampleRate(m_sinkSampleRate / (1<<settings.m_log2Decim));
|
||||
}
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
void DemodAnalyzerWorker::applySampleRate(int sampleRate)
|
||||
{
|
||||
m_sinkSampleRate = sampleRate;
|
||||
|
||||
m_recordSilenceNbSamples = (m_settings.m_recordSilenceTime * (m_sinkSampleRate / (1<<m_settings.m_log2Decim))) / 10; // time in 100'ś ms
|
||||
m_recordSilenceCount = 0;
|
||||
|
||||
if (m_wavFileRecord)
|
||||
{
|
||||
if (m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
|
||||
m_wavFileRecord->setSampleRate(m_sinkSampleRate / (1<<m_settings.m_log2Decim));
|
||||
}
|
||||
}
|
||||
|
||||
void DemodAnalyzerWorker::handleData()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
@ -37,6 +37,8 @@ class BasebandSampleSink;
|
||||
class ScopeVis;
|
||||
class ChannelAPI;
|
||||
class Feature;
|
||||
class WavFileRecord;
|
||||
|
||||
class DemodAnalyzerWorker : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -91,12 +93,6 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
void setMessageQueueToFeature(MessageQueue *messageQueue) { m_msgQueueToFeature = messageQueue; }
|
||||
|
||||
void feedPart(
|
||||
const QByteArray::const_iterator& begin,
|
||||
const QByteArray::const_iterator& end,
|
||||
DataFifo::DataType dataType
|
||||
);
|
||||
|
||||
void applySampleRate(int sampleRate);
|
||||
void applySettings(const DemodAnalyzerSettings& settings, bool force = false);
|
||||
|
||||
@ -121,10 +117,21 @@ private:
|
||||
int m_sampleBufferSize;
|
||||
MovingAverageUtil<double, double, 480> m_channelPowerAvg;
|
||||
ScopeVis* m_scopeVis;
|
||||
WavFileRecord* m_wavFileRecord;
|
||||
int m_recordSilenceNbSamples;
|
||||
int m_recordSilenceCount;
|
||||
int m_nbBytes;
|
||||
QRecursiveMutex m_mutex;
|
||||
|
||||
void feedPart(
|
||||
const QByteArray::const_iterator& begin,
|
||||
const QByteArray::const_iterator& end,
|
||||
DataFifo::DataType dataType
|
||||
);
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
void decimate(int countSamples);
|
||||
void writeSampleToFile(const Sample& sample);
|
||||
|
||||
inline void processSample(
|
||||
DataFifo::DataType dataType,
|
||||
|
@ -73,6 +73,35 @@ This is the resulting sample rate after possible decimation that is used by the
|
||||
|
||||
Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band.
|
||||
|
||||
<h3>A.8. Record as .wav file</h3>
|
||||
|
||||
Use this button to toggle recording. Start or stop recording
|
||||
|
||||
Format is always 16 bit little-endian and can be mono (1 channel) or stereo (2 channels) depending on data type.
|
||||
|
||||
<h3>A.9. Select recording output file</h3>
|
||||
|
||||
Click on this icon to open a file selection dialog that lets you specify the location and name of the output files.
|
||||
|
||||
Each recording is written in a new file with the starting timestamp before the `.wav` extension in `yyyy-MM-ddTHH_mm_ss_zzz` format. It keeps the first dot limited groups of the filename before the `.wav` extension if there are two such groups or before the two last groups if there are more than two groups. Examples:
|
||||
|
||||
- Given file name: `test.wav` then a recording file will be like: `test.2020-08-05T21_39_07_974.wav`
|
||||
- Given file name: `test.2020-08-05T20_36_15_974.wav` then a recording file will be like (with timestamp updated): `test.2020-08-05T21_41_21_173.wav`
|
||||
- Given file name: `test.first.wav` then a recording file will be like: `test.2020-08-05T22_00_07_974.wav`
|
||||
- Given file name: `record.test.first.eav` then a recording file will be like: `reocrd.test.2020-08-05T21_39_52_974.wav`
|
||||
|
||||
If a filename is given without `.wav` extension then the `.wav` extension is appended automatically before the above algorithm is applied. If a filename is given with an extension different of `.wav` then the extension is replaced by `.wav` automatically before the above algorithm is applied.
|
||||
|
||||
The file path currently being written (or last closed) appears at the right of the button (A.1.10).
|
||||
|
||||
<h3>A.1.10. Recording file path</h3>
|
||||
|
||||
This is the file path currently being written (or last closed).
|
||||
|
||||
<h3>A.1.11 Record silence time</h3>
|
||||
|
||||
This is the time in seconds (between 0.1 and 10.0) of silence (null samples) before recording stops. When non null samples come again this will start a new recording. Set the value to 0 to record continuously.
|
||||
|
||||
<h2>B. Spectrum view</h2>
|
||||
|
||||
This is the same display as with the channel analyzer spectrum view. This is the spectrum of a real signal so it is symmetrical around zero frequency. Details on the spectrum view and controls can be found [here](../../../sdrgui/gui/spectrum.md)
|
||||
|
@ -82,8 +82,9 @@ void WavFileRecord::feed(const SampleVector::const_iterator& begin, const Sample
|
||||
{
|
||||
(void) positiveOnly;
|
||||
|
||||
if(!m_recordOn)
|
||||
if (!m_recordOn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (begin < end) // if there is something to put out
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ public:
|
||||
virtual int getBytesPerSample() override { return 4; };
|
||||
const QString& getCurrentFileName() override { return m_currentFileName; }
|
||||
void setMono(bool mono) { m_nbChannels = mono ? 1 : 2; }
|
||||
void setSampleRate(quint32 sampleRate) { m_sampleRate = sampleRate; }
|
||||
|
||||
void genUniqueFileName(uint deviceUID, int istream = -1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user