aaudio: apply volume in the MMAP data path

The volume scaling is in AudioStreamInternal and not the mixer
because we will need volume scaling in EXCLUSIVE mode too.

Bug: 37518243
Test: play a tone using NativeOboe app then press volume keys
Change-Id: Ibbac9770ea4493f8ade64681be86f109a92803cd
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index af4b93a..810751a 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -32,9 +32,10 @@
 #include "binding/AAudioStreamConfiguration.h"
 #include "binding/IAAudioService.h"
 #include "binding/AAudioServiceMessage.h"
-#include "fifo/FifoBuffer.h"
-
 #include "core/AudioStreamBuilder.h"
+#include "fifo/FifoBuffer.h"
+#include "utility/LinearRamp.h"
+
 #include "AudioStreamInternal.h"
 
 #define LOG_TIMESTAMPS   0
@@ -478,8 +479,9 @@
             ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
             break;
         case AAUDIO_SERVICE_EVENT_VOLUME:
-            mVolume = message->event.dataDouble;
-            ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f", mVolume);
+            mVolumeRamp.setTarget((float) message->event.dataDouble);
+            ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f",
+                     message->event.dataDouble);
             break;
         default:
             ALOGW("WARNING - processCommands() Unrecognized event = %d",
@@ -639,10 +641,10 @@
 }
 
 
-// TODO this function needs a major cleanup.
 aaudio_result_t AudioStreamInternal::writeNowWithConversion(const void *buffer,
                                        int32_t numFrames) {
-    // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)", buffer, numFrames);
+    // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)",
+    //              buffer, numFrames);
     WrappingBuffer wrappingBuffer;
     uint8_t *source = (uint8_t *) buffer;
     int32_t framesLeft = numFrames;
@@ -659,31 +661,67 @@
                 framesToWrite = framesAvailable;
             }
             int32_t numBytes = getBytesPerFrame() * framesToWrite;
-            // TODO handle volume scaling
-            if (getFormat() == mDeviceFormat) {
-                // Copy straight through.
-                memcpy(wrappingBuffer.data[partIndex], source, numBytes);
-            } else if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT
-                       && mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
-                // Data conversion.
-                AAudioConvert_floatToPcm16(
-                        (const float *) source,
-                        framesToWrite * getSamplesPerFrame(),
-                        (int16_t *) wrappingBuffer.data[partIndex]);
-            } else if (getFormat() == AAUDIO_FORMAT_PCM_I16
-                       && mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
-                // Data conversion.
-                AAudioConvert_pcm16ToFloat(
-                        (const int16_t *) source,
-                        framesToWrite * getSamplesPerFrame(),
-                        (float *) wrappingBuffer.data[partIndex]);
-            } else {
-                // TODO handle more conversions
-                ALOGE("AudioStreamInternal::writeNowWithConversion() unsupported formats: %d, %d",
-                      getFormat(), mDeviceFormat);
-                return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            int32_t numSamples = framesToWrite * getSamplesPerFrame();
+            // Data conversion.
+            float levelFrom;
+            float levelTo;
+            bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(),
+                                    &levelFrom, &levelTo);
+            // The formats are validated when the stream is opened so we do not have to
+            // check for illegal combinations here.
+            if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT) {
+                if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+                    AAudio_linearRamp(
+                            (const float *) source,
+                            (float *) wrappingBuffer.data[partIndex],
+                            framesToWrite,
+                            getSamplesPerFrame(),
+                            levelFrom,
+                            levelTo);
+                } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
+                    if (ramping) {
+                        AAudioConvert_floatToPcm16(
+                                (const float *) source,
+                                (int16_t *) wrappingBuffer.data[partIndex],
+                                framesToWrite,
+                                getSamplesPerFrame(),
+                                levelFrom,
+                                levelTo);
+                    } else {
+                        AAudioConvert_floatToPcm16(
+                                (const float *) source,
+                                (int16_t *) wrappingBuffer.data[partIndex],
+                                numSamples,
+                                levelTo);
+                    }
+                }
+            } else if (getFormat() == AAUDIO_FORMAT_PCM_I16) {
+                if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+                    if (ramping) {
+                        AAudioConvert_pcm16ToFloat(
+                                (const int16_t *) source,
+                                (float *) wrappingBuffer.data[partIndex],
+                                framesToWrite,
+                                getSamplesPerFrame(),
+                                levelFrom,
+                                levelTo);
+                    } else {
+                        AAudioConvert_pcm16ToFloat(
+                                (const int16_t *) source,
+                                (float *) wrappingBuffer.data[partIndex],
+                                numSamples,
+                                levelTo);
+                    }
+                } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
+                    AAudio_linearRamp(
+                            (const int16_t *) source,
+                            (int16_t *) wrappingBuffer.data[partIndex],
+                            framesToWrite,
+                            getSamplesPerFrame(),
+                            levelFrom,
+                            levelTo);
+                }
             }
-
             source += numBytes;
             framesLeft -= framesToWrite;
         } else {