CoreAudio: Make it possible to set volume on of QAudioOutput
authorAndy Nichols <andy.nichols@digia.com>
Sun, 2 Mar 2014 17:44:52 +0000 (18:44 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 3 Mar 2014 14:55:00 +0000 (15:55 +0100)
QAudioOutput::setVolume stopped working for CoreAudio when it was ported
to live in it's own plugin.  This was because it was not possible to set
the volume of QAudioOutput in iOS.  Now the functionality has been
restored and added for iOS as well.  For OS X we use the old method of
setting the volume property of the AudioUnit.  On iOS it is not possible
to set the volume on a per AudioUnit basis, so we now manually modify
the buffer contents (the same we do for QAudioInput already).

Task-number: QTBUG-36756
Change-Id: I42b5892fe5534217043fa55e7b5b9a4ce824050d
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
src/plugins/coreaudio/coreaudiooutput.mm

index bb0da57..e5e1c65 100644 (file)
 # include <CoreServices/CoreServices.h>
 #endif
 
+#if defined(Q_OS_IOS)
+# include <QtMultimedia/private/qaudiohelpers_p.h>
+#endif
+
 QT_BEGIN_NAMESPACE
 
 static const int DEFAULT_BUFFER_SIZE = 8 * 1024;
@@ -430,13 +434,23 @@ QAudioFormat CoreAudioOutput::format() const
 void CoreAudioOutput::setVolume(qreal volume)
 {
     const qreal normalizedVolume = qBound(qreal(0.0), volume, qreal(1.0));
-    m_cachedVolume = normalizedVolume;
     if (!m_isOpen) {
+        m_cachedVolume = normalizedVolume;
         return;
     }
 
-    //TODO: actually set the output volume here
-    //To set the output volume you need a handle to the mixer unit
+#if defined(Q_OS_OSX)
+    //on OS X the volume can be set directly on the AudioUnit
+    if (AudioUnitSetParameter(m_audioUnit,
+                              kHALOutputParam_Volume,
+                              kAudioUnitScope_Global,
+                              0 /* bus */,
+                              (float)normalizedVolume,
+                              0) == noErr)
+        m_cachedVolume = normalizedVolume;
+#else
+    m_cachedVolume = normalizedVolume;
+#endif
 }
 
 qreal CoreAudioOutput::volume() const
@@ -497,6 +511,17 @@ OSStatus CoreAudioOutput::renderCallback(void *inRefCon, AudioUnitRenderActionFl
         if (framesRead > 0) {
             ioData->mBuffers[0].mDataByteSize = framesRead * bytesPerFrame;
             d->m_totalFrames += framesRead;
+#ifdef Q_OS_IOS
+        // on iOS we have to adjust the sound volume ourselves
+        if (!qFuzzyCompare(d->m_cachedVolume, qreal(1.0f))) {
+            QAudioHelperInternal::qMultiplySamples(d->m_cachedVolume,
+                                                   d->m_audioFormat,
+                                                   ioData->mBuffers[0].mData, /* input */
+                                                   ioData->mBuffers[0].mData, /* output */
+                                                   ioData->mBuffers[0].mDataByteSize);
+        }
+#endif
+
         }
         else {
             ioData->mBuffers[0].mDataByteSize = 0;