mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Audio output: forward actual sample rate to Audio Manager
This commit is contained in:
		
							parent
							
								
									768d3f1398
								
							
						
					
					
						commit
						5df7f73da7
					
				| @ -96,6 +96,8 @@ AudioDeviceManager::AudioDeviceManager() | ||||
| 
 | ||||
|     m_defaultInputStarted = false; | ||||
|     m_defaultOutputStarted = false; | ||||
| 
 | ||||
|     connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); | ||||
| } | ||||
| 
 | ||||
| AudioDeviceManager::~AudioDeviceManager() | ||||
| @ -281,6 +283,7 @@ void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sample | ||||
|         } | ||||
| 
 | ||||
|         qDebug("AudioDeviceManager::addAudioSink: new AudioOutputDevice on thread: %p", thread); | ||||
|         audioOutputDevice->setManagerMessageQueue(&m_inputMessageQueue); | ||||
|         audioOutputDevice->moveToThread(thread); | ||||
| 
 | ||||
|         QObject::connect( | ||||
| @ -445,7 +448,6 @@ void AudioDeviceManager::startAudioOutput(int outputDeviceIndex) | ||||
|         AudioOutputDevice::MsgStart *msg = AudioOutputDevice::MsgStart::create(outputDeviceIndex, sampleRate); | ||||
|         m_audioOutputs[outputDeviceIndex]->getInputMessageQueue()->push(msg); | ||||
| 
 | ||||
|         m_audioOutputInfos[deviceName].sampleRate = sampleRate; // FIXME: possible change of sample rate in AudioOutputDevice
 | ||||
|         m_audioOutputInfos[deviceName].udpAddress = udpAddress; | ||||
|         m_audioOutputInfos[deviceName].udpPort = udpPort; | ||||
|         m_audioOutputInfos[deviceName].copyToUDP = copyAudioToUDP; | ||||
| @ -488,7 +490,7 @@ void AudioDeviceManager::startAudioInput(int inputDeviceIndex) | ||||
| 
 | ||||
|         m_audioInputs[inputDeviceIndex]->start(inputDeviceIndex, sampleRate); | ||||
|         m_audioInputs[inputDeviceIndex]->setVolume(volume); | ||||
|         m_audioInputInfos[deviceName].sampleRate = m_audioInputs[inputDeviceIndex]->getRate(); | ||||
|         m_audioInputInfos[deviceName].sampleRate = m_audioInputs[inputDeviceIndex]->getRate(); // FIXME
 | ||||
|         m_audioInputInfos[deviceName].volume = volume; | ||||
|         m_defaultInputStarted = (inputDeviceIndex == -1); | ||||
|     } | ||||
| @ -671,17 +673,6 @@ void AudioDeviceManager::setOutputDeviceInfo(int outputDeviceIndex, const Output | ||||
| 
 | ||||
|         AudioOutputDevice::MsgStart *msgStart = AudioOutputDevice::MsgStart::create(outputDeviceIndex, deviceInfo.sampleRate); | ||||
|         audioOutput->getInputMessageQueue()->push(msgStart); | ||||
| 
 | ||||
|         m_audioOutputInfos[deviceName].sampleRate = audioOutput->getRate(); // store actual sample rate
 | ||||
| 
 | ||||
|         // send message to attached channels
 | ||||
|         QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); | ||||
| 
 | ||||
|         for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) | ||||
|         { | ||||
|             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioOutput); | ||||
|             (*it)->push(msg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     audioOutput->setUdpCopyToUDP(deviceInfo.copyToUDP); | ||||
| @ -724,18 +715,6 @@ void AudioDeviceManager::unsetOutputDeviceInfo(int outputDeviceIndex) | ||||
| 
 | ||||
|     stopAudioOutput(outputDeviceIndex); | ||||
|     startAudioOutput(outputDeviceIndex); | ||||
| 
 | ||||
|     if (oldDeviceInfo.sampleRate != m_audioOutputInfos[deviceName].sampleRate) | ||||
|     { | ||||
|         // send message to attached channels
 | ||||
|         QList<MessageQueue *>::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); | ||||
| 
 | ||||
|         for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) | ||||
|         { | ||||
|             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioOutput); | ||||
|             (*it)->push(msg); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AudioDeviceManager::unsetInputDeviceInfo(int inputDeviceIndex) | ||||
| @ -865,3 +844,40 @@ void AudioDeviceManager::debugAudioOutputInfos() const | ||||
|                 << " decimationFactor: " << it.value().udpDecimationFactor; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool AudioDeviceManager::handleMessage(const Message& msg) | ||||
| { | ||||
|     if (AudioOutputDevice::MsgReportSampleRate::match(msg)) | ||||
|     { | ||||
|         AudioOutputDevice::MsgReportSampleRate& report = (AudioOutputDevice::MsgReportSampleRate&) msg; | ||||
|         int deviceIndex = report.getDeviceIndex(); | ||||
|         const QString& deviceName = report.getDeviceName(); | ||||
|         int sampleRate = report.getSampleRate(); | ||||
|         qDebug("AudioDeviceManager::handleMessage: AudioOutputDevice::MsgReportSampleRate: device(%d) %s: rate: %d", | ||||
|             deviceIndex, qPrintable(deviceName), sampleRate); | ||||
|         m_audioOutputInfos[deviceName].sampleRate = sampleRate; | ||||
| 
 | ||||
|         // send message to attached channels
 | ||||
|         for (auto& messageQueue : m_outputDeviceSinkMessageQueues[deviceIndex]) | ||||
|         { | ||||
|             DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate, DSPConfigureAudio::AudioOutput); | ||||
|             messageQueue->push(msg); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void AudioDeviceManager::handleInputMessages() | ||||
| { | ||||
| 	Message* message; | ||||
| 
 | ||||
| 	while ((message = m_inputMessageQueue.pop()) != nullptr) | ||||
| 	{ | ||||
| 		if (handleMessage(*message)) { | ||||
| 			delete message; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -22,18 +22,20 @@ | ||||
| #include <QStringList> | ||||
| #include <QList> | ||||
| #include <QMap> | ||||
| #include <QObject> | ||||
| 
 | ||||
| #include "audio/audioinputdevice.h" | ||||
| #include "audio/audiooutputdevice.h" | ||||
| #include "audio/audiodeviceinfo.h" | ||||
| #include "util/messagequeue.h" | ||||
| #include "export.h" | ||||
| 
 | ||||
| class QThread; | ||||
| class QDataStream; | ||||
| class AudioFifo; | ||||
| class MessageQueue; | ||||
| 
 | ||||
| class SDRBASE_API AudioDeviceManager { | ||||
| class SDRBASE_API AudioDeviceManager : public QObject { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     class InputDeviceInfo | ||||
|     { | ||||
| @ -149,6 +151,8 @@ private: | ||||
|     bool m_defaultOutputStarted; //!< True if the default audio output (-1) has already been started
 | ||||
|     bool m_defaultInputStarted;  //!< True if the default audio input (-1) has already been started
 | ||||
| 
 | ||||
|     MessageQueue m_inputMessageQueue; | ||||
| 
 | ||||
|     void resetToDefaults(); | ||||
|     QByteArray serialize() const; | ||||
|     bool deserialize(const QByteArray& data); | ||||
| @ -166,7 +170,12 @@ private: | ||||
|     void deserializeOutputMap(QByteArray& data); | ||||
|     void debugAudioOutputInfos() const; | ||||
| 
 | ||||
|     bool handleMessage(const Message& cmd); | ||||
| 
 | ||||
| 	friend class MainSettings; | ||||
| 
 | ||||
| private slots: | ||||
|     void handleInputMessages(); | ||||
| }; | ||||
| 
 | ||||
| QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info); | ||||
|  | ||||
| @ -32,6 +32,7 @@ | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(AudioOutputDevice::MsgStart, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AudioOutputDevice::MsgStop, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AudioOutputDevice::MsgReportSampleRate, Message) | ||||
| 
 | ||||
| AudioOutputDevice::AudioOutputDevice() : | ||||
| 	m_audioOutput(nullptr), | ||||
| @ -47,7 +48,8 @@ AudioOutputDevice::AudioOutputDevice() : | ||||
|     m_recordSilenceTime(0), | ||||
|     m_recordSilenceNbSamples(0), | ||||
|     m_recordSilenceCount(0), | ||||
| 	m_audioFifos() | ||||
| 	m_audioFifos(), | ||||
|     m_managerMessageQueue(nullptr) | ||||
| { | ||||
|     connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); | ||||
| } | ||||
| @ -66,18 +68,18 @@ AudioOutputDevice::~AudioOutputDevice() | ||||
| //	m_audioFifos.clear();
 | ||||
| } | ||||
| 
 | ||||
| bool AudioOutputDevice::start(int device, int rate) | ||||
| bool AudioOutputDevice::start(int deviceIndex, int sampleRate) | ||||
| { | ||||
|     // if (m_audioOutput) {
 | ||||
|     //     return true;
 | ||||
|     // }
 | ||||
| //	if (m_audioUsageCount == 0)
 | ||||
| //	{
 | ||||
|         qDebug("AudioOutputDevice::start: device: %d rate: %d thread: %p", device, rate, QThread::currentThread()); | ||||
|         qDebug("AudioOutputDevice::start: device: %d rate: %d thread: %p", deviceIndex, sampleRate, QThread::currentThread()); | ||||
|         QMutexLocker mutexLocker(&m_mutex); | ||||
|         AudioDeviceInfo devInfo; | ||||
| 
 | ||||
|         if (device < 0) | ||||
|         if (deviceIndex < 0) | ||||
|         { | ||||
|             devInfo = AudioDeviceInfo::defaultOutputDevice(); | ||||
|             qWarning("AudioOutputDevice::start: using system default device %s", qPrintable(devInfo.defaultOutputDevice().deviceName())); | ||||
| @ -86,15 +88,16 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|         { | ||||
|             QList<AudioDeviceInfo> devicesInfo = AudioDeviceInfo::availableOutputDevices(); | ||||
| 
 | ||||
|             if (device < devicesInfo.size()) | ||||
|             if (deviceIndex < devicesInfo.size()) | ||||
|             { | ||||
|                 devInfo = devicesInfo[device]; | ||||
|                 qWarning("AudioOutputDevice::start: using audio device #%d: %s", device, qPrintable(devInfo.deviceName())); | ||||
|                 devInfo = devicesInfo[deviceIndex]; | ||||
|                 qWarning("AudioOutputDevice::start: using audio device #%d: %s", deviceIndex, qPrintable(devInfo.deviceName())); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 devInfo = AudioDeviceInfo::defaultOutputDevice(); | ||||
|                 qWarning("AudioOutputDevice::start: audio device #%d does not exist. Using system default device %s", device, qPrintable(devInfo.defaultOutputDevice().deviceName())); | ||||
|                 qWarning("AudioOutputDevice::start: audio device #%d does not exist. Using system default device %s", deviceIndex, qPrintable(devInfo.defaultOutputDevice().deviceName())); | ||||
|                 deviceIndex = -1; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -104,7 +107,7 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|         m_audioFormat = devInfo.deviceInfo().preferredFormat(); | ||||
| #endif | ||||
| 
 | ||||
|         m_audioFormat.setSampleRate(rate); | ||||
|         m_audioFormat.setSampleRate(sampleRate); | ||||
|         m_audioFormat.setChannelCount(2); | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) | ||||
|         m_audioFormat.setSampleFormat(QAudioFormat::Int16); | ||||
| @ -118,7 +121,7 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|         if (!devInfo.isFormatSupported(m_audioFormat)) | ||||
|         { | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) | ||||
|             qWarning("AudioOutputDevice::start: format %d Hz 2xS16LE audio/pcm not supported.", rate); | ||||
|             qWarning("AudioOutputDevice::start: format %d Hz 2xS16LE audio/pcm not supported.", sampleRate); | ||||
| #else | ||||
|             m_audioFormat = devInfo.deviceInfo().nearestFormat(m_audioFormat); | ||||
|             std::ostringstream os; | ||||
| @ -128,7 +131,7 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|                << " codec: "  << m_audioFormat.codec().toStdString() | ||||
|                << " byteOrder: " <<  (m_audioFormat.byteOrder() == QAudioFormat::BigEndian ? "BE" : "LE") | ||||
|                << " sampleType: " << (int) m_audioFormat.sampleType(); | ||||
|             qWarning("AudioOutputDevice::start: format %d Hz 2xS16LE audio/pcm not supported. Using: %s", rate, os.str().c_str()); | ||||
|             qWarning("AudioOutputDevice::start: format %d Hz 2xS16LE audio/pcm not supported. Using: %s", sampleRate, os.str().c_str()); | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
| @ -161,7 +164,7 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|         // m_audioOutput->setBufferSize(m_audioFormat.sampleRate() / 5); FIXME: does not work generally
 | ||||
|         m_recordSilenceNbSamples = (m_recordSilenceTime * m_audioFormat.sampleRate()) / 10; // time in 100'ś ms
 | ||||
| 
 | ||||
|         QIODevice::open(QIODevice::ReadOnly); | ||||
|         QIODevice::open(QIODevice::ReadOnly | QIODevice::Unbuffered); | ||||
| 
 | ||||
|         m_audioOutput->start(this); | ||||
| 
 | ||||
| @ -170,6 +173,10 @@ bool AudioOutputDevice::start(int device, int rate) | ||||
|         } else { | ||||
|             qDebug("AudioOutputDevice::start: started buffer: %d bytes", m_audioOutput->bufferSize()); | ||||
|         } | ||||
| 
 | ||||
|         if (m_managerMessageQueue) { | ||||
|             m_managerMessageQueue->push(AudioOutputDevice::MsgReportSampleRate::create(deviceIndex, devInfo.deviceName(), m_audioFormat.sampleRate())); | ||||
|         } | ||||
| //	}
 | ||||
| //
 | ||||
| //	m_audioUsageCount++;
 | ||||
|  | ||||
| @ -77,6 +77,30 @@ public: | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     class MsgReportSampleRate : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
|     public: | ||||
|         int getDeviceIndex() const { return m_deviceIndex; } | ||||
|         const QString& getDeviceName() const { return m_deviceName; } | ||||
|         int getSampleRate() const { return m_sampleRate; } | ||||
| 
 | ||||
|         static MsgReportSampleRate* create(int deviceIndex, const QString& deviceName, int sampleRate) { | ||||
|             return new MsgReportSampleRate(deviceIndex, deviceName, sampleRate); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         int m_deviceIndex; | ||||
|         QString m_deviceName; | ||||
|         int m_sampleRate; | ||||
| 
 | ||||
|         MsgReportSampleRate(int deviceIndex, const QString& deviceName, int sampleRate) : | ||||
|             Message(), | ||||
|             m_deviceIndex(deviceIndex), | ||||
|             m_deviceName(deviceName), | ||||
|             m_sampleRate(sampleRate) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     enum UDPChannelMode | ||||
|     { | ||||
|         UDPChannelLeft, | ||||
| @ -118,6 +142,7 @@ public: | ||||
|     void setDeviceName(const QString& deviceName) { m_deviceName = deviceName;} | ||||
| 
 | ||||
|     MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } | ||||
|     void setManagerMessageQueue(MessageQueue *messageQueue) { m_managerMessageQueue = messageQueue; } | ||||
| 
 | ||||
| private: | ||||
| 	QRecursiveMutex m_mutex; | ||||
| @ -147,6 +172,7 @@ private: | ||||
|     QString m_deviceName; | ||||
| 
 | ||||
|     MessageQueue m_inputMessageQueue; | ||||
|     MessageQueue *m_managerMessageQueue; | ||||
| 
 | ||||
| 	//virtual bool open(OpenMode mode);
 | ||||
| 	virtual qint64 readData(char* data, qint64 maxLen); | ||||
| @ -155,7 +181,7 @@ private: | ||||
|     void writeSampleToFile(qint16 lSample, qint16 rSample); | ||||
|     bool handleMessage(const Message& cmd); | ||||
| 
 | ||||
| 	bool start(int device, int rate); | ||||
| 	bool start(int deviceIndex, int sampleRate); | ||||
| 	void stop(); | ||||
| 
 | ||||
| 	friend class AudioOutputPipe; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user