From 75d4503a0118b8136ed534e67af5c84fb860291a Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Fri, 8 Mar 2013 14:56:12 +0000
Subject: [PATCH] ps3: implement very simple audio playback.

---
 src/sample.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 7 deletions(-)

diff --git a/src/sample.cpp b/src/sample.cpp
index 727e586d..3cf74aa3 100644
--- a/src/sample.cpp
+++ b/src/sample.cpp
@@ -16,7 +16,9 @@
 #include <cstdio>
 #include <cstring>
 
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+#   include <cell/mstream.h> /* multistream */
+#elif defined USE_SDL_MIXER
 #   if defined HAVE_SDL_SDL_H
 #      include <SDL/SDL.h>
 #   else
@@ -46,7 +48,29 @@ class SampleData
 
 private:
     String m_name;
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    static void Callback(int stream, void *data, int type,
+                         void *write_buf, int buf_size)
+    {
+        UNUSED(write_buf, buf_size);
+        switch (type)
+        {
+        case CELL_MS_CALLBACK_MOREDATA:
+            /* For streamed sound */
+            break;
+        case CELL_MS_CALLBACK_CLOSESTREAM:
+        case CELL_MS_CALLBACK_FINISHSTREAM:
+            /* Finished playing */
+            break;
+        default:
+            /* FIXME: we can't reach here */
+            break;
+        }
+    }
+
+    String m_data;
+    int m_channel;
+#elif defined USE_SDL_MIXER
     Mix_Chunk *m_chunk;
     int m_channel;
 #endif
@@ -61,7 +85,24 @@ Sample::Sample(char const *path)
 {
     data->m_name = String("<sample> ") + path;
 
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    Array<String> pathlist = System::GetPathList(path);
+    File f;
+    for (int i = 0; i < pathlist.Count(); ++i)
+    {
+        f.Open(pathlist[i], FileAccess::Read);
+        if (f.IsValid())
+        {
+            data->m_data = f.ReadString();
+            f.Close();
+            break;
+        }
+    }
+    if (data->m_data.Count() == 0)
+    {
+        Log::Error("could not load sample %s\n", path);
+    }
+#elif defined USE_SDL_MIXER
     Array<String> pathlist = System::GetPathList(path);
     for (int i = 0; i < pathlist.Count(); ++i)
     {
@@ -83,7 +124,9 @@ Sample::Sample(char const *path)
 
 Sample::~Sample()
 {
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    /* Nothing to do */
+#elif defined USE_SDL_MIXER
     Mix_FreeChunk(data->m_chunk);
 #endif
     delete data;
@@ -101,21 +144,57 @@ char const *Sample::GetName()
 
 void Sample::Play()
 {
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    if (data->m_data.Count() <= 64 + 256)
+        return;
+
+    data->m_channel = cellMSStreamOpen();
+
+    CellMSInfo mi;
+    mi.SubBusGroup = CELL_MS_MASTER_BUS;
+    mi.FirstBuffer = &data->m_data[0] + 64;
+    /* FIXME: hardcoded crap */
+    mi.FirstBufferSize = data->m_data.Count() - 64 - 256;
+    mi.SecondBuffer = nullptr;
+    mi.SecondBufferSize = 0;
+
+    mi.Pitch = 44100;
+    mi.numChannels = 2;
+    mi.flags = CELL_MS_STREAM_AUTOCLOSE;
+
+    mi.initialOffset = 0;
+    mi.inputType = CELL_MS_16BIT_LITTLE;
+    cellMSStreamSetInfo(data->m_channel, &mi);
+
+    cellMSStreamSetCallbackFunc(data->m_channel, SampleData::Callback);
+
+    cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
+                         CELL_MS_SPEAKER_FL, CELL_MS_CHANNEL_0, 1.0f);
+    cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
+                         CELL_MS_SPEAKER_FR, CELL_MS_CHANNEL_0, 1.0f);
+    cellMSStreamPlay(data->m_channel);
+#elif defined USE_SDL_MIXER
     data->m_channel = Mix_PlayChannel(-1, data->m_chunk, 0);
 #endif
 }
 
 void Sample::Loop()
 {
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    /* FIXME: not implemented */
+    Play();
+#elif defined USE_SDL_MIXER
     data->m_channel = Mix_PlayChannel(-1, data->m_chunk, -1);
 #endif
 }
 
 void Sample::Stop()
 {
-#if defined USE_SDL_MIXER
+#if __CELLOS_LV2__
+    if (data->m_channel >= 0)
+        cellMSStreamClose(data->m_channel);
+    data->m_channel = -1;
+#elif defined USE_SDL_MIXER
     if (data->m_channel >= 0)
         Mix_HaltChannel(data->m_channel);
     data->m_channel = -1;