From 1dee8ceda1e5ecd5ebaee464b1450f323e82305f Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sat, 4 Aug 2018 00:03:12 -0400
Subject: [PATCH] audio_core: Use s16 where possible for audio samples.

---
 src/audio_core/audio_out.cpp            |  2 +-
 src/audio_core/audio_out.h              |  2 +-
 src/audio_core/buffer.h                 | 13 +++++++++----
 src/audio_core/cubeb_sink.cpp           | 11 +++++------
 src/audio_core/null_sink.h              |  3 +--
 src/audio_core/sink_stream.h            |  4 ++--
 src/audio_core/stream.cpp               | 19 +++++--------------
 src/audio_core/stream.h                 |  3 ---
 src/core/hle/service/audio/audout_u.cpp |  6 +++---
 9 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp
index eb9db755a6..12632a95c5 100644
--- a/src/audio_core/audio_out.cpp
+++ b/src/audio_core/audio_out.cpp
@@ -51,7 +51,7 @@ void AudioOut::StopStream(StreamPtr stream) {
     stream->Stop();
 }
 
-bool AudioOut::QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data) {
+bool AudioOut::QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<s16>&& data) {
     return stream->QueueBuffer(std::make_shared<Buffer>(tag, std::move(data)));
 }
 
diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h
index d564ff91ae..39b7e656b2 100644
--- a/src/audio_core/audio_out.h
+++ b/src/audio_core/audio_out.h
@@ -34,7 +34,7 @@ public:
     void StopStream(StreamPtr stream);
 
     /// Queues a buffer into the specified audio stream, returns true on success
-    bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data);
+    bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<s16>&& data);
 
 private:
     SinkPtr sink;
diff --git a/src/audio_core/buffer.h b/src/audio_core/buffer.h
index 4bf5fd58a7..a323b23ec9 100644
--- a/src/audio_core/buffer.h
+++ b/src/audio_core/buffer.h
@@ -18,11 +18,16 @@ class Buffer {
 public:
     using Tag = u64;
 
-    Buffer(Tag tag, std::vector<u8>&& data) : tag{tag}, data{std::move(data)} {}
+    Buffer(Tag tag, std::vector<s16>&& samples) : tag{tag}, samples{std::move(samples)} {}
 
     /// Returns the raw audio data for the buffer
-    const std::vector<u8>& GetData() const {
-        return data;
+    std::vector<s16>& Samples() {
+        return samples;
+    }
+
+    /// Returns the raw audio data for the buffer
+    const std::vector<s16>& GetSamples() const {
+        return samples;
     }
 
     /// Returns the buffer tag, this is provided by the game to the audout service
@@ -32,7 +37,7 @@ public:
 
 private:
     Tag tag;
-    std::vector<u8> data;
+    std::vector<s16> samples;
 };
 
 using BufferPtr = std::shared_ptr<Buffer>;
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 0b0e9a0535..1501ef1f48 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -61,25 +61,24 @@ public:
         cubeb_stream_destroy(stream_backend);
     }
 
-    void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) override {
+    void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) override {
         if (!ctx) {
             return;
         }
 
-        queue.reserve(queue.size() + sample_count * GetNumChannels());
+        queue.reserve(queue.size() + samples.size() * GetNumChannels());
 
         if (is_6_channel) {
             // Downsample 6 channels to 2
-            const size_t sample_count_copy_size = sample_count * num_channels * 2;
+            const size_t sample_count_copy_size = samples.size() * 2;
             queue.reserve(sample_count_copy_size);
-            for (size_t i = 0; i < sample_count * num_channels; i += num_channels) {
+            for (size_t i = 0; i < samples.size(); i += num_channels) {
                 queue.push_back(samples[i]);
                 queue.push_back(samples[i + 1]);
             }
         } else {
             // Copy as-is
-            std::copy(samples, samples + sample_count * GetNumChannels(),
-                      std::back_inserter(queue));
+            std::copy(samples.begin(), samples.end(), std::back_inserter(queue));
         }
     }
 
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
index 66041ea3f8..f235d93e56 100644
--- a/src/audio_core/null_sink.h
+++ b/src/audio_core/null_sink.h
@@ -20,8 +20,7 @@ public:
 
 private:
     struct NullSinkStreamImpl final : SinkStream {
-        void EnqueueSamples(u32 /*num_channels*/, const s16* /*samples*/,
-                            size_t /*sample_count*/) override {}
+        void EnqueueSamples(u32 /*num_channels*/, const std::vector<s16>& /*samples*/) override {}
     } null_sink_stream;
 };
 
diff --git a/src/audio_core/sink_stream.h b/src/audio_core/sink_stream.h
index e7a3f01b0c..41b6736d88 100644
--- a/src/audio_core/sink_stream.h
+++ b/src/audio_core/sink_stream.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <vector>
 
 #include "common/common_types.h"
 
@@ -22,9 +23,8 @@ public:
      * Feed stereo samples to sink.
      * @param num_channels Number of channels used.
      * @param samples Samples in interleaved stereo PCM16 format.
-     * @param sample_count Number of samples.
      */
-    virtual void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) = 0;
+    virtual void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) = 0;
 };
 
 using SinkStreamPtr = std::unique_ptr<SinkStream>;
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 7ab87c0c9d..ad9e2915ce 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -32,10 +32,6 @@ u32 Stream::GetNumChannels() const {
     return {};
 }
 
-u32 Stream::GetSampleSize() const {
-    return GetNumChannels() * 2;
-}
-
 Stream::Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback,
                SinkStream& sink_stream, std::string&& name_)
     : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
@@ -55,17 +51,15 @@ void Stream::Stop() {
 }
 
 s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {
-    const size_t num_samples{buffer.GetData().size() / GetSampleSize()};
+    const size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
     return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate);
 }
 
-static std::vector<s16> GetVolumeAdjustedSamples(const std::vector<u8>& data) {
-    std::vector<s16> samples(data.size() / sizeof(s16));
-    std::memcpy(samples.data(), data.data(), data.size());
+static void VolumeAdjustSamples(std::vector<s16>& samples) {
     const float volume{std::clamp(Settings::values.volume, 0.0f, 1.0f)};
 
     if (volume == 1.0f) {
-        return samples;
+        return;
     }
 
     // Implementation of a volume slider with a dynamic range of 60 dB
@@ -73,8 +67,6 @@ static std::vector<s16> GetVolumeAdjustedSamples(const std::vector<u8>& data) {
     for (auto& sample : samples) {
         sample = static_cast<s16>(sample * volume_scale_factor);
     }
-
-    return samples;
 }
 
 void Stream::PlayNextBuffer() {
@@ -96,9 +88,8 @@ void Stream::PlayNextBuffer() {
     active_buffer = queued_buffers.front();
     queued_buffers.pop();
 
-    const size_t sample_count{active_buffer->GetData().size() / GetSampleSize()};
-    sink_stream.EnqueueSamples(
-        GetNumChannels(), GetVolumeAdjustedSamples(active_buffer->GetData()).data(), sample_count);
+    VolumeAdjustSamples(active_buffer->Samples());
+    sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
 
     CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
 }
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 00f991733b..049b92ca92 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -69,9 +69,6 @@ public:
     /// Gets the number of channels
     u32 GetNumChannels() const;
 
-    /// Gets the sample size in bytes
-    u32 GetSampleSize() const;
-
 private:
     /// Current state of the stream
     enum class State {
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index f4a5576343..108a7c6eba 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -113,10 +113,10 @@ private:
         std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer));
         const u64 tag{rp.Pop<u64>()};
 
-        std::vector<u8> data(audio_buffer.buffer_size);
-        Memory::ReadBlock(audio_buffer.buffer, data.data(), data.size());
+        std::vector<s16> samples(audio_buffer.buffer_size / sizeof(s16));
+        Memory::ReadBlock(audio_buffer.buffer, samples.data(), audio_buffer.buffer_size);
 
-        if (!audio_core.QueueBuffer(stream, tag, std::move(data))) {
+        if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) {
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded));
         }