From 67ee05c7ef7e3195c9c58ef9c83fc82d6de030e9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 11 Nov 2022 23:25:04 +0100 Subject: [PATCH] Audio output device recording: implemented mono recording option --- sdrbase/audio/audiooutputdevice.cpp | 35 ++++++++++++++++++++++++++--- sdrbase/audio/audiooutputdevice.h | 1 + sdrbase/dsp/wavfilerecord.cpp | 24 +++++++++++++++----- sdrbase/dsp/wavfilerecord.h | 3 +++ 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/sdrbase/audio/audiooutputdevice.cpp b/sdrbase/audio/audiooutputdevice.cpp index 006059743..4c445e6eb 100644 --- a/sdrbase/audio/audiooutputdevice.cpp +++ b/sdrbase/audio/audiooutputdevice.cpp @@ -218,6 +218,15 @@ void AudioOutputDevice::setUdpChannelFormat(UDPChannelCodec udpChannelCodec, boo if (m_audioNetSink) { m_audioNetSink->setParameters((AudioNetSink::Codec) m_udpChannelCodec, stereo, sampleRate); } + + if (m_wavFileRecord) + { + if (m_wavFileRecord->isRecording()) { + m_wavFileRecord->stopRecording(); + } + + m_wavFileRecord->setMono(!stereo); + } } void AudioOutputDevice::setUdpDecimation(uint32_t decimation) @@ -403,12 +412,12 @@ qint64 AudioOutputDevice::readData(char* data, qint64 maxLen) { if (m_recordSilenceNbSamples <= 0) { - m_wavFileRecord->write(sl, sr); + writeSampleToFile(sl, sr); m_recordSilenceCount = 0; } else if (m_recordSilenceCount < m_recordSilenceNbSamples) { - m_wavFileRecord->write(sl, sr); + writeSampleToFile(sl, sr); m_recordSilenceCount++; } else @@ -422,7 +431,7 @@ qint64 AudioOutputDevice::readData(char* data, qint64 maxLen) m_wavFileRecord->startRecording(); } - m_wavFileRecord->write(sl, sr); + writeSampleToFile(sl, sr); m_recordSilenceCount = 0; } } @@ -431,6 +440,26 @@ qint64 AudioOutputDevice::readData(char* data, qint64 maxLen) return samplesPerBuffer * 4; } +void AudioOutputDevice::writeSampleToFile(qint16 lSample, qint16 rSample) +{ + switch (m_udpChannelMode) + { + case UDPChannelStereo: + m_wavFileRecord->write(lSample, rSample); + break; + case UDPChannelMixed: + m_wavFileRecord->writeMono((lSample+rSample)/2); + break; + case UDPChannelRight: + m_wavFileRecord->writeMono(rSample); + break; + case UDPChannelLeft: + default: + m_wavFileRecord->writeMono(lSample); + break; + } +} + qint64 AudioOutputDevice::writeData(const char* data, qint64 len) { Q_UNUSED(data); diff --git a/sdrbase/audio/audiooutputdevice.h b/sdrbase/audio/audiooutputdevice.h index f0eb86787..411a00e2b 100644 --- a/sdrbase/audio/audiooutputdevice.h +++ b/sdrbase/audio/audiooutputdevice.h @@ -102,6 +102,7 @@ private: //virtual bool open(OpenMode mode); virtual qint64 readData(char* data, qint64 maxLen); virtual qint64 writeData(const char* data, qint64 len); + void writeSampleToFile(qint16 lSample, qint16 rSample); friend class AudioOutputPipe; }; diff --git a/sdrbase/dsp/wavfilerecord.cpp b/sdrbase/dsp/wavfilerecord.cpp index 23940792a..62236e16a 100644 --- a/sdrbase/dsp/wavfilerecord.cpp +++ b/sdrbase/dsp/wavfilerecord.cpp @@ -37,7 +37,8 @@ WavFileRecord::WavFileRecord(quint32 sampleRate, quint64 centerFrequency) : m_recordOn(false), m_recordStart(false), m_byteCount(0), - m_msShift(0) + m_msShift(0), + m_nbChannels(2) { setObjectName("WavFileRecord"); } @@ -49,7 +50,8 @@ WavFileRecord::WavFileRecord(const QString& fileBase) : m_centerFrequency(0), m_recordOn(false), m_recordStart(false), - m_byteCount(0) + m_byteCount(0), + m_nbChannels(2) { setObjectName("WavFileRecord"); } @@ -124,6 +126,18 @@ void WavFileRecord::write(qint16 lSample, qint16 rSample) m_byteCount += 4; } +void WavFileRecord::writeMono(qint16 sample) +{ + if (m_recordStart) + { + writeHeader(); + m_recordStart = false; + } + + m_sampleFile.write(reinterpret_cast(&sample), 2); + m_byteCount += 2; +} + void WavFileRecord::start() { } @@ -229,11 +243,11 @@ void WavFileRecord::writeHeader() header.m_fmtHeader.m_id[3] = ' '; header.m_fmtHeader.m_size = 16; header.m_audioFormat = 1; // Linear PCM - header.m_numChannels = 2; // I/Q + header.m_numChannels = m_nbChannels; // 2 for I/Q header.m_sampleRate = m_sampleRate; // We always use 16-bits regardless of SDR_RX_SAMP_SZ - header.m_byteRate = m_sampleRate * 2 * 16 / 8; - header.m_blockAlign = 2 * 16 / 8; + header.m_byteRate = m_sampleRate * m_nbChannels * 16 / 8; + header.m_blockAlign = m_nbChannels * 16 / 8; header.m_bitsPerSample = 16; header.m_auxiHeader.m_id[0] = 'a'; diff --git a/sdrbase/dsp/wavfilerecord.h b/sdrbase/dsp/wavfilerecord.h index ce1890d90..b717706ea 100644 --- a/sdrbase/dsp/wavfilerecord.h +++ b/sdrbase/dsp/wavfilerecord.h @@ -93,11 +93,13 @@ public: void setMsShift(qint64 shift) override { m_msShift = shift; } virtual int getBytesPerSample() override { return 4; }; const QString& getCurrentFileName() override { return m_currentFileName; } + void setMono(bool mono) { m_nbChannels = mono ? 1 : 2; } void genUniqueFileName(uint deviceUID, int istream = -1); virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) override; void write(qint16 lSample, qint16 rSample); //!< write a single sample + void writeMono(qint16 sample); //!< write a single mono sample virtual void start() override; virtual void stop() override; virtual bool handleMessage(const Message& message) override; @@ -124,6 +126,7 @@ private: QString m_currentFileName; quint64 m_byteCount; qint64 m_msShift; + int m_nbChannels; void writeHeader(); };