mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-22 08:04:49 -05:00
Audio output device recording: implementation (1)
This commit is contained in:
parent
e89331f58f
commit
4a383e439b
@ -641,6 +641,9 @@ void AudioDeviceManager::setOutputDeviceInfo(int outputDeviceIndex, const Output
|
||||
audioOutput->setUdpChannelMode(deviceInfo.udpChannelMode);
|
||||
audioOutput->setUdpChannelFormat(deviceInfo.udpChannelCodec, deviceInfo.udpChannelMode == AudioOutputDevice::UDPChannelStereo, deviceInfo.sampleRate);
|
||||
audioOutput->setUdpDecimation(deviceInfo.udpDecimationFactor);
|
||||
audioOutput->setFileRecordName(deviceInfo.fileRecordName);
|
||||
audioOutput->setRecordToFile(deviceInfo.recordToFile);
|
||||
audioOutput->setRecordSilenceTime(deviceInfo.recordSilenceTime);
|
||||
|
||||
qDebug("AudioDeviceManager::setOutputDeviceInfo: index: %d device: %s updated",
|
||||
outputDeviceIndex, qPrintable(deviceName));
|
||||
|
@ -23,16 +23,22 @@
|
||||
#include "audiooutputdevice.h"
|
||||
#include "audiofifo.h"
|
||||
#include "audionetsink.h"
|
||||
#include "dsp/wavfilerecord.h"
|
||||
|
||||
AudioOutputDevice::AudioOutputDevice() :
|
||||
m_audioOutput(0),
|
||||
m_audioNetSink(0),
|
||||
m_copyAudioToUdp(false),
|
||||
m_audioOutput(nullptr),
|
||||
m_audioNetSink(nullptr),
|
||||
m_wavFileRecord(nullptr),
|
||||
m_copyAudioToUdp(false),
|
||||
m_udpChannelMode(UDPChannelLeft),
|
||||
m_udpChannelCodec(UDPCodecL16),
|
||||
m_audioUsageCount(0),
|
||||
m_onExit(false),
|
||||
m_volume(1.0),
|
||||
m_recordToFile(false),
|
||||
m_recordSilenceTime(0),
|
||||
m_recordSilenceNbSamples(0),
|
||||
m_recordSilenceCount(0),
|
||||
m_audioFifos()
|
||||
{
|
||||
}
|
||||
@ -114,14 +120,15 @@ bool AudioOutputDevice::start(int device, int rate)
|
||||
|
||||
m_audioOutput = new QAudioOutput(devInfo, m_audioFormat);
|
||||
m_audioNetSink = new AudioNetSink(0, m_audioFormat.sampleRate(), false);
|
||||
m_wavFileRecord = new WavFileRecord(m_audioFormat.sampleRate());
|
||||
m_audioOutput->setVolume(m_volume);
|
||||
m_recordSilenceNbSamples = (m_recordSilenceTime * m_audioFormat.sampleRate()) / 10; // time in 100'ś ms
|
||||
|
||||
QIODevice::open(QIODevice::ReadOnly);
|
||||
|
||||
m_audioOutput->start(this);
|
||||
|
||||
if (m_audioOutput->state() != QAudio::ActiveState)
|
||||
{
|
||||
if (m_audioOutput->state() != QAudio::ActiveState) {
|
||||
qWarning("AudioOutputDevice::start: cannot start");
|
||||
}
|
||||
// }
|
||||
@ -139,8 +146,11 @@ void AudioOutputDevice::stop()
|
||||
m_audioOutput->stop();
|
||||
QIODevice::close();
|
||||
delete m_audioNetSink;
|
||||
m_audioNetSink = 0;
|
||||
m_audioNetSink = nullptr;
|
||||
delete m_wavFileRecord;
|
||||
m_wavFileRecord = nullptr;
|
||||
delete m_audioOutput;
|
||||
m_audioOutput = nullptr;
|
||||
|
||||
// if (m_audioUsageCount > 0)
|
||||
// {
|
||||
@ -161,14 +171,12 @@ void AudioOutputDevice::stop()
|
||||
void AudioOutputDevice::addFifo(AudioFifo* audioFifo)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
m_audioFifos.push_back(audioFifo);
|
||||
}
|
||||
|
||||
void AudioOutputDevice::removeFifo(AudioFifo* audioFifo)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
m_audioFifos.remove(audioFifo);
|
||||
}
|
||||
|
||||
@ -219,6 +227,63 @@ void AudioOutputDevice::setUdpDecimation(uint32_t decimation)
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputDevice::setFileRecordName(const QString& fileRecordName)
|
||||
{
|
||||
if (!m_wavFileRecord) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList dotBreakout = 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("AudioOutputDevice::setFileRecordName: newFileRecordName: %s fileBase: %s", qPrintable(newFileRecordName), qPrintable(fileBase));
|
||||
m_wavFileRecord->setFileName(fileBase);
|
||||
}
|
||||
|
||||
void AudioOutputDevice::setRecordToFile(bool recordToFile)
|
||||
{
|
||||
if (!m_wavFileRecord) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (recordToFile)
|
||||
{
|
||||
if (!m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->startRecording();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
}
|
||||
|
||||
m_recordToFile = recordToFile;
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
|
||||
void AudioOutputDevice::setRecordSilenceTime(int recordSilenceTime)
|
||||
{
|
||||
m_recordSilenceNbSamples = (recordSilenceTime * m_audioFormat.sampleRate()) / 10; // time in 100'ś ms
|
||||
m_recordSilenceCount = 0;
|
||||
m_recordSilenceTime = recordSilenceTime;
|
||||
}
|
||||
|
||||
qint64 AudioOutputDevice::readData(char* data, qint64 maxLen)
|
||||
{
|
||||
//qDebug("AudioOutputDevice::readData: %lld", maxLen);
|
||||
@ -331,6 +396,36 @@ qint64 AudioOutputDevice::readData(char* data, qint64 maxLen)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_recordToFile) && (m_wavFileRecord))
|
||||
{
|
||||
if ((sr == 0) && (sl == 0))
|
||||
{
|
||||
if (m_recordSilenceNbSamples <= 0)
|
||||
{
|
||||
m_wavFileRecord->write(sl, sr);
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
else if (m_recordSilenceCount < m_recordSilenceNbSamples)
|
||||
{
|
||||
m_wavFileRecord->write(sl, sr);
|
||||
m_recordSilenceCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_wavFileRecord->stopRecording();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_wavFileRecord->isRecording()) {
|
||||
m_wavFileRecord->startRecording();
|
||||
}
|
||||
|
||||
m_wavFileRecord->write(sl, sr);
|
||||
m_recordSilenceCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return samplesPerBuffer * 4;
|
||||
|
@ -31,6 +31,7 @@ class QAudioOutput;
|
||||
class AudioFifo;
|
||||
class AudioOutputPipe;
|
||||
class AudioNetSink;
|
||||
class WavFileRecord;
|
||||
|
||||
class SDRBASE_API AudioOutputDevice : QIODevice {
|
||||
public:
|
||||
@ -72,17 +73,26 @@ public:
|
||||
void setUdpChannelFormat(UDPChannelCodec udpChannelCodec, bool stereo, int sampleRate);
|
||||
void setUdpDecimation(uint32_t decimation);
|
||||
void setVolume(float volume);
|
||||
void setFileRecordName(const QString& fileRecordName);
|
||||
void setRecordToFile(bool recordToFile);
|
||||
void setRecordSilenceTime(int recordSilenceTime);
|
||||
|
||||
private:
|
||||
QRecursiveMutex m_mutex;
|
||||
QAudioOutput* m_audioOutput;
|
||||
AudioNetSink* m_audioNetSink;
|
||||
WavFileRecord* m_wavFileRecord;
|
||||
bool m_copyAudioToUdp;
|
||||
UDPChannelMode m_udpChannelMode;
|
||||
UDPChannelCodec m_udpChannelCodec;
|
||||
uint m_audioUsageCount;
|
||||
bool m_onExit;
|
||||
float m_volume;
|
||||
QString m_fileRecordName;
|
||||
bool m_recordToFile;
|
||||
int m_recordSilenceTime;
|
||||
int m_recordSilenceNbSamples;
|
||||
int m_recordSilenceCount;
|
||||
|
||||
std::list<AudioFifo*> m_audioFifos;
|
||||
std::vector<qint32> m_mixBuffer;
|
||||
|
@ -111,6 +111,19 @@ void WavFileRecord::feed(const SampleVector::const_iterator& begin, const Sample
|
||||
}
|
||||
}
|
||||
|
||||
void WavFileRecord::write(qint16 lSample, qint16 rSample)
|
||||
{
|
||||
if (m_recordStart)
|
||||
{
|
||||
writeHeader();
|
||||
m_recordStart = false;
|
||||
}
|
||||
|
||||
m_sampleFile.write(reinterpret_cast<const char*>(&lSample), 2);
|
||||
m_sampleFile.write(reinterpret_cast<const char*>(&rSample), 2);
|
||||
m_byteCount += 4;
|
||||
}
|
||||
|
||||
void WavFileRecord::start()
|
||||
{
|
||||
}
|
||||
|
@ -97,6 +97,7 @@ public:
|
||||
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
|
||||
virtual void start() override;
|
||||
virtual void stop() override;
|
||||
virtual bool handleMessage(const Message& message) override;
|
||||
|
Loading…
Reference in New Issue
Block a user