philippe44 1 год назад
Родитель
Сommit
008c36facf
100 измененных файлов с 9869 добавлено и 834 удалено
  1. 1 1
      CMakeLists.txt
  2. 4 2
      components/spotify/CMakeLists.txt
  3. 392 295
      components/spotify/Shim.cpp
  4. 0 49
      components/spotify/Shim.h
  5. 0 17
      components/spotify/cspot/CMakeLists.txt
  6. 3 0
      components/spotify/cspot/README.md
  7. 2 0
      components/spotify/cspot/bell/.clangd
  8. 52 0
      components/spotify/cspot/bell/.github/workflows/c-cpp.yml
  9. 2 1
      components/spotify/cspot/bell/.gitignore
  10. 9 10
      components/spotify/cspot/bell/.gitmodules
  11. 65 0
      components/spotify/cspot/bell/.vscode/settings.json
  12. 153 100
      components/spotify/cspot/bell/CMakeLists.txt
  13. 0 9
      components/spotify/cspot/bell/README.md
  14. 0 163
      components/spotify/cspot/bell/cJSON/Makefile
  15. 0 71
      components/spotify/cspot/bell/cJSON/tests/unity/examples/example_1/makefile
  16. 0 70
      components/spotify/cspot/bell/cJSON/tests/unity/examples/example_2/makefile
  17. 35 0
      components/spotify/cspot/bell/cmake/FindMbedTLS.cmake
  18. 63 0
      components/spotify/cspot/bell/cmake/Findportaudio.cmake
  19. 14 0
      components/spotify/cspot/bell/example/CMakeLists.txt
  20. 70 0
      components/spotify/cspot/bell/example/main.cpp
  21. 13 0
      components/spotify/cspot/bell/example/scripts/dsp_spectogram.py
  22. 6 0
      components/spotify/cspot/bell/external/alac/.gitignore
  23. 241 0
      components/spotify/cspot/bell/external/alac/ALACMagicCookieDescription.txt
  24. 9 0
      components/spotify/cspot/bell/external/alac/CONTRIBUTING.md
  25. 53 0
      components/spotify/cspot/bell/external/alac/LICENSE
  26. 9 0
      components/spotify/cspot/bell/external/alac/PULL_REQUEST_TEMPLATE.md
  27. 44 0
      components/spotify/cspot/bell/external/alac/ReadMe.txt
  28. 202 0
      components/spotify/cspot/bell/external/alac/codec/ALACAudioTypes.h
  29. 260 0
      components/spotify/cspot/bell/external/alac/codec/ALACBitUtilities.c
  30. 104 0
      components/spotify/cspot/bell/external/alac/codec/ALACBitUtilities.h
  31. 737 0
      components/spotify/cspot/bell/external/alac/codec/ALACDecoder.cpp
  32. 65 0
      components/spotify/cspot/bell/external/alac/codec/ALACDecoder.h
  33. 1432 0
      components/spotify/cspot/bell/external/alac/codec/ALACEncoder.cpp
  34. 92 0
      components/spotify/cspot/bell/external/alac/codec/ALACEncoder.h
  35. 335 0
      components/spotify/cspot/bell/external/alac/codec/APPLE_LICENSE.txt
  36. 177 0
      components/spotify/cspot/bell/external/alac/codec/EndianPortable.c
  37. 59 0
      components/spotify/cspot/bell/external/alac/codec/EndianPortable.h
  38. 362 0
      components/spotify/cspot/bell/external/alac/codec/ag_dec.c
  39. 370 0
      components/spotify/cspot/bell/external/alac/codec/ag_enc.c
  40. 81 0
      components/spotify/cspot/bell/external/alac/codec/aglib.h
  41. 85 0
      components/spotify/cspot/bell/external/alac/codec/alac.vcxproj
  42. 42 0
      components/spotify/cspot/bell/external/alac/codec/build.sh
  43. 381 0
      components/spotify/cspot/bell/external/alac/codec/dp_dec.c
  44. 386 0
      components/spotify/cspot/bell/external/alac/codec/dp_enc.c
  45. 61 0
      components/spotify/cspot/bell/external/alac/codec/dplib.h
  46. 390 0
      components/spotify/cspot/bell/external/alac/codec/matrix_dec.c
  47. 342 0
      components/spotify/cspot/bell/external/alac/codec/matrix_enc.c
  48. 80 0
      components/spotify/cspot/bell/external/alac/codec/matrixlib.h
  49. 20 0
      components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.sln
  50. 379 0
      components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.vcproj
  51. 362 0
      components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.xcodeproj/project.pbxproj
  52. 456 0
      components/spotify/cspot/bell/external/alac/convert-utility/CAFFileALAC.cpp
  53. 209 0
      components/spotify/cspot/bell/external/alac/convert-utility/CAFFileALAC.h
  54. 784 0
      components/spotify/cspot/bell/external/alac/convert-utility/main.cpp
  55. 202 0
      components/spotify/cspot/bell/external/alac/targets/include/ALACAudioTypes.h
  56. 65 0
      components/spotify/cspot/bell/external/alac/targets/include/ALACDecoder.h
  57. 92 0
      components/spotify/cspot/bell/external/alac/targets/include/ALACEncoder.h
  58. BIN
      components/spotify/cspot/bell/external/alac/targets/win32/x64/alac.lib
  59. BIN
      components/spotify/cspot/bell/external/alac/targets/win32/x86/alac.lib
  60. 0 0
      components/spotify/cspot/bell/external/cJSON/.editorconfig
  61. 0 0
      components/spotify/cspot/bell/external/cJSON/.gitattributes
  62. 0 0
      components/spotify/cspot/bell/external/cJSON/.github/CONTRIBUTING.md
  63. 0 0
      components/spotify/cspot/bell/external/cJSON/.github/workflows/CI.yml
  64. 0 0
      components/spotify/cspot/bell/external/cJSON/.gitignore
  65. 0 0
      components/spotify/cspot/bell/external/cJSON/.travis.yml
  66. 0 0
      components/spotify/cspot/bell/external/cJSON/CHANGELOG.md
  67. 10 23
      components/spotify/cspot/bell/external/cJSON/CMakeLists.txt
  68. 0 0
      components/spotify/cspot/bell/external/cJSON/CONTRIBUTORS.md
  69. 0 0
      components/spotify/cspot/bell/external/cJSON/LICENSE
  70. 0 0
      components/spotify/cspot/bell/external/cJSON/README.md
  71. 0 0
      components/spotify/cspot/bell/external/cJSON/appveyor.yml
  72. 7 16
      components/spotify/cspot/bell/external/cJSON/cJSON.c
  73. 0 7
      components/spotify/cspot/bell/external/cJSON/cJSON.h
  74. 0 0
      components/spotify/cspot/bell/external/cJSON/cJSON_Utils.c
  75. 0 0
      components/spotify/cspot/bell/external/cJSON/cJSON_Utils.h
  76. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/.gitignore
  77. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/CMakeLists.txt
  78. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/afl-prepare-linux.sh
  79. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/afl.c
  80. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/afl.sh
  81. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/cjson_read_fuzzer.c
  82. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/fuzz_main.c
  83. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test1
  84. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test10
  85. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test11
  86. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test2
  87. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3
  88. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.bu
  89. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.uf
  90. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.uu
  91. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test4
  92. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test5
  93. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test6
  94. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test7
  95. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test8
  96. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test9
  97. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/json.dict
  98. 0 0
      components/spotify/cspot/bell/external/cJSON/fuzzing/ossfuzz.sh
  99. 0 0
      components/spotify/cspot/bell/external/cJSON/library_config/cJSONConfig.cmake.in
  100. 0 0
      components/spotify/cspot/bell/external/cJSON/library_config/cJSONConfigVersion.cmake.in

+ 1 - 1
CMakeLists.txt

@@ -13,7 +13,7 @@ add_definitions(-DHIERARCHICAL_STATES=1)
 #add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG)
 #uncomment line below to get network status debug logs
 #add_definitions(-DNETWORK_STATUS_LOG_LEVEL=ESP_LOG_DEBUG)
-#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG) 
+#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG)
 #add_definitions(-DNETWORK_WIFI_LOG_LEVEL=ESP_LOG_DEBUG)
 #add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG)
 #add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG)

+ 4 - 2
components/spotify/CMakeLists.txt

@@ -3,18 +3,20 @@ set(CMAKE_CXX_STANDARD 17)
 
 idf_component_register(
 		SRC_DIRS . 
-		INCLUDE_DIRS . "cspot/include" "cspot/bell/include"
+		INCLUDE_DIRS . "cspot/include"
 		PRIV_REQUIRES mbedtls mdns nvs_flash platform_config services esp_http_server tools codecs
 		LDFRAGMENTS "linker.lf"
 )
 
+		#INCLUDE_DIRS . "cspot/include" "cspot/bell/include"
+
 add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
 
 set(BELL_DISABLE_CODECS ON)
 set(BELL_DISABLE_SINKS ON)
 set(CSPOT_TARGET_ESP32 ON)
 # becase CMake is so broken, the cache set below overrides a normal "set" for the first build
-set(BELL_EXTERNAL_TREMOR "idf::codecs" CACHE STRING "provide own codecs")
+set(BELL_EXTERNAL_VORBIS "idf::codecs" CACHE STRING "provide own codecs")
 set(BELL_EXTERNAL_CJSON "idf::json" CACHE STRING "provide own CJSON")
 
 add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cspot ${CMAKE_CURRENT_BINARY_DIR}/cspot)

+ 392 - 295
components/spotify/Shim.cpp

@@ -1,9 +1,37 @@
-/* 
+/*
  *  This software is released under the MIT License.
  *  https://opensource.org/licenses/MIT
  *
  */
 
+#include <string>
+#include <streambuf>
+#include <Session.h>
+#include <PlainConnection.h>
+#include <memory>
+#include <vector>
+#include <iostream>
+#include <inttypes.h>
+#include <fstream>
+#include <stdarg.h>
+#include <ApResolve.h>
+
+#include "MDNSService.h"
+#include "SpircHandler.h"
+#include "LoginBlob.h"
+#include "CentralAudioBuffer.h"
+#include "Logger.h"
+#include "Utils.h"
+
+#include "esp_http_server.h"
+#include "cspot_private.h"
+#include "cspot_sink.h"
+#include "platform_config.h"
+#include "tools.h"
+
+//#include "time.h"
+
+/*
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
@@ -30,184 +58,396 @@
 #include "tools.h"
 #include "cspot_private.h"
 #include "cspot_sink.h"
-#include "Shim.h"
+*/
 
-extern "C" {
-	httpd_handle_t get_http_server(int *port);
-	static esp_err_t handlerWrapper(httpd_req_t *req);
+static const char *TAG = "cspot";
+
+class cspotPlayer *player;
+
+/****************************************************************************************
+ * Chunk manager class (task)
+ */
+
+class chunkManager : public bell::Task {
+public:
+    std::atomic<bool> isRunning = true;
+    std::atomic<bool> isPaused = true;
+    chunkManager(std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer, std::function<void()> trackHandler, std::function<void(const uint8_t*, size_t)> audioHandler);
+    void teardown();
+
+private:
+    std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer;
+    std::function<void()> trackHandler;
+    std::function<void(const uint8_t*, size_t)> audioHandler;
+    std::mutex runningMutex;
+
+    void runTask() override;
 };
 
-#define CSPOT_STACK_SIZE (8*1024)
+chunkManager::chunkManager(std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer,
+                            std::function<void()> trackHandler, std::function<void(const uint8_t*, size_t)> audioHandler)
+    : bell::Task("player", 4 * 1024, 0, 0) {
+    this->centralAudioBuffer = centralAudioBuffer;
+    this->trackHandler = trackHandler;
+    this->audioHandler = audioHandler;
+    startTask();
+}
 
-static const char *TAG = "cspot";
+void chunkManager::runTask() {
+    std::scoped_lock lock(runningMutex);
+    size_t lastHash = 0;
 
-// using a global is pretty ugly, but it's easier with all Lambda below
-static EXT_RAM_ATTR struct cspot_s {
-	char name[32];
-	cspot_cmd_cb_t cHandler;
-	cspot_data_cb_t dHandler;
-	TaskHandle_t TaskHandle;
-    std::shared_ptr<LoginBlob> blob;
-} cspot;
+    while (isRunning) {
 
-std::shared_ptr<ConfigJSON> configMan;
-std::shared_ptr<NVSFile> file;
-std::shared_ptr<MercuryManager> mercuryManager;
-std::shared_ptr<SpircController> spircController;
+        if (isPaused) {
+            BELL_SLEEP_MS(100);
+            continue;
+        }
+
+        auto chunk = centralAudioBuffer->readChunk();
+
+        if (!chunk || chunk->pcmSize == 0) {
+            BELL_SLEEP_MS(50);
+            continue;
+        }
+
+        // receiving first chunk of new track from Spotify server
+        if (lastHash != chunk->trackHash) {
+            CSPOT_LOG(info, "hash update %x => %x", lastHash, chunk->trackHash);
+            lastHash = chunk->trackHash;
+            trackHandler();
+        }
+
+        audioHandler(chunk->pcmData, chunk->pcmSize);
+    }
+}
+
+void chunkManager::teardown() {
+    isRunning = false;
+    std::scoped_lock lock(runningMutex);
+}
 
 /****************************************************************************************
- * Main task (could it be deleted after spirc has started?)
+ * Player's main class  & task
  */
-static void cspotTask(void *pvParameters) {
-	char configName[] = "cspot_config";
-	std::string jsonConfig;	
-	
-    // Config file
-    file = std::make_shared<NVSFile>();
-	configMan = std::make_shared<ConfigJSON>(configName, file);
+
+class cspotPlayer : public bell::Task {
+private:
+    std::string name;
+    bool playback = false;
+    bell::WrappedSemaphore clientConnected;
+    std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer;
+
+    TimerHandle_t trackTimer;
+
+    int startOffset, volume = 0, bitrate = 160;
+    httpd_handle_t serverHandle;
+    int serverPort;
+    cspot_cmd_cb_t cmdHandler;
+	cspot_data_cb_t dataHandler;
+
+    std::shared_ptr<cspot::LoginBlob> blob;
+    std::unique_ptr<cspot::SpircHandler> spirc;
+    std::unique_ptr<chunkManager> chunker;
+
+    void eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event);
+    void trackHandler(void);
+
+    void runTask();
+
+public:
+    std::atomic<bool> trackNotify = false;
+
+    cspotPlayer(const char*, httpd_handle_t, int, cspot_cmd_cb_t, cspot_data_cb_t);
+    ~cspotPlayer();
+    esp_err_t handleGET(httpd_req_t *request);
+    esp_err_t handlePOST(httpd_req_t *request);
+};
+
+cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmdHandler, cspot_data_cb_t dataHandler) :
+                        bell::Task("playerInstance", 32 * 1024, 0, 0),
+                        serverHandle(server), serverPort(port),
+                        cmdHandler(cmdHandler), dataHandler(dataHandler) {
+                            
+    cJSON *item, *config = config_alloc_get_cjson("cspot_config");
+    if ((item = cJSON_GetObjectItem(config, "volume")) != NULL) volume = item->valueint;
+    if ((item = cJSON_GetObjectItem(config, "bitrate")) != NULL) bitrate = item->valueint;
+    if ((item = cJSON_GetObjectItem(config, "deviceName") ) != NULL) this->name = item->valuestring;
+    else this->name = name;
+    cJSON_Delete(config);
+    
+    if (bitrate != 96 && bitrate != 160 && bitrate != 320) bitrate = 160;
+}
+
+cspotPlayer::~cspotPlayer() {
+}
+
+extern "C" {
+    static esp_err_t handleGET(httpd_req_t *request) {
+        return player->handleGET(request);
+    }
+
+    static esp_err_t handlePOST(httpd_req_t *request) {
+        return player->handlePOST(request);
+    }
+
+    static void trackTimerHandler(TimerHandle_t xTimer) {
+        player->trackNotify = true;
+    }
+}
+
+esp_err_t cspotPlayer::handleGET(httpd_req_t *request) {
+    std::string body = this->blob->buildZeroconfInfo();
+
+    if (body.size() == 0) {
+        CSPOT_LOG(info, "cspot empty blob's body on GET");
+        return ESP_ERR_HTTPD_INVALID_REQ;
+    }
+
+    httpd_resp_set_hdr(request, "Content-type", "application/json");
+    httpd_resp_set_hdr(request, "Content-length", std::to_string(body.size()).c_str());
+    httpd_resp_send(request, body.c_str(), body.size());
+
+    return ESP_OK;
+}
+
+esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) {
+   cJSON* response= cJSON_CreateObject();
+
+   cJSON_AddNumberToObject(response, "status", 101);
+   cJSON_AddStringToObject(response, "statusString", "ERROR-OK");
+   cJSON_AddNumberToObject(response, "spotifyError", 0);
    
-	// We might have no config at all
-	if (!file->readFile(configName, jsonConfig) || !jsonConfig.length()) {
-		ESP_LOGW(TAG, "Cannot load config, using default");
-		
-		configMan->deviceName = cspot.name;
-		configMan->format = AudioFormat_OGG_VORBIS_160;
-		configMan->volume = 32767;
-
-		configMan->save();	
-	}
-	
-	// safely load config now
-	configMan->load();
-	if (!configMan->deviceName.length()) configMan->deviceName = cspot.name;
-	ESP_LOGI(TAG, "Started CSpot with %s (bitrate %d)", configMan->deviceName.c_str(), configMan->format == AudioFormat_OGG_VORBIS_320 ? 320 : (configMan->format == AudioFormat_OGG_VORBIS_160 ? 160 : 96));
-
-	// All we do here is notify the task to start the mercury loop
-    auto createPlayerCallback = [](std::shared_ptr<LoginBlob> blob) {
-		// TODO: handle/refuse that another user takes ownership
-		cspot.blob = blob;
-		xTaskNotifyGive(cspot.TaskHandle);
-    };
-
-	int port;
-	httpd_handle_t server = get_http_server(&port);
-	auto httpServer = std::make_shared<ShimHTTPServer>(server, port);
-
-    auto authenticator = std::make_shared<ZeroconfAuthenticator>(createPlayerCallback, httpServer);
-	authenticator->registerHandlers();
-
-	// wait to be notified and have a mercury loop
-	while (1) {
-		ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
-
-        auto session = std::make_unique<Session>();
-        session->connectWithRandomAp();
-        auto token = session->authenticate(cspot.blob);
-
-        ESP_LOGI(TAG, "Creating Spotify (using CSpot) player");
-		
-        // Auth successful
-        if (token.size() > 0 && cspot.cHandler(CSPOT_SETUP, 44100)) {
-			auto audioSink = std::make_shared<ShimAudioSink>();
-
-            mercuryManager = std::make_shared<MercuryManager>(std::move(session));
-            mercuryManager->startTask();
-
-            spircController = std::make_shared<SpircController>(mercuryManager, cspot.blob->username, audioSink);
-
-			spircController->setEventHandler([](CSpotEvent &event) {
-ESP_LOGI(TAG, "Getting Spotify event %d ", (int) event.eventType);				
-            switch (event.eventType) {
-            case CSpotEventType::TRACK_INFO: {
-                TrackInfo track = std::get<TrackInfo>(event.data);
-				cspot.cHandler(CSPOT_TRACK, 44100, track.duration, track.artist.c_str(), 
-							   track.album.c_str(), track.name.c_str(), track.imageUrl.c_str());
-                break;
-            }
-            case CSpotEventType::PLAY_PAUSE: {
-                bool isPaused = std::get<bool>(event.data);
-				if (isPaused) cspot.cHandler(CSPOT_PAUSE);
-				else cspot.cHandler(CSPOT_PLAY, false);
-                break;
-            }
-			case CSpotEventType::PLAYBACK_START:
-				cspot.cHandler(CSPOT_PLAY, (int) std::get<bool>(event.data));
-				break;
-			case CSpotEventType::LOAD:
-				cspot.cHandler(CSPOT_LOAD, std::get<int>(event.data), -1);
-				break;
-			case CSpotEventType::SEEK:
-				cspot.cHandler(CSPOT_SEEK, std::get<int>(event.data));
-				break;
-			case CSpotEventType::DISC:
-				cspot.cHandler(CSPOT_DISC);				
-				spircController->stopPlayer();
-				mercuryManager->stop();
-				break;
-			case CSpotEventType::PREV:
-			case CSpotEventType::NEXT:
-				cspot.cHandler(CSPOT_FLUSH);
-                break;
-			/*
-			// we use volume from sink which is a 16 bits value
-			case CSpotEventType::VOLUME: {
-                int volume = std::get<int>(event.data);
-				cspot.cHandler(CSPOT_VOLUME, volume);
-				ESP_LOGW(TAG, "cspot volume : %d", volume);
-                break;
-            }
-			*/
-            default:
-                break;
-            }
-			});
+    // get body if any (add '\0' at the end if used as string)
+	if (request->content_len) {
+		char* body = (char*) calloc(1, request->content_len + 1);
+		int size = httpd_req_recv(request, body, request->content_len);
+
+        // I know this is very crude and unsafe...
+        url_decode(body);
+        char *key = strtok(body, "&");
+
+        std::map<std::string, std::string> queryMap;
+
+        while (key) {
+            char *value = strchr(key, '=');
+            *value++ = '\0';
+            queryMap[key] = value;
+            key = strtok(NULL, "&");
+        };
+
+        free(body);
+
+        // Pass user's credentials to the blob and give the token
+        blob->loadZeroconfQuery(queryMap);
+        clientConnected.give();
+    }
+
+    char *responseStr = cJSON_PrintUnformatted(response);
+    cJSON_Delete(response);
+
+    esp_err_t rc = httpd_resp_send(request, responseStr, strlen(responseStr));
+    free(responseStr);
+    
+    return rc;
+}
+
+void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event) {
+    switch (event->eventType) {
+    case cspot::SpircHandler::EventType::PLAYBACK_START: {
+        centralAudioBuffer->clearBuffer();
+
+        // we are not playing anymore
+        xTimerStop(trackTimer, portMAX_DELAY);
+        trackNotify = false;
+        playback = false;
+
+        // memorize position for when track's beginning will be detected
+        startOffset = std::get<int>(event->data);
+
+        cmdHandler(CSPOT_START, 44100);
+        CSPOT_LOG(info, "start track <%s>", spirc->getTrackPlayer()->getCurrentTrackInfo().name.c_str());
+
+        // Spotify servers do not send volume at connection
+        spirc->setRemoteVolume(volume);
+        break;
+    }
+    case cspot::SpircHandler::EventType::PLAY_PAUSE: {
+        bool pause = std::get<bool>(event->data);
+        cmdHandler(pause ? CSPOT_PAUSE : CSPOT_PLAY);
+        chunker->isPaused = pause;
+        break;
+    }
+    case cspot::SpircHandler::EventType::TRACK_INFO: {
+        auto trackInfo = std::get<cspot::CDNTrackStream::TrackInfo>(event->data);
+        cmdHandler(CSPOT_TRACK, trackInfo.duration, startOffset, trackInfo.artist.c_str(),
+                       trackInfo.album.c_str(), trackInfo.name.c_str(), trackInfo.imageUrl.c_str());
+        spirc->updatePositionMs(startOffset);
+        startOffset = 0;
+        break;
+    }
+    case cspot::SpircHandler::EventType::NEXT:
+    case cspot::SpircHandler::EventType::PREV:
+    case cspot::SpircHandler::EventType::FLUSH: {
+        // FLUSH is sent when there is no next, just clean everything
+        centralAudioBuffer->clearBuffer();
+        cmdHandler(CSPOT_FLUSH);
+        break;
+    }
+    case cspot::SpircHandler::EventType::DISC:
+        centralAudioBuffer->clearBuffer();
+        xTimerStop(trackTimer, portMAX_DELAY);
+        cmdHandler(CSPOT_DISC);
+        chunker->teardown();
+        break;
+    case cspot::SpircHandler::EventType::SEEK: {
+        centralAudioBuffer->clearBuffer();
+        cmdHandler(CSPOT_SEEK, std::get<int>(event->data));
+        break;
+    }
+    case cspot::SpircHandler::EventType::DEPLETED:
+        CSPOT_LOG(info, "playlist ended, no track left to play");
+        break;
+    case cspot::SpircHandler::EventType::VOLUME:
+        volume = std::get<int>(event->data);
+        cmdHandler(CSPOT_VOLUME, volume);
+        break;
+    default:
+        break;
+    }
+}
+
+void cspotPlayer::trackHandler(void) {
+    if (playback) {
+        uint32_t remains;
+        auto trackInfo = spirc->getTrackPlayer()->getCurrentTrackInfo();
+        // if this is not first track, estimate when the current one will finish
+        cmdHandler(CSPOT_REMAINING, &remains);
+        if (remains > 100) xTimerChangePeriod(trackTimer, pdMS_TO_TICKS(remains), portMAX_DELAY);
+        else trackNotify = true;
+        CSPOT_LOG(info, "next track <%s> in cspot buffers, remaining %d ms", trackInfo.name.c_str(), remains);
+    } else {
+        trackNotify = true;
+        playback = true;
+    }  
+}
 
-			// need to make sure mercuryManager is running otherwise we'll loop and destroy instances
-			while (!mercuryManager->isRunning) vTaskDelay(pdMS_TO_TICKS(25));
-            mercuryManager->reconnectedCallback = []() {
-                return spircController->subscribe();
-            };
+void cspotPlayer::runTask() {
+    httpd_uri_t request = {
+		.uri = "/spotify_info",
+		.method = HTTP_GET,
+		.handler = ::handleGET,
+		.user_ctx = NULL,
+	};
 
-            mercuryManager->handleQueue();
+    // register GET and POST handler for built-in server
+    httpd_register_uri_handler(serverHandle, &request);
+    request.method = HTTP_POST;
+    request.handler = ::handlePOST;
+    httpd_register_uri_handler(serverHandle, &request);
+
+    // construct blob for that player
+    blob = std::make_unique<cspot::LoginBlob>(name);
+
+    // Register mdns service, for spotify to find us
+    bell::MDNSService::registerService( blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort,
+            { {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} });
+                            
+                                static int count = 0;
+    // gone with the wind...
+    while (1) {
+        clientConnected.wait();
+
+        CSPOT_LOG(info, "Spotify client connected for %s", name.c_str());
         
-			// release controllers
-			mercuryManager.reset();
-			spircController.reset();
-		}
+        centralAudioBuffer = std::make_shared<bell::CentralAudioBuffer>(32);        
+        auto ctx = cspot::Context::createFromBlob(blob);
+             
+        if (bitrate == 320) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_320;
+        else if (bitrate == 96) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_96;
+        else ctx->config.audioFormat = AudioFormat_OGG_VORBIS_160;            
 
-		// release auth blob and flush files
-		cspot.blob.reset();
-		file->flush();
+        ctx->session->connectWithRandomAp();
+        auto token = ctx->session->authenticate(blob);      
 
-		ESP_LOGI(TAG, "Shutting down CSpot player");
-	}
+        // Auth successful
+        if (token.size() > 0) {
+            trackTimer = xTimerCreate("trackTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, trackTimerHandler);
+            spirc = std::make_unique<cspot::SpircHandler>(ctx);
+
+            // set call back to calculate a hash on trackId
+            spirc->getTrackPlayer()->setDataCallback(
+                [this](uint8_t* data, size_t bytes, std::string_view trackId, size_t sequence) {
+                    return centralAudioBuffer->writePCM(data, bytes, sequence);
+            });
+
+            // set event (PLAY, VOLUME...) handler
+            spirc->setEventHandler(
+                [this](std::unique_ptr<cspot::SpircHandler::Event> event) {
+                    eventHandler(std::move(event));
+            });
+
+            // Start handling mercury messages
+            ctx->session->startTask();
+
+            // Create a player, pass the tack handler
+            chunker = std::make_unique<chunkManager>(centralAudioBuffer,
+                [this](void) {
+                    return trackHandler();
+                },
+                [this](const uint8_t* data, size_t bytes) {
+                    return dataHandler(data, bytes);
+             });
+
+            // exit when player has stopped (received a DISC)
+            while (chunker->isRunning) {
+                ctx->session->handlePacket();
+
+                // inform Spotify that next track has started (don't need to be super accurate)
+                if (trackNotify) {
+                    CSPOT_LOG(info, "next track's audio has reached DAC");
+                    spirc->notifyAudioReachedPlayback();
+                    trackNotify = false;
+                }
+            }
 
-	// we should not be here
-	vTaskDelete(NULL);
+            xTimerDelete(trackTimer, portMAX_DELAY);
+            spirc->disconnect();
+                       
+            CSPOT_LOG(info, "disconnecting player %s", name.c_str());
+        }
+        
+        // we want to release memory ASAP and fore sure
+        centralAudioBuffer.reset();
+        ctx.reset();
+        token.clear();
+
+        // update volume when we disconnect
+        cJSON *item, *config = config_alloc_get_cjson("cspot_config");
+        cJSON_DeleteItemFromObject(config, "volume");
+        cJSON_AddNumberToObject(config, "volume", volume);
+        config_set_cjson_str_and_free("cspot_config", config);
+    }
 }
 
 /****************************************************************************************
  * API to create and start a cspot instance
  */
-struct cspot_s* cspot_create(const char *name, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) {
-	static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
-	static EXT_RAM_ATTR StackType_t xStack[CSPOT_STACK_SIZE] __attribute__ ((aligned (4)));
-
+ 
+struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) {
 	bell::setDefaultLogger();
-	
-	cspot.cHandler = cmd_cb;
-	cspot.dHandler = data_cb;
-	strncpy(cspot.name, name, sizeof(cspot.name) - 1);
-    cspot.TaskHandle = xTaskCreateStatic(&cspotTask, "cspot", CSPOT_STACK_SIZE, NULL, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT - 2, xStack, &xTaskBuffer);
-	
-	return &cspot;
+    player = new cspotPlayer(name, server, port, cmd_cb, data_cb);
+    player->startTask();
+	return (cspot_s*) player;
 }
 
 /****************************************************************************************
  * Commands sent by local buttons/actions
  */
+ 
 bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) {
-	// we might have not controller left
+	// we might have no controller left
+/*
 	if (!spircController.use_count()) return false;
 
 	switch(event) {
@@ -241,150 +481,7 @@ bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) {
 		default:
 			break;
 	}
+*/
 
 	return true;
 }
-
-/****************************************************************************************
- * AudioSink class to push data to squeezelite backend (decode_external)
- */
-void ShimAudioSink::volumeChanged(uint16_t volume) {
-	cspot.cHandler(CSPOT_VOLUME, volume);
-}
-
-void ShimAudioSink::feedPCMFrames(const uint8_t *data, size_t bytes) {	
-	cspot.dHandler(data, bytes);
-}
-
-/****************************************************************************************
- * NVSFile class to store config
- */
-bool NVSFile::readFile(std::string filename, std::string &fileContent) {
-	auto search = files.find(filename);
-    
-	// cache 
-	if (search == files.end()) {
-		char *content = (char*) config_alloc_get(NVS_TYPE_STR, filename.c_str());
-		if (!content) return false;
-		fileContent = content;
-		free(content);
-	} else {
-		fileContent = search->second;
-	}
-
-	return true;
-}
-
-bool NVSFile::writeFile(std::string filename, std::string fileContent) {
-    auto search = files.find(filename);
-
-	files[filename] = fileContent;    
-	if (search == files.end()) return (ESP_OK == config_set_value(NVS_TYPE_STR, filename.c_str(), fileContent.c_str()));
-	return true;
-}
-
-bool NVSFile::flush() {
-	esp_err_t err = ESP_OK;
-
-	for (auto it = files.begin(); it != files.end(); ++it) {
-		err |= config_set_value(NVS_TYPE_STR, it->first.c_str(), it->second.c_str());
-	}
-	return (err == ESP_OK);
-}
-
-/****************************************************************************************
- * Shim HTTP server for spirc
- */
-static esp_err_t handlerWrapper(httpd_req_t *req) {
-	std::unique_ptr<bell::HTTPRequest> request = std::make_unique<bell::HTTPRequest>();
-	char *query = NULL, *body = NULL;
-	bell::httpHandler *handler = (bell::httpHandler*) req->user_ctx;
-	size_t query_len = httpd_req_get_url_query_len(req);
-
-	request->connection = httpd_req_to_sockfd(req);
-
-	// get body if any (add '\0' at the end if used as string)
-	if (req->content_len) {
-		body = (char*) calloc(1, req->content_len + 1);
-		int size = httpd_req_recv(req, body, req->content_len);
-		request->body = body;
-		ESP_LOGD(TAG,"wrapper received body %d/%d", size, req->content_len);
-	}
-
-	// parse query if any (can be in body as well for url-encoded)
-	if (query_len) {
-		query = (char*) malloc(query_len + 1);
-		httpd_req_get_url_query_str(req, query, query_len + 1);
-	} else if (body && strchr(body, '&')) {
-		query = body;
-		body = NULL;
-	}	
-		
-	// I know this is very crude and unsafe...
-	url_decode(query);
-	char *key = strtok(query, "&");
-
-	while (key) {
-		char *value = strchr(key, '=');
-		*value++ = '\0';
-		request->queryParams[key] = value;
-		ESP_LOGD(TAG,"wrapper received key:%s value:%s", key, value);
-		key = strtok(NULL, "&");
-	};
-
-	if (query) free(query);
-	if (body) free(body);
-	
-	/*
-	 This is a strange construct as the C++ handler will call the ShimHTTPSer::respond 
-	 and then we'll return. So we can't obtain the response to be sent, as esp_http_server
-	 normally expects, instead respond() will use raw socket and close connection
-	*/
-	(*handler)(std::move(request));
-
-	return ESP_OK;
-}
-
-void ShimHTTPServer::registerHandler(bell::RequestType requestType, const std::string &routeUrl, bell::httpHandler handler, bool readDataToStr) {
-	httpd_uri_t request = { 
-		.uri = routeUrl.c_str(), 
-		.method = (requestType == bell::RequestType::GET ? HTTP_GET : HTTP_POST),
-		.handler = handlerWrapper,
-		.user_ctx = NULL,
-	};
-
-	// find the first free spot and register handler
-	for (int i = 0; i < sizeof(uriHandlers)/sizeof(bell::httpHandler); i++) {
-		if (!uriHandlers[i]) {
-			uriHandlers[i] = handler;
-			request.user_ctx = uriHandlers + i;
-			httpd_register_uri_handler(serverHandle, &request);
-			break;	
-		}
-	}
-		
-	if (!request.user_ctx) ESP_LOGW(TAG, "Cannot add handler for %s", routeUrl.c_str());
-}
-
-void ShimHTTPServer::respond(const bell::HTTPResponse &response) {
-	char *buf;
-	size_t len = asprintf(&buf, "HTTP/1.1 %d OK\r\n"
-			"Server: SQUEEZEESP32\r\n"
-			"Connection: close\r\n"		
-			"Content-type: %s\r\n"		
-			"Content-length: %d\r\n"	
-			"Access-Control-Allow-Origin: *\r\n"
-			"Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS\r\n"
-			"Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token\r\n"
-			"\r\n%s", 
-			response.status, response.contentType.c_str(), 
-			response.body.size(), response.body.c_str()
-	);
-
-	// use raw socket send and close connection
-	httpd_socket_send(serverHandle, response.connectionFd, buf, len, 0);
-	free(buf);
-	
-	// we want to close the socket due to the strange construct
-	httpd_sess_trigger_close(serverHandle, response.connectionFd);
-}

+ 0 - 49
components/spotify/Shim.h

@@ -1,49 +0,0 @@
-/* 
- *  This software is released under the MIT License.
- *  https://opensource.org/licenses/MIT
- *
- */
-
-#pragma once
-
-#include <vector>
-#include <iostream>
-#include <map>
-#include "AudioSink.h"
-#include "FileHelper.h"
-#include "BaseHTTPServer.h"
-#include <stdio.h>
-#include <string.h>
-#include <sys/unistd.h>
-#include <sys/stat.h>
-#include "esp_err.h"
-#include "esp_http_server.h"
-#include "esp_log.h"
-
-class ShimAudioSink : public AudioSink {
-public:
-	ShimAudioSink(void) { softwareVolumeControl = false; }
-    void feedPCMFrames(const uint8_t *data, size_t bytes);
-	virtual void volumeChanged(uint16_t volume);
-};
-
-class NVSFile : public FileHelper {
-private:
-	std::map<std::string, std::string> files;
-
-public:
-    bool readFile(std::string filename, std::string &fileContent);
-    bool writeFile(std::string filename, std::string fileContent);
-	bool flush();
-};
-
-class ShimHTTPServer : public bell::BaseHTTPServer {    
-private:
-	httpd_handle_t serverHandle;
-	bell::httpHandler uriHandlers[4];
-	
-public:
-   ShimHTTPServer(httpd_handle_t server, int port) { serverHandle = server; serverPort = port; }
-   void registerHandler(bell::RequestType requestType, const std::string &, bell::httpHandler, bool readDataToStr = false);
-   void respond(const bell::HTTPResponse &);
-};

+ 0 - 17
components/spotify/cspot/CMakeLists.txt

@@ -16,11 +16,6 @@ endif()
 # Main library sources
 file(GLOB SOURCES "src/*.cpp" "src/*.c")
 
-if(WIN32)
-    list(APPEND SOURCES "mdnssvc/mdns.c" "mdnssvc/mdnsd.c")
-    list(APPEND EXTRA_INCLUDES "mdnssvc")
-endif()	
-
 # Use externally specified bell library or the submodule
 if(CSPOT_EXTERNAL_BELL)
     list(APPEND EXTRA_LIBS ${CSPOT_EXTERNAL_BELL})
@@ -29,24 +24,12 @@ else()
     list(APPEND EXTRA_LIBS bell)
 endif()
 
-# Add Apple Bonjour compatibility library for Linux
-if(UNIX AND NOT APPLE)
-    list(APPEND EXTRA_LIBS dns_sd)
-    # TODO: migrate from this to native linux mDNS
-endif()
-
 # Build protobuf code
-if(1)
 set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
 file(GLOB PROTOS protobuf/*.proto)
 nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
 add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
 set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRUE)
-else()
-list(APPEND SOURCES "protobuf/authentication.pb.c" "protobuf/keyexchange.pb.c" "protobuf/mercury.pb.c" "protobuf/metadata.pb.c" "protobuf/spirc.pb.c")
-list(APPEND EXTRA_INCLUDES ".")
-message(WARNING "NOT GENERATING PROTOBUF")
-endif()
 
 add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
 # PUBLIC to propagate includes from bell to cspot dependents

+ 3 - 0
components/spotify/cspot/README.md

@@ -0,0 +1,3 @@
+# Base CSpot library
+
+CSpot Spotify-Connect receiver library further integrated in ../targets/

+ 2 - 0
components/spotify/cspot/bell/.clangd

@@ -0,0 +1,2 @@
+CompileFlags:
+   CompilationDatabase: example/build      # Search build/ directory for compile_commands.json

+ 52 - 0
components/spotify/cspot/bell/.github/workflows/c-cpp.yml

@@ -0,0 +1,52 @@
+name: C/C++ CI
+
+on: [push, pull_request]
+
+jobs:
+  build:
+    strategy:
+        matrix:
+          os: [macos-latest, ubuntu-latest]
+        fail-fast: false
+    runs-on:  ${{ matrix.os }}
+    steps:
+    - uses: actions/checkout@v2
+      with:
+        submodules: recursive
+        
+    - name: Install Protoc
+      uses: arduino/setup-protoc@v1
+      with:
+        repo-token: ${{ secrets.GITHUB_TOKEN }} # https://github.com/arduino/setup-protoc/issues/6
+        
+    - name: Setup cmake
+      uses: jwlawson/actions-setup-cmake@v1.4
+      with:
+        cmake-version: '3.18.x'
+
+    - name: Install avachi libraries (mDNS), mbedtls and asound
+      run: sudo apt-get install libavahi-compat-libdnssd-dev libasound2-dev libmbedtls-dev
+      if: ${{ matrix.os == 'ubuntu-latest' }}
+      
+    - name: Install openssl on macos
+      run: |
+        brew install mbedtls@3
+        brew link --force mbedtls@3
+        brew install portaudio
+        brew link --force portaudio
+        export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/Cellar/portaudio/19.6.0/lib/pkgconfig"
+        pkg-config --modversion portaudio-2.0
+        echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV
+      if: ${{ matrix.os == 'macos-latest' }}
+      
+    - name: Install python dependencies
+      run: python3 -m pip install --upgrade pip setuptools wheel
+      
+    - name: Install grpcio-tools
+      run: sudo pip3 install grpcio-tools
+      
+    - name: cmake
+      run: mkdir -p build && cd build && cmake ..
+      
+    - name: make
+      run: cd build && make

+ 2 - 1
components/spotify/cspot/bell/.gitignore

@@ -22,7 +22,6 @@
 *.pch
 
 # Libraries
-*.lib
 *.a
 *.la
 *.lo
@@ -124,3 +123,5 @@ Temporary Items
 # End of https://www.toptal.com/developers/gitignore/api/c,c++,cmake,macos
 
 build/
+__history/
+*.bak

+ 9 - 10
components/spotify/cspot/bell/.gitmodules

@@ -1,10 +1,9 @@
-[submodule "tremor"]
-	path = tremor
-	url = https://gitlab.xiph.org/xiph/tremor.git
-	branch = lowmem
-[submodule "cJSON"]
-	path = cJSON
-	url = https://github.com/DaveGamble/cJSON
-[submodule "nanopb"]
-	path = nanopb
-	url = https://github.com/nanopb/nanopb
+[submodule "external/lws"]
+	path = external/lws
+	url = https://github.com/warmcat/libwebsockets
+[submodule "external/nlohmann_json"]
+	path = external/nlohmann_json
+	url = https://github.com/nlohmann/json
+[submodule "external/mdnssvc"]
+	path = external/mdnssvc
+	url = https://github.com/philippe44/mdnssvc

+ 65 - 0
components/spotify/cspot/bell/.vscode/settings.json

@@ -0,0 +1,65 @@
+{
+    "files.associations": {
+        "array": "cpp",
+        "atomic": "cpp",
+        "bit": "cpp",
+        "*.tcc": "cpp",
+        "bitset": "cpp",
+        "cctype": "cpp",
+        "chrono": "cpp",
+        "clocale": "cpp",
+        "cmath": "cpp",
+        "compare": "cpp",
+        "concepts": "cpp",
+        "condition_variable": "cpp",
+        "cstdarg": "cpp",
+        "cstddef": "cpp",
+        "cstdint": "cpp",
+        "cstdio": "cpp",
+        "cstdlib": "cpp",
+        "cstring": "cpp",
+        "ctime": "cpp",
+        "cwchar": "cpp",
+        "cwctype": "cpp",
+        "deque": "cpp",
+        "map": "cpp",
+        "set": "cpp",
+        "string": "cpp",
+        "unordered_map": "cpp",
+        "vector": "cpp",
+        "exception": "cpp",
+        "algorithm": "cpp",
+        "functional": "cpp",
+        "iterator": "cpp",
+        "memory": "cpp",
+        "memory_resource": "cpp",
+        "numeric": "cpp",
+        "optional": "cpp",
+        "random": "cpp",
+        "ratio": "cpp",
+        "regex": "cpp",
+        "string_view": "cpp",
+        "system_error": "cpp",
+        "tuple": "cpp",
+        "type_traits": "cpp",
+        "utility": "cpp",
+        "fstream": "cpp",
+        "initializer_list": "cpp",
+        "iosfwd": "cpp",
+        "iostream": "cpp",
+        "istream": "cpp",
+        "limits": "cpp",
+        "mutex": "cpp",
+        "new": "cpp",
+        "numbers": "cpp",
+        "ostream": "cpp",
+        "semaphore": "cpp",
+        "sstream": "cpp",
+        "stdexcept": "cpp",
+        "stop_token": "cpp",
+        "streambuf": "cpp",
+        "thread": "cpp",
+        "typeinfo": "cpp",
+        "cinttypes": "cpp"
+    }
+}

+ 153 - 100
components/spotify/cspot/bell/CMakeLists.txt

@@ -11,23 +11,24 @@ option(BELL_CODEC_VORBIS "Support tremor Vorbis codec" ON)
 option(BELL_CODEC_ALAC "Support Apple ALAC codec" ON)
 option(BELL_CODEC_OPUS "Support Opus codec" ON)
 option(BELL_DISABLE_SINKS "Disable all built-in audio sink implementations" OFF)
+
 # These are default OFF, as they're OS-dependent (ESP32 sinks are always enabled - no external deps)
 option(BELL_SINK_ALSA "Enable ALSA audio sink" OFF)
 option(BELL_SINK_PORTAUDIO "Enable PortAudio sink" OFF)
+
 # cJSON wrapper
 option(BELL_DISABLE_CJSON "Disable cJSON and JSONObject completely" OFF)
 set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional")
 
-if(BELL_EXTERNAL_MBEDTLS)
-    set(MbedTLS_DIR ${BELL_EXTERNAL_MBEDTLS})
-    message(STATUS "Setting local mbedtls ${MbedTLS_DIR}")
-endif()
+# disable json tests
+set(JSON_BuildTests OFF CACHE INTERNAL "")
 
 # Backwards compatibility with deprecated options
 if(BELL_USE_ALSA)
     message(WARNING "Deprecated Bell options used, replace BELL_USE_ALSA with BELL_SINK_ALSA")
     set(BELL_SINK_ALSA ${BELL_USE_ALSA})
 endif()
+
 if(BELL_USE_PORTAUDIO)
     message(WARNING "Deprecated Bell options used, replace BELL_USE_PORTAUDIO with BELL_SINK_PORTAUDIO")
     set(BELL_SINK_PORTAUDIO ${BELL_USE_PORTAUDIO})
@@ -35,6 +36,7 @@ endif()
 
 message(STATUS "Bell options:")
 message(STATUS "    Disable all codecs: ${BELL_DISABLE_CODECS}")
+
 if(NOT BELL_DISABLE_CODECS)
     message(STATUS "    - AAC audio codec: ${BELL_CODEC_AAC}")
     message(STATUS "    - MP3 audio codec: ${BELL_CODEC_MP3}")
@@ -42,51 +44,74 @@ if(NOT BELL_DISABLE_CODECS)
     message(STATUS "    - Opus audio codec: ${BELL_CODEC_OPUS}")
     message(STATUS "    - ALAC audio codec: ${BELL_CODEC_ALAC}")
 endif()
+
 message(STATUS "    Disable built-in audio sinks: ${BELL_DISABLE_SINKS}")
+
 if(NOT BELL_DISABLE_SINKS)
     message(STATUS "    - ALSA sink: ${BELL_SINK_ALSA}")
     message(STATUS "    - PortAudio sink: ${BELL_SINK_PORTAUDIO}")
 endif()
+
 message(STATUS "    Disable cJSON and JSONObject: ${BELL_DISABLE_CJSON}")
 
 # Include nanoPB library
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra")
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb/extra")
 find_package(Nanopb REQUIRED)
+message(${NANOPB_INCLUDE_DIRS})
 list(APPEND EXTRA_INCLUDES ${NANOPB_INCLUDE_DIRS})
 
 # CMake options
 set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED 20)
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-set(AUDIO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/audio")
+
+set(AUDIO_CODEC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-codec")
+set(AUDIO_CONTAINERS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-containers")
+set(AUDIO_DSP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-dsp")
+set(AUDIO_SINKS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-sinks")
+set(IO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/io")
+set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/platform")
+set(UTILITIES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/utilities")
+
 add_definitions("-DUSE_DEFAULT_STDLIB=1")
 
 # Main library sources
-file(GLOB SOURCES "src/*.cpp" "src/*.c" "nanopb/*.c")
-list(APPEND EXTRA_INCLUDES "include/platform")
-list(APPEND EXTRA_INCLUDES "include/audio/container")
+file(GLOB SOURCES
+    "external/nanopb/*.c"
+    "main/utilities/*.cpp" "main/utilities/*.c"
+    "main/io/*.cpp" "main/io/*.c"
+)
+
+list(REMOVE_ITEM SOURCES "${IO_DIR}/BellTar.cpp" "${IO_DIR}/BellHTTPServer.cpp")
+
+list(APPEND EXTRA_INCLUDES "main/audio-codec/include")
+list(APPEND EXTRA_INCLUDES "main/audio-dsp/include")
+list(APPEND EXTRA_INCLUDES "main/audio-sinks/include")
+list(APPEND EXTRA_INCLUDES "main/io/include")
+list(APPEND EXTRA_INCLUDES "main/utilities/include")
+list(APPEND EXTRA_INCLUDES "main/platform")
 
 # Add platform specific sources
 if(ESP_PLATFORM)
-    file(GLOB ESP_PLATFORM_SOURCES "src/platform/esp/*.cpp" "src/platform/esp/*.c" "src/asm/biquad_f32_ae32.S")
+    file(GLOB ESP_PLATFORM_SOURCES "main/platform/esp/*.cpp" "main/platform/esp/*.c" "main/asm/biquad_f32_ae32.S")
     list(APPEND SOURCES ${ESP_PLATFORM_SOURCES})
 endif()
-if(UNIX)
-    file(GLOB UNIX_PLATFORM_SOURCES "src/platform/unix/*.cpp" "src/platform/unix/*.c")
-    list(APPEND SOURCES ${UNIX_PLATFORM_SOURCES})
-endif()
+
 if(APPLE)
-    file(GLOB APPLE_PLATFORM_SOURCES "src/platform/apple/*.cpp" "src/platform/apple/*.c")
+    file(GLOB APPLE_PLATFORM_SOURCES "main/platform/apple/*.cpp" "main/platform/apple/*.c")
     list(APPEND SOURCES ${APPLE_PLATFORM_SOURCES})
     list(APPEND EXTRA_INCLUDES "/usr/local/opt/mbedtls@3/include")
 endif()
+
 if(UNIX AND NOT APPLE)
-    file(GLOB LINUX_PLATFORM_SOURCES "src/platform/linux/*.cpp" "src/platform/linux/*.c")
+    file(GLOB LINUX_PLATFORM_SOURCES "main/platform/linux/*.cpp" "main/platform/linux/*.c")
     list(APPEND SOURCES ${LINUX_PLATFORM_SOURCES})
 endif()
+
 if(WIN32)
-    file(GLOB WIN32_PLATFORM_SOURCES "src/platform/win32/*.cpp" "src/platform/win32/*.c")
+    file(GLOB WIN32_PLATFORM_SOURCES "main/platform/win32/*.cpp" "main/platform/win32/*.c")
     list(APPEND SOURCES ${WIN32_PLATFORM_SOURCES})
-    list(APPEND EXTRA_INCLUDES "include/platform/win32")    
+    list(APPEND EXTRA_INCLUDES "main/platform/win32")
 endif()
 
 # A hack to make Opus keep quiet
@@ -96,90 +121,75 @@ function(message)
     endif()
 endfunction()
 
+
 if(ESP_PLATFORM)
-    list(APPEND EXTRA_LIBS idf::mbedtls idf::pthread idf::mdns)
-    add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
+    list(APPEND EXTRA_LIBS idf::mdns idf::mbedtls idf::pthread idf::driver idf::lwip)
+    add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation -Wno-stringop-overflow -Wno-error=format -Wno-format -Wno-stringop-overread -Wno-stringop-overflow)
 else()
     find_package(Threads REQUIRED)
-    set(THREADS_PREFER_PTHREAD_FLAG ON)
-    list(APPEND EXTRA_LIBS Threads::Threads)
-    
     find_package(MbedTLS REQUIRED)
-    get_target_property(MBEDTLS_INFO MbedTLS::mbedtls INTERFACE_INCLUDE_DIRECTORIES)
-    list(APPEND EXTRA_INCLUDES ${MBEDTLS_INFO})
-
-    # try to handle mbedtls when not system-wide installed      
-    if(BELL_EXTERNAL_MBEDTLS)
-        if(MSVC)
-            set(MBEDTLS_RELEASE "RELEASE" CACHE STRING "local mbedtls version")
-        else()
-            set(MBEDTLS_RELEASE "NOCONFIG" CACHE STRING "local mbedtls version")
-        endif()
-        message(STATUS "using local mbedtls version ${MBEDTLS_RELEASE}")        
-        get_target_property(MBEDTLS_INFO MbedTLS::mbedtls IMPORTED_LOCATION_${MBEDTLS_RELEASE})
-        list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
-        get_target_property(MBEDTLS_INFO MbedTLS::mbedx509 IMPORTED_LOCATION_${MBEDTLS_RELEASE})
-        list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
-        get_target_property(MBEDTLS_INFO MbedTLS::mbedcrypto IMPORTED_LOCATION_${MBEDTLS_RELEASE})
-        list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
-    else()  
-        list(APPEND EXTRA_LIBS mbedtls mbedcrypto mbedx509)
-    endif() 
-    
+    list(APPEND EXTRA_INCLUDES ${MBEDTLS_INCLUDE_DIRS})
+    set(THREADS_PREFER_PTHREAD_FLAG ON)
+    list(APPEND EXTRA_LIBS ${MBEDTLS_LIBRARIES} Threads::Threads)
+
     if(MSVC)
-        add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
+        add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS _USE_MATH_DEFINES)
         add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142)
-    endif() 
+    endif()
 endif()
 
 if(NOT BELL_DISABLE_CODECS)
-	file(GLOB EXTRA_SOURCES "src/audio/container/*.cpp")
-	list(APPEND SOURCES "${EXTRA_SOURCES}")
-    list(APPEND SOURCES "${AUDIO_DIR}/codec/DecoderGlobals.cpp")
-    list(APPEND SOURCES "${AUDIO_DIR}/codec/BaseCodec.cpp")
-    list(APPEND SOURCES "${AUDIO_DIR}/codec/AudioCodecs.cpp")
-    list(APPEND EXTRA_INCLUDES "include/audio/codec")
+    file(GLOB EXTRA_SOURCES "main/audio-containers/*.cpp" "main/audio-codec/*.cpp" "main/audio-codec/*.c" "main/audio-dsp/*.cpp" "main/audio-dsp/*.c")
+
+    list(APPEND SOURCES "${EXTRA_SOURCES}")
+    list(APPEND SOURCES "${AUDIO_CODEC_DIR}/DecoderGlobals.cpp")
+    list(APPEND SOURCES "${AUDIO_CODEC_DIR}/BaseCodec.cpp")
+    list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AudioCodecs.cpp")
+    list(APPEND EXTRA_INCLUDES "main/audio-containers/include")
+
     # AAC-LC codec
     if(BELL_CODEC_AAC)
-        file(GLOB LIBHELIX_AAC_SOURCES "libhelix-aac/*.c")
+        file(GLOB LIBHELIX_AAC_SOURCES "external/libhelix-aac/*.c")
         list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES})
-        list(APPEND EXTRA_INCLUDES "libhelix-aac")
-        list(APPEND SOURCES "${AUDIO_DIR}/codec/AACDecoder.cpp")
+        list(APPEND EXTRA_INCLUDES "external/libhelix-aac")
+        list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AACDecoder.cpp")
         list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC")
     endif()
+
     # MP3 codec
     if(BELL_CODEC_MP3)
-        file(GLOB LIBHELIX_MP3_SOURCES "libhelix-mp3/*.c")
+        file(GLOB LIBHELIX_MP3_SOURCES "external/libhelix-mp3/*.c")
         list(APPEND LIBHELIX_SOURCES ${LIBHELIX_MP3_SOURCES})
-        list(APPEND EXTRA_INCLUDES "libhelix-mp3")
-        list(APPEND SOURCES "${AUDIO_DIR}/codec/MP3Decoder.cpp")
+        list(APPEND EXTRA_INCLUDES "external/libhelix-mp3")
+        list(APPEND SOURCES "${AUDIO_CODEC_DIR}/MP3Decoder.cpp")
         list(APPEND CODEC_FLAGS "-DBELL_CODEC_MP3")
     endif()
 
     # MP3 codec
-    if(BELL_CODEC_ALAC)
-        file(GLOB ALAC_SOURCES "alac/*.c" "alac/*.cpp")
-        list(APPEND ALAC_SOURCES ${ALAC_SOURCES})
-        list(APPEND EXTRA_INCLUDES "alac")
-        # list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp")
-        list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC")
-    endif()
+    # if(BELL_CODEC_ALAC)
+    #     file(GLOB ALAC_SOURCES "external/alac/*.c" "external/alac/*.cpp")
+    #     list(APPEND ALAC_SOURCES ${ALAC_SOURCES})
+    #     list(APPEND EXTRA_INCLUDES "external/alac")
+
+    #     # list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp")
+    #     list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC")
+    # endif()
+
     # libhelix Cygwin workaround
     if(CYGWIN)
         # Both Cygwin and ESP are Unix-like so this seems to work (or, at least, compile)
-        set_source_files_properties("${AUDIO_DIR}/codec/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM")
+        set_source_files_properties("${AUDIO_CODEC_DIR}/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM")
     endif()
+
     list(APPEND SOURCES ${LIBHELIX_SOURCES})
     list(APPEND SOURCES ${ALAC_SOURCES})
+
     # Vorbis codec
     if(BELL_CODEC_VORBIS)
-        file(GLOB TREMOR_SOURCES "tremor/*.c")
-        list(REMOVE_ITEM TREMOR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tremor/ivorbisfile_example.c")
-        list(APPEND SOURCES ${TREMOR_SOURCES})
-        list(APPEND EXTRA_INCLUDES "tremor")
-        list(APPEND SOURCES "${AUDIO_DIR}/codec/VorbisDecoder.cpp")
+        list(APPEND SOURCES "${AUDIO_CODEC_DIR}/VorbisDecoder.cpp")
         list(APPEND CODEC_FLAGS "-DBELL_CODEC_VORBIS")
-    endif()
+    endif() 
+    
     # Opus codec
     if(BELL_CODEC_OPUS)
         set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF CACHE BOOL "")
@@ -187,72 +197,115 @@ if(NOT BELL_DISABLE_CODECS)
         set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF CACHE BOOL "")
         set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
         set(MESSAGE_QUIET ON)
-        add_subdirectory("opus")
+        add_subdirectory("external/opus")
         unset(MESSAGE_QUIET)
         target_compile_options(opus PRIVATE "-O3")
         list(APPEND EXTRA_LIBS Opus::opus)
-        list(APPEND SOURCES "${AUDIO_DIR}/codec/OPUSDecoder.cpp")
+        list(APPEND SOURCES "${AUDIO_CODEC_DIR}/OPUSDecoder.cpp")
         list(APPEND CODEC_FLAGS -DBELL_CODEC_OPUS)
     endif()
+    
     # Enable global codecs
     string(REPLACE ";" " " CODEC_FLAGS "${CODEC_FLAGS}")
-    set_source_files_properties("${AUDIO_DIR}/codec/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}")
-elseif(BELL_EXTERNAL_TREMOR) 	
-    list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_TREMOR})
+    set_source_files_properties("${AUDIO_CODEC_DIR}/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}")
+else()  
+    list(REMOVE_ITEM SOURCES "${IO_DIR}/EncodedAudioStream.cpp")
+endif() 
+
+if(BELL_EXTERNAL_VORBIS)
+    message(STATUS "Using external Vorbis codec ${BELL_EXTERNAL_VORBIS}")
+    list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_VORBIS})
+else()  
+    file(GLOB TREMOR_SOURCES "external/tremor/*.c")
+    list(REMOVE_ITEM TREMOR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/tremor/ivorbisfile_example.c")
+    list(APPEND SOURCES ${TREMOR_SOURCES})
+    list(APPEND EXTRA_INCLUDES "external/tremor")
 endif()
 
 if(NOT BELL_DISABLE_SINKS)
     set(PLATFORM "unix")
+
     if(ESP_PLATFORM)
         set(PLATFORM "esp")
     endif()
+
     # Add all built-in audio sinks
-    file(GLOB SINK_SOURCES "${AUDIO_DIR}/sinks/${PLATFORM}/*.cpp" "${AUDIO_DIR}/sinks/${PLATFORM}/*.c")
-    list(APPEND EXTRA_INCLUDES "include/audio/sinks/${PLATFORM}")
+    file(GLOB SINK_SOURCES "${AUDIO_SINKS_DIR}/${PLATFORM}/*.cpp" "${AUDIO_SINKS_DIR}/${PLATFORM}/*.c")
+    list(APPEND EXTRA_INCLUDES "main/audio-sinks/include/${PLATFORM}")
+
     # Find ALSA if required, else remove the sink
     if(BELL_SINK_ALSA)
         find_package(ALSA REQUIRED)
         list(APPEND EXTRA_INCLUDES ${ALSA_INCLUDE_DIRS})
         list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES})
     else()
-        list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/ALSAAudioSink.cpp")
+        list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/ALSAAudioSink.cpp")
     endif()
+
     # Find PortAudio if required, else remove the sink
     if(BELL_SINK_PORTAUDIO)
-        if(WIN32)
-            list(APPEND EXTRA_INCLUDES "portaudio/include")
-            if(NOT "${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
-                list(APPEND EXTRA_LIBS "${CMAKE_CURRENT_SOURCE_DIR}/portaudio/portaudio_win32.lib")
-            else()
-                list(APPEND EXTRA_LIBS "${CMAKE_CURRENT_SOURCE_DIR}/portaudio/portaudio_x64.lib")
-            endif()
-        else()
-            find_package(portaudio REQUIRED)
-            list(APPEND EXTRA_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
-            list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
-        endif()
+        find_package(Portaudio REQUIRED)
+        list(APPEND EXTRA_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
+        list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
     else()
-        list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/PortAudioSink.cpp")
+        list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/PortAudioSink.cpp")
     endif()
+
     list(APPEND SOURCES ${SINK_SOURCES})
 endif()
 
 if(BELL_DISABLE_CJSON)
-    list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/JSONObject.cpp")
+    list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main/io/JSONObject.cpp")
 else()
+    add_subdirectory(external/nlohmann_json)
+    list(APPEND EXTRA_LIBS nlohmann_json::nlohmann_json)
     if(BELL_EXTERNAL_CJSON)
         list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
     else()
-        list(APPEND SOURCES "cJSON/cJSON.c")
-        list(APPEND EXTRA_INCLUDES "cJSON")
+        list(APPEND SOURCES "external/cJSON/cJSON.c")
+        list(APPEND EXTRA_INCLUDES "external/cJSON")
     endif()
 endif()
 
+if (BELL_DISABLE_FMT)
+else()
+    list(APPEND EXTRA_INCLUDES "external/fmt/include")
+endif()
+
+if(WIN32 OR UNIX)
+    list(APPEND SOURCES "external/mdnssvc/mdns.c" "external/mdnssvc/mdnsd.c")
+    list(APPEND EXTRA_INCLUDES "external/mdnssvc")
+endif() 
+
+# file(GLOB CIVET_SRC "external/civetweb/*.c" "external/civetweb/*.inl" "external/civetweb/*.cpp")
+
+# list(APPEND SOURCES ${CIVET_SRC})
+# list(APPEND EXTRA_INCLUDES "external/civetweb/include") 
+
 add_library(bell STATIC ${SOURCES})
+
+# Add Apple Bonjour compatibility library for Linux
+if(UNIX AND NOT APPLE)
+    if (BELL_DISABLE_AVAHI)
+        add_compile_definitions(BELL_DISABLE_AVAHI)
+    else()
+        list(APPEND EXTRA_LIBS avahi-client avahi-common)
+    endif()
+endif()
+
 # PUBLIC to propagate esp-idf includes to bell dependents
 target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
-target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
-target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
-if(WIN32)
-    target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
+target_include_directories(bell PUBLIC ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
+target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC FMT_HEADER_ONLY)
+
+if(BELL_DISABLE_CODECS)
+    target_compile_definitions(bell PUBLIC BELL_DISABLE_CODECS)
+endif() 
+
+if(BELL_VORBIS_FLOAT)
+    target_compile_definitions(bell PUBLIC BELL_VORBIS_FLOAT)
 endif() 
+
+if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
+endif()

+ 0 - 9
components/spotify/cspot/bell/README.md

@@ -1,9 +0,0 @@
-# bell
-
-Core audio utils library used in cspot and euphonium projects.
-
-Implemented utilities:
-
-- HTTPServer
-- Crypto (openssl and mbedtls backed)
-- Semaphore implementations

+ 0 - 163
components/spotify/cspot/bell/cJSON/Makefile

@@ -1,163 +0,0 @@
-CJSON_OBJ = cJSON.o
-UTILS_OBJ = cJSON_Utils.o
-CJSON_LIBNAME = libcjson
-UTILS_LIBNAME = libcjson_utils
-CJSON_TEST = cJSON_test
-
-CJSON_TEST_SRC = cJSON.c test.c
-
-LDLIBS = -lm
-
-LIBVERSION = 1.7.15
-CJSON_SOVERSION = 1
-UTILS_SOVERSION = 1
-
-CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
-UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
-
-PREFIX ?= /usr/local
-INCLUDE_PATH ?= include/cjson
-LIBRARY_PATH ?= lib
-
-INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH)
-INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
-
-INSTALL ?= cp -a
-
-CC = gcc -std=c89
-
-# validate gcc version for use fstack-protector-strong
-MIN_GCC_VERSION = "4.9"
-GCC_VERSION := "`$(CC) -dumpversion`"
-IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
-ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
-    CFLAGS += -fstack-protector-strong
-else
-    CFLAGS += -fstack-protector
-endif
-
-PIC_FLAGS = -fPIC
-R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
-
-uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
-
-#library file extensions
-SHARED = so
-STATIC = a
-
-## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
-ifeq (Darwin, $(uname))
-	SHARED = dylib
-	CJSON_SO_LDFLAG = ""
-	UTILS_SO_LDFLAG = ""
-endif
-
-#cJSON library names
-CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED)
-CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION)
-CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION)
-CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC)
-
-#cJSON_Utils library names
-UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED)
-UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION)
-UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION)
-UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC)
-
-SHARED_CMD = $(CC) -shared -o
-
-.PHONY: all shared static tests clean install
-
-all: shared static tests
-
-shared: $(CJSON_SHARED) $(UTILS_SHARED)
-
-static: $(CJSON_STATIC) $(UTILS_STATIC)
-
-tests: $(CJSON_TEST)
-
-test: tests
-	./$(CJSON_TEST)
-
-.c.o:
-	$(CC) -c $(R_CFLAGS) $<
-
-#tests
-#cJSON
-$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
-	$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC)  -o $@ $(LDLIBS) -I.
-
-#static libraries
-#cJSON
-$(CJSON_STATIC): $(CJSON_OBJ)
-	$(AR) rcs $@ $<
-#cJSON_Utils
-$(UTILS_STATIC): $(UTILS_OBJ)
-	$(AR) rcs $@ $<
-
-#shared libraries .so.1.0.0
-#cJSON
-$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
-	$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
-#cJSON_Utils
-$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
-	$(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS)
-
-#objects
-#cJSON
-$(CJSON_OBJ): cJSON.c cJSON.h
-#cJSON_Utils
-$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h
-
-
-#links .so -> .so.1 -> .so.1.0.0
-#cJSON
-$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION)
-	ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO)
-$(CJSON_SHARED): $(CJSON_SHARED_SO)
-	ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED)
-#cJSON_Utils
-$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION)
-	ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO)
-$(UTILS_SHARED): $(UTILS_SHARED_SO)
-	ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED)
-
-#install
-#cJSON
-install-cjson:
-	mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH)
-	$(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH)
-	$(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
-#cJSON_Utils
-install-utils: install-cjson
-	$(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH)
-	$(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
-
-install: install-cjson install-utils
-
-#uninstall
-#cJSON
-uninstall-cjson: uninstall-utils
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
-	$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
-	
-#cJSON_Utils
-uninstall-utils:
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION)
-	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
-	$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h
-
-remove-dir:
-	$(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH))
-	$(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH))
-
-uninstall: uninstall-utils uninstall-cjson remove-dir
-
-clean:
-	$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
-	$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
-	$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
-	$(RM) $(CJSON_TEST)  #delete test

+ 0 - 71
components/spotify/cspot/bell/cJSON/tests/unity/examples/example_1/makefile

@@ -1,71 +0,0 @@
-# ==========================================
-#   Unity Project - A Test Framework for C
-#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
-#   [Released under MIT License. Please refer to license.txt for details]
-# ==========================================
-
-#We try to detect the OS we are running on, and adjust commands as needed
-ifeq ($(OS),Windows_NT)
-  ifeq ($(shell uname -s),) # not in a bash-like shell
-	CLEANUP = del /F /Q
-	MKDIR = mkdir
-  else # in a bash-like shell, like msys
-	CLEANUP = rm -f
-	MKDIR = mkdir -p
-  endif
-	TARGET_EXTENSION=.exe
-else
-	CLEANUP = rm -f
-	MKDIR = mkdir -p
-	TARGET_EXTENSION=.out
-endif
-
-C_COMPILER=gcc
-ifeq ($(shell uname -s), Darwin)
-C_COMPILER=clang
-endif
-
-UNITY_ROOT=../..
-
-CFLAGS=-std=c89
-CFLAGS += -Wall
-CFLAGS += -Wextra
-CFLAGS += -Wpointer-arith
-CFLAGS += -Wcast-align
-CFLAGS += -Wwrite-strings
-CFLAGS += -Wswitch-default
-CFLAGS += -Wunreachable-code
-CFLAGS += -Winit-self
-CFLAGS += -Wmissing-field-initializers
-CFLAGS += -Wno-unknown-pragmas
-CFLAGS += -Wstrict-prototypes
-CFLAGS += -Wundef
-CFLAGS += -Wold-style-definition
-
-TARGET_BASE1=test1
-TARGET_BASE2=test2
-TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION)
-TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION)
-SRC_FILES1=$(UNITY_ROOT)/src/unity.c src/ProductionCode.c  test/TestProductionCode.c  test/test_runners/TestProductionCode_Runner.c
-SRC_FILES2=$(UNITY_ROOT)/src/unity.c src/ProductionCode2.c test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c
-INC_DIRS=-Isrc -I$(UNITY_ROOT)/src
-SYMBOLS=
-
-all: clean default
-
-default: $(SRC_FILES1) $(SRC_FILES2)
-	$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1)
-	$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2)
-	- ./$(TARGET1)
-	./$(TARGET2)
-
-test/test_runners/TestProductionCode_Runner.c: test/TestProductionCode.c
-	ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode.c  test/test_runners/TestProductionCode_Runner.c
-test/test_runners/TestProductionCode2_Runner.c: test/TestProductionCode2.c
-	ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c
-
-clean:
-	$(CLEANUP) $(TARGET1) $(TARGET2)
-
-ci: CFLAGS += -Werror
-ci: default

+ 0 - 70
components/spotify/cspot/bell/cJSON/tests/unity/examples/example_2/makefile

@@ -1,70 +0,0 @@
-# ==========================================
-#   Unity Project - A Test Framework for C
-#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
-#   [Released under MIT License. Please refer to license.txt for details]
-# ==========================================
-
-#We try to detect the OS we are running on, and adjust commands as needed
-ifeq ($(OS),Windows_NT)
-  ifeq ($(shell uname -s),) # not in a bash-like shell
-	CLEANUP = del /F /Q
-	MKDIR = mkdir
-  else # in a bash-like shell, like msys
-	CLEANUP = rm -f
-	MKDIR = mkdir -p
-  endif
-	TARGET_EXTENSION=.exe
-else
-	CLEANUP = rm -f
-	MKDIR = mkdir -p
-	TARGET_EXTENSION=.out
-endif
-
-C_COMPILER=gcc
-ifeq ($(shell uname -s), Darwin)
-C_COMPILER=clang
-endif
-
-UNITY_ROOT=../..
-
-CFLAGS=-std=c99
-CFLAGS += -Wall
-CFLAGS += -Wextra
-CFLAGS += -Wpointer-arith
-CFLAGS += -Wcast-align
-CFLAGS += -Wwrite-strings
-CFLAGS += -Wswitch-default
-CFLAGS += -Wunreachable-code
-CFLAGS += -Winit-self
-CFLAGS += -Wmissing-field-initializers
-CFLAGS += -Wno-unknown-pragmas
-CFLAGS += -Wstrict-prototypes
-CFLAGS += -Wundef
-CFLAGS += -Wold-style-definition
-
-TARGET_BASE1=all_tests
-TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION)
-SRC_FILES1=\
-  $(UNITY_ROOT)/src/unity.c \
-  $(UNITY_ROOT)/extras/fixture/src/unity_fixture.c \
-  src/ProductionCode.c \
-  src/ProductionCode2.c \
-  test/TestProductionCode.c \
-  test/TestProductionCode2.c \
-  test/test_runners/TestProductionCode_Runner.c \
-  test/test_runners/TestProductionCode2_Runner.c \
-  test/test_runners/all_tests.c
-INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -I$(UNITY_ROOT)/extras/fixture/src
-SYMBOLS=
-
-all: clean default
-
-default:
-	$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1)
-	- ./$(TARGET1) -v
-
-clean:
-	$(CLEANUP) $(TARGET1)
-
-ci: CFLAGS += -Werror
-ci: default

+ 35 - 0
components/spotify/cspot/bell/cmake/FindMbedTLS.cmake

@@ -0,0 +1,35 @@
+if(BELL_EXTERNAL_MBEDTLS)
+    set(MbedTLS_DIR ${BELL_EXTERNAL_MBEDTLS})
+    message(STATUS "Using config mode, setting local mbedtls ${MbedTLS_DIR}")
+
+	find_package(MbedTLS REQUIRED CONFIG)
+	
+	get_target_property(MBEDTLS_INCLUDE_DIRS MbedTLS::mbedtls INTERFACE_INCLUDE_DIRECTORIES)
+
+    if(MSVC)
+        set(MBEDTLS_RELEASE "RELEASE" CACHE STRING "local mbedtls version")
+    else()
+        set(MBEDTLS_RELEASE "NOCONFIG" CACHE STRING "local mbedtls version")
+    endif()
+    
+    get_target_property(MBEDTLS_INFO MbedTLS::mbedtls IMPORTED_LOCATION_${MBEDTLS_RELEASE})
+    set(MBEDTLS_LIBRARIES ${MBEDTLS_INFO})
+    get_target_property(MBEDTLS_INFO MbedTLS::mbedx509 IMPORTED_LOCATION_${MBEDTLS_RELEASE})
+    list(APPEND MBEDTLS_LIBRARIES ${MBEDTLS_INFO})
+    get_target_property(MBEDTLS_INFO MbedTLS::mbedcrypto IMPORTED_LOCATION_${MBEDTLS_RELEASE})
+    list(APPEND MBEDTLS_LIBRARIES ${MBEDTLS_INFO})
+else()
+	find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
+
+find_library(MBEDTLS_LIBRARY mbedtls)
+find_library(MBEDX509_LIBRARY mbedx509)
+find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
+
+set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(MbedTLS DEFAULT_MSG
+    MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
+
+	mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
+endif()

+ 63 - 0
components/spotify/cspot/bell/cmake/Findportaudio.cmake

@@ -0,0 +1,63 @@
+#  PORTAUDIO_FOUND - system has libportaudio
+#  PORTAUDIO_INCLUDE_DIRS - the libportaudio include directory
+#  PORTAUDIO_LIBRARIES - Link these to use libportaudio
+
+if (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
+  # in cache already
+  set(PORTAUDIO_FOUND TRUE)
+else (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
+  if(WIN32)
+	set(PORTAUDIO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio/include")
+
+    if(NOT "${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
+	  set(PORTAUDIO_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio/portaudio_win32.lib")	  
+    else()
+      set(PORTAUDIO_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio/portaudio_x64.lib")
+    endif()
+  else()
+ 	find_path(PORTAUDIO_INCLUDE_DIR
+	  NAMES
+		portaudio.h
+		PATHS
+			/usr/include
+			/usr/local/include
+			/opt/local/include
+			/sw/include
+	)
+  
+	find_library(PORTAUDIO_LIBRARY
+		NAMES
+		portaudio
+		PATHS
+			/usr/lib
+			/usr/local/lib
+			/opt/local/lib
+			/sw/lib
+	)
+  endif()
+  
+  set(PORTAUDIO_INCLUDE_DIRS
+    ${PORTAUDIO_INCLUDE_DIR}
+  )
+  set(PORTAUDIO_LIBRARIES
+    ${PORTAUDIO_LIBRARY}
+  )
+
+  if (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
+    set(PORTAUDIO_FOUND TRUE)
+  endif (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
+
+  if (PORTAUDIO_FOUND)
+    if (NOT Portaudio_FIND_QUIETLY)
+      message(STATUS "Found libportaudio: ${PORTAUDIO_LIBRARIES}")
+    endif (NOT Portaudio_FIND_QUIETLY)
+  else (PORTAUDIO_FOUND)
+    if (Portaudio_FIND_REQUIRED)
+      message(FATAL_ERROR "Could not find libportaudio")
+    endif (Portaudio_FIND_REQUIRED)
+  endif (PORTAUDIO_FOUND)
+
+  # show the PORTAUDIO_INCLUDE_DIRS and PORTAUDIO_LIBRARIES variables only in the advanced view
+  mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES)
+
+endif (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)

+ 14 - 0
components/spotify/cspot/bell/example/CMakeLists.txt

@@ -0,0 +1,14 @@
+project(bell_example)
+cmake_minimum_required(VERSION 3.18)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_BUILD_TYPE Debug)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_BINARY_DIR}/bell)
+
+file(GLOB SOURCES "*.cpp")
+include_directories(".")
+
+add_executable(bell_example ${SOURCES})
+target_link_libraries(bell_example bell ${CMAKE_DL_LIBS} ${THINGS_TO_LINK})
+get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)

+ 70 - 0
components/spotify/cspot/bell/example/main.cpp

@@ -0,0 +1,70 @@
+#include <memory.h>
+#include <atomic>
+#include <cmath>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <vector>
+#include "AudioCodecs.h"
+#include "AudioContainers.h"
+#include "BellHTTPServer.h"
+#include "BellTar.h"
+#include "BellTask.h"
+#include "CentralAudioBuffer.h"
+#include "Compressor.h"
+#include "DecoderGlobals.h"
+#include "EncodedAudioStream.h"
+#include "HTTPClient.h"
+#include "PortAudioSink.h"
+#define DEBUG_LEVEL 4
+#include "X509Bundle.h"
+#include "mbedtls/debug.h"
+
+#include <BellDSP.h>
+#include <BellLogger.h>
+
+std::shared_ptr<bell::CentralAudioBuffer> audioBuffer;
+std::atomic<bool> isPaused = false;
+
+class AudioPlayer : bell::Task {
+ public:
+  std::unique_ptr<PortAudioSink> audioSink;
+  std::unique_ptr<bell::BellDSP> dsp;
+
+  AudioPlayer() : bell::Task("player", 1024, 0, 0) {
+    this->audioSink = std::make_unique<PortAudioSink>();
+    this->audioSink->setParams(44100, 2, 16);
+    this->dsp = std::make_unique<bell::BellDSP>(audioBuffer);
+    startTask();
+  }
+
+  void runTask() override {
+    while (true) {
+      if (audioBuffer->hasAtLeast(64) || isPaused) {
+        auto chunk = audioBuffer->readChunk();
+
+        if (chunk != nullptr && chunk->pcmSize > 0) {
+          this->dsp->process(chunk->pcmData, chunk->pcmSize, 2, 44100,
+                             bell::BitWidth::BW_16);
+
+          this->audioSink->feedPCMFrames(chunk->pcmData, chunk->pcmSize);
+        }
+      }
+    }
+  }
+};
+
+int main() {
+  bell::setDefaultLogger();
+
+  std::fstream file("system.tar", std::ios::in | std::ios::binary);
+  if (!file.is_open()) {
+    std::cout << "file not open" << std::endl;
+    return 1;
+  }
+
+  BellTar::reader reader(file);
+  reader.extract_all_files("./dupa2");
+  return 0;
+}

+ 13 - 0
components/spotify/cspot/bell/example/scripts/dsp_spectogram.py

@@ -0,0 +1,13 @@
+import matplotlib.pyplot as plt
+from scipy import signal
+from scipy.io import wavfile
+
+sample_rate, samples = wavfile.read('out.wav')
+print(sample_rate)
+frequencies, times, spectrogram = signal.spectrogram(samples, sample_rate)
+
+plt.pcolormesh(times, frequencies, spectrogram)
+plt.imshow(spectrogram)
+plt.ylabel('Frequency [Hz]')
+plt.xlabel('Time [sec]')
+plt.show()

+ 6 - 0
components/spotify/cspot/bell/external/alac/.gitignore

@@ -0,0 +1,6 @@
+*.o*
+*.bak
+build/
+codec/*.a
+.vs/
+*.user

+ 241 - 0
components/spotify/cspot/bell/external/alac/ALACMagicCookieDescription.txt

@@ -0,0 +1,241 @@
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+Apple Lossless Format "Magic Cookie" Description
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+
+Many encoded formats for audio require additional, codec specific configuration information in order to operate successfully.
+This codec specific information is often called a 'magic cookie'. The Apple Lossless codec's 'magic cookie' contains the 
+ALACSpecificConfig and optional ALACChannelLayoutInfo (both described below).
+
+The 'magic cookie' must accompany the bitstream when stored in any file container (M4A/MP4, CAF) so that it may be provided to the 
+decoder when decoding the bitstream. From the caller's perspective, the 'magic cookie' is opaque and should be stored in the file 
+and presented to the decoder exactly as it is vended from the encoder (and consequently stored in the file). 
+
+The ALAC 'magic cookie' as stored in a file has all fields described in big-endian order (regardless of file format).
+
+The layout of the 'magic cookie' is as follows:
+
+
+---------------- ALAC Specific Info (24 bytes) (mandatory) ---------------------------
+(ALACSpecificConfig)		Decoder Info
+	
+---------------- Channel Layout Info (24 bytes) (optional) ----------------------------
+(ALAC Channel Layout Info)	Channel Layout Info
+
+
+If the channel layout is absent from the cookie, then the following assumptions are made:
+1 channel - mono
+2 channels - stereo in left, right order
+> 2 channels - no specific channel designation or role.
+
+
+__________________________________________________________________________________________________________________________________
+* ALAC Specific Info (24 bytes) (mandatory)
+__________________________________________________________________________________________________________________________________
+
+The Apple Lossless codec stores specific information about the encoded stream in the ALACSpecificConfig. This
+info is vended by the encoder and is used to setup the decoder for a given encoded bitstream. 
+
+When read from and written to a file, the fields of this struct must be in big-endian order. 
+When vended by the encoder (and received by the decoder) the struct values will be in big-endian order.
+
+/*
+    struct	ALACSpecificConfig (defined in ALACAudioTypes.h)
+    abstract   	This struct is used to describe codec provided information about the encoded Apple Lossless bitstream. 
+		It must accompany the encoded stream in the containing audio file and be provided to the decoder.
+
+    field      	frameLength 		uint32_t	indicating the frames per packet when no explicit frames per packet setting is 
+							present in the packet header. The encoder frames per packet can be explicitly set 
+							but for maximum compatibility, the default encoder setting of 4096 should be used.
+
+    field      	compatibleVersion 	uint8_t 	indicating compatible version, 
+							value must be set to 0
+
+    field      	bitDepth 		uint8_t 	describes the bit depth of the source PCM data (maximum value = 32)
+
+    field      	pb 			uint8_t 	currently unused tuning parameter. 
+						 	value should be set to 40
+
+    field      	mb 			uint8_t 	currently unused tuning parameter. 
+						 	value should be set to 10
+
+    field      	kb			uint8_t 	currently unused tuning parameter. 
+						 	value should be set to 14
+
+    field      	numChannels 		uint8_t 	describes the channel count (1 = mono, 2 = stereo, etc...)
+							when channel layout info is not provided in the 'magic cookie', a channel count > 2
+							describes a set of discreet channels with no specific ordering
+
+    field      	maxRun			uint16_t 	currently unused. 
+   						  	value should be set to 255
+
+    field      	maxFrameBytes 		uint32_t 	the maximum size of an Apple Lossless packet within the encoded stream. 
+						  	value of 0 indicates unknown
+
+    field      	avgBitRate 		uint32_t 	the average bit rate in bits per second of the Apple Lossless stream. 
+						  	value of 0 indicates unknown
+
+    field      	sampleRate 		uint32_t 	sample rate of the encoded stream
+ */
+
+typedef struct ALACSpecificConfig
+{
+	uint32_t	frameLength;
+	uint8_t		compatibleVersion;
+	uint8_t		bitDepth;
+	uint8_t		pb;
+	uint8_t		mb;
+	uint8_t		kb;
+	uint8_t		numChannels;
+	uint16_t	maxRun;
+	uint32_t	maxFrameBytes;
+	uint32_t	avgBitRate;
+	uint32_t	sampleRate;
+
+} ALACSpecificConfig;
+		
+
+__________________________________________________________________________________________________________________________________
+Channel Layout Info (24 bytes) (optional)
+__________________________________________________________________________________________________________________________________
+
+The Apple Lossless codec can support a specific set of channel layouts. When channel information is vended 
+by the encoder (in the 'magic cookie'), it is formatted in the the ALACChannelLayoutInfo.
+
+When read from and written to a file, the fields of this struct must be in big-endian order. 
+When vended by the encoder (and received by the decoder) the struct values will be in big-endian order.
+
+/*
+    struct	ALACChannelLayoutInfo (defined in ALACAudioTypes.h)
+    abstract	This struct is used to specify particular channel orderings or configurations.
+		It is an optional portion of the 'magic cookie', being required to describe specific channel layouts (see below)
+		of more than 2 channels. 
+
+    field      	channelLayoutInfoSize 	uint32_t 	indicates the size of the channel layout data
+							value should be set to 24
+
+    field      	channelLayoutInfoID 	uint32_t 	identifier indicating that channel layout info is present 
+							value = 'chan'
+
+    field      	versionFlags 		uint32_t 	version flags
+						 	value should be set to 0
+
+    field	channelLayoutTag	uint32_t	channel layout type
+							from defined list in ALACAudioTypes.h (see below)
+
+    field      	reserved1 		uint32_t 	currently unused field
+						 	value should be set to 0
+
+    field      	reserved2 		uint32_t	currently unused field 
+						 	value should be set to 0
+*/
+
+typedef struct ALACChannelLayoutInfo
+{
+	uint32_t	channelLayoutInfoSize;
+	uint32_t	channelLayoutInfoID;
+	uint32_t	versionFlags;
+	uint32_t	channelLayoutTag;	
+	uint32_t	reserved1;	
+	uint32_t	reserved2;	
+} ALACChannelLayoutInfo;
+
+
+* Channel Layout Tags
+
+These constants will be used to describe the bitstream's channel layout. (defined in ALACAudioTypes.h)
+
+enum
+{
+   kALACChannelLayoutTag_Mono         	= (100<<16) | 1,    	// C
+   kALACChannelLayoutTag_Stereo       	= (101<<16) | 2,	// L R
+   kALACChannelLayoutTag_MPEG_3_0_B   	= (113<<16) | 3,	// C L R
+   kALACChannelLayoutTag_MPEG_4_0_B   	= (116<<16) | 4,	// C L R Cs
+   kALACChannelLayoutTag_MPEG_5_0_D	= (120<<16) | 5,    	// C L R Ls Rs
+   kALACChannelLayoutTag_MPEG_5_1_D   	= (124<<16) | 6,	// C L R Ls Rs LFE
+   kALACChannelLayoutTag_AAC_6_1      	= (142<<16) | 7,	// C L R Ls Rs Cs LFE
+   kALACChannelLayoutTag_MPEG_7_1_B	= (127<<16) | 8    	// C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+* Storing Apple Lossless Magic Cookie in Audio Files
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+
+The Apple Lossless Magic Cookie is treated as opaque by file parsing code.  The 'magic cookie' vended by the encoder 
+is placed without modification into the audio file and the read from that file and passed (unmodified) to the decoder.
+
+__________________________________________________________________________________________________________________________________
+* CAF File
+
+In a CAF file (Core Audio File), the 'magic cookie' is stored in CAF's Magic Cookie chunk ('kuki').
+
+__________________________________________________________________________________________________________________________________
+* MP4/M4A File
+
+In an MP4/M4A file, the 'magic cookie' is encapsulated in the AudioSample entry of a Sound Description box ('stsd').  
+An ISO style full box header to describe the ALACSpecificConfig portion is appended to the AudioSampleEntry, followed by the 
+'magic cookie' as it is vended by the encoder. 
+
+(All fields are stored in big-endian order: see ISO/IEC 14496-12 for a full description of the SoundDescription and AudioSampleEntry boxes, etc.)
+
+---------------- SoundDescriptionBox (FullBox) ----------------------------
+
+		SampleEntrySize		 	// = sizeof(SoundDescriptionBox)(16) + sizeof (AudioSampleEntry)(AudioSampleEntry.SampleEntrySize)
+		SampleEntryType			// = 'stsd'
+		VersionFlags 			// = 0
+		EntryCount			// = 1
+
+---------------- Audio Sample Entry (REQUIRED) -----------------------------
+
+		SampleEntrySize 		// sizeof(AudioSampleEntry)(36) + sizeof(full ISO box header)(12) + sizeof(Apple Lossless Magic Cookie)
+		SampleEntryType			// = 'alac', specifies that the AudioSampleEntry describes an Apple Lossless bitstream
+		mReserved[6]			// = 0
+		dref index			// = 1
+		reserved[2]			// = 0
+		channel count			// = number of channels as a uint_16 value
+		sample size			// = source pcm bitdepth (example = 16bit source pcm)
+		predefined			// = 0
+		reserved			// = 0
+		sample rate			// sample rate as a uint_32 value
+
+     Appended to AudioSampleEntry:
+
+		ALAC Specific Info Size		// uint_32 value, = 36 (12 + sizeof(ALACSpecificConfig))
+		ALAC Specific Info ID		// uint_32 value, = 'alac', format ID which matches the Audio Sample Entry SampleEntryType field
+		Version Flags			// uint_32 value, = 0		
+
+		Apple Lossless Magic Cookie	// 'magic cookie' vended from ALAC encoder (24 or 48 Bytes)
+
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+* Compatibility
+__________________________________________________________________________________________________________________________________
+__________________________________________________________________________________________________________________________________
+
+Previous versions of the Apple Lossless encoder vended a different 'magic cookie'. To ensure compatibility, the Apple Lossless decoder 
+must be prepared to parse a 'magic cookie' in the format described below. Note that the 'magic cookie' defined above is 
+encapsulated in the following method and can be extracted as a contiguous set of bytes.
+
+
+---------------- Format Atom (12 bytes) --------------------------------
+(uint_32)		Format Atom Size		// = 12
+(uint_32)		Channel Layout Info ID		// = 'frma'	
+(uint_32)		Format Type			// = 'alac'	
+	
+---------------- ALAC Specific Info (36 bytes) (required) --------------
+(uint_32)		ALAC Specific Info Size		// = 36 (12 + sizeof(ALACSpecificConfig))
+(uint_32)		ALAC Specific Info ID		// = 'alac', format ID which matches the Audio Sample Entry SampleEntryType field
+(uint_32)		Version Flags			// = 0		
+
+	[ Apple Lossless Magic Cookie (see above) ]
+
+---------------- Terminator Atom (8 bytes) -----------------------------
+(uint_32)		Channel Layout Info Size	// = 8	
+(uint_32)		Channel Layout Info ID		// = 0	
+
+
+

+ 9 - 0
components/spotify/cspot/bell/external/alac/CONTRIBUTING.md

@@ -0,0 +1,9 @@
+By submitting a request, you represent that you have the right to license
+your contribution to the community, and agree that your contributions are
+licensed under the [Apache License Version 2.0](LICENSE).
+
+For existing files modified by your request, you represent that you have
+retained any existing copyright notices and licensing terms. For each new
+file in your request, you represent that you have added to the file a
+copyright notice (including the year and the copyright owner's name) and
+ALAC's licensing terms.

+ 53 - 0
components/spotify/cspot/bell/external/alac/LICENSE

@@ -0,0 +1,53 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

+ 9 - 0
components/spotify/cspot/bell/external/alac/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,9 @@
+By submitting a request, you represent that you have the right to license
+your contribution to the community, and agree that your contributions are
+licensed under the [Apache License Version 2.0](LICENSE).
+
+For existing files modified by your request, you represent that you have
+retained any existing copyright notices and licensing terms. For each new
+file in your request, you represent that you have added to the file a
+copyright notice (including the year and the copyright owner's name) and
+ALAC's licensing terms.

+ 44 - 0
components/spotify/cspot/bell/external/alac/ReadMe.txt

@@ -0,0 +1,44 @@
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+The Apple Lossless Format
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+Apple Lossless supports the following features. Not all of these are implemented in alacconvert, though they are in the codec code provided.
+
+1. Bit depths 16, 20, 24 and 32 bits.
+2. Any arbitrary integer sample rate from 1 to 384,000 Hz. In theory rates up to 4,294,967,295 (2^32 - 1) Hz could be supported.
+3. From one to eight channels are supported. Channel orders for the supported formats are described as:
+	Num Chan	Order
+	1 		mono
+	2 		stereo (Left, Right)
+	3 		MPEG 3.0 B (Center, Left, Right)
+	4 		MPEG 4.0 B (Center, Left, Right, Center Surround)
+	5 		MPEG 5.0 D (Center, Left, Right, Left Surround, Right Surround)
+	6 		MPEG 5.1 D (Center, Left, Right, Left Surround, Right Surround, Low Frequency Effects)
+	7 		Apple AAC 6.1 (Center, Left, Right, Left Surround, Right Surround, Center Surround, Low Frequency Effects)
+	8 		MPEG 7.1 B (Center, Left Center, Right Center, Left, Right, Left Surround, Right Surround,  Low Frequency Effects)
+4. Packet size defaults to 4096 sample frames of audio per packet. Other packet sizes are certainly possible. However, non-default packet sizes are not guaranteed to work properly on all hardware devices that support Apple Lossless. Packets above 16,384 sample frames are not supported.
+
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+This package contains the sources for the Apple Lossless (ALAC) encoder and decoder.
+
+The "codec" directory contains all the sources necessary for a functioning codec. Also includes is a makefile that will build libalac.a on a UNIX/Linux machine.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ALACconvert
+
+The convert-utility directory contains sources to build alacconvert which is a simple utility that demonstrates how to use the included ALAC encoder and decoder.
+
+alacconvert supports the following formats:
+
+1. 16- or 24-bit mono or stereo .wav files where the data is little endian integer. Extended WAVE format chunks are not handled.
+2. 16- or 24-bit mono or stereo .caf (Core Audio Format) files as well as certain multi-channel configurations where the data is big or little endian integer. It does no channel order manipulation.
+3. ALAC .caf files.
+
+Three project are provided to build a command line utility called alacconvert that converts cpm data to ALAC or vice versa. A Mac OS X Xcode project, A Windows Visual Studio project, and a generic UNIX/Linux make file.
+
+Note: When building on Windows, if you are using a version of Visual Studio before Visual Studio 2010, <stdint.h> is not installed. You will need to acquire this file on your own. It can be put in the same directory as the project.
+
+
+

+ 202 - 0
components/spotify/cspot/bell/external/alac/codec/ALACAudioTypes.h

@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACAudioTypes.h
+*/
+
+#ifndef ALACAUDIOTYPES_H
+#define ALACAUDIOTYPES_H
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+    #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+    #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+    #pragma pack(2)
+#endif
+
+#include <stdint.h>
+
+#if defined(__ppc__)
+#define TARGET_RT_BIG_ENDIAN 1
+#elif defined(__ppc64__)
+#define TARGET_RT_BIG_ENDIAN 1
+#endif
+
+#define kChannelAtomSize 12
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmultichar"
+    
+enum 
+{
+    kALAC_UnimplementedError   = -4,
+    kALAC_FileNotFoundError    = -43,
+    kALAC_ParamError           = -50,
+    kALAC_MemFullError         = -108
+};
+
+enum
+{
+    kALACFormatAppleLossless = 'alac',
+    kALACFormatLinearPCM = 'lpcm'
+};
+
+enum
+{
+    kALACMaxChannels	= 8,
+    kALACMaxEscapeHeaderBytes = 8,
+    kALACMaxSearches	= 16,
+    kALACMaxCoefs		= 16,
+    kALACDefaultFramesPerPacket = 4096
+};
+
+typedef uint32_t ALACChannelLayoutTag;
+
+enum
+{
+    kALACFormatFlagIsFloat                     = (1 << 0),     // 0x1
+    kALACFormatFlagIsBigEndian                 = (1 << 1),     // 0x2
+    kALACFormatFlagIsSignedInteger             = (1 << 2),     // 0x4
+    kALACFormatFlagIsPacked                    = (1 << 3),     // 0x8
+    kALACFormatFlagIsAlignedHigh               = (1 << 4),     // 0x10
+};
+
+enum
+{
+#if TARGET_RT_BIG_ENDIAN
+    kALACFormatFlagsNativeEndian       = kALACFormatFlagIsBigEndian
+#else
+    kALACFormatFlagsNativeEndian       = 0
+#endif
+};
+
+// this is required to be an IEEE 64bit float
+typedef double alac_float64_t;
+
+// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
+enum
+{
+    kALACChannelLayoutTag_Mono          = (100<<16) | 1,    // C
+    kALACChannelLayoutTag_Stereo        = (101<<16) | 2,	// L R
+    kALACChannelLayoutTag_MPEG_3_0_B    = (113<<16) | 3,	// C L R
+    kALACChannelLayoutTag_MPEG_4_0_B    = (116<<16) | 4,	// C L R Cs
+    kALACChannelLayoutTag_MPEG_5_0_D    = (120<<16) | 5,    // C L R Ls Rs
+    kALACChannelLayoutTag_MPEG_5_1_D    = (124<<16) | 6,	// C L R Ls Rs LFE
+    kALACChannelLayoutTag_AAC_6_1       = (142<<16) | 7,	// C L R Ls Rs Cs LFE
+    kALACChannelLayoutTag_MPEG_7_1_B	= (127<<16) | 8     // C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
+// given number of channels and one of these layout tags
+static const ALACChannelLayoutTag	ALACChannelLayoutTags[kALACMaxChannels] =
+{
+    kALACChannelLayoutTag_Mono,         // C
+    kALACChannelLayoutTag_Stereo,		// L R
+    kALACChannelLayoutTag_MPEG_3_0_B,	// C L R
+    kALACChannelLayoutTag_MPEG_4_0_B,	// C L R Cs
+    kALACChannelLayoutTag_MPEG_5_0_D,	// C L R Ls Rs
+    kALACChannelLayoutTag_MPEG_5_1_D,	// C L R Ls Rs LFE
+    kALACChannelLayoutTag_AAC_6_1,		// C L R Ls Rs Cs LFE
+    kALACChannelLayoutTag_MPEG_7_1_B	// C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
+struct ALACAudioChannelLayout
+{
+    ALACChannelLayoutTag          mChannelLayoutTag;
+    uint32_t                      mChannelBitmap;
+    uint32_t                      mNumberChannelDescriptions;
+};
+typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
+
+struct AudioFormatDescription
+{
+    alac_float64_t mSampleRate;
+    uint32_t  mFormatID;
+    uint32_t  mFormatFlags;
+    uint32_t  mBytesPerPacket;
+    uint32_t  mFramesPerPacket;
+    uint32_t  mBytesPerFrame;
+    uint32_t  mChannelsPerFrame;
+    uint32_t  mBitsPerChannel;
+    uint32_t  mReserved;
+};
+typedef struct AudioFormatDescription  AudioFormatDescription;
+
+/* Lossless Definitions */
+
+enum
+{
+	kALACCodecFormat		= 'alac',
+	kALACVersion			= 0,
+	kALACCompatibleVersion	= kALACVersion,
+	kALACDefaultFrameSize	= 4096
+};
+
+// note: this struct is wrapped in an 'alac' atom in the sample description extension area
+// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
+typedef struct ALACSpecificConfig
+{
+	uint32_t				frameLength;
+	uint8_t					compatibleVersion;
+	uint8_t					bitDepth;							// max 32
+	uint8_t					pb;									// 0 <= pb <= 255
+	uint8_t					mb;
+	uint8_t					kb;
+	uint8_t					numChannels;
+	uint16_t				maxRun;
+	uint32_t				maxFrameBytes;
+	uint32_t				avgBitRate;
+	uint32_t				sampleRate;
+
+} ALACSpecificConfig;
+
+
+// The AudioChannelLayout atom type is not exposed yet so define it here
+enum
+{
+	AudioChannelLayoutAID = 'chan'
+};
+
+#pragma GCC diagnostic pop
+
+#if PRAGMA_STRUCT_ALIGN
+    #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+    #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+    #pragma pack()
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ALACAUDIOTYPES_H */

+ 260 - 0
components/spotify/cspot/bell/external/alac/codec/ALACBitUtilities.c

@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*=============================================================================
+    File:		ALACBitUtilities.c
+
+	$NoKeywords: $
+=============================================================================*/
+
+#include <stdio.h>
+#include "ALACBitUtilities.h"
+
+// BitBufferInit
+//
+void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
+{
+	bits->cur		= buffer;
+	bits->end		= bits->cur + byteSize;
+	bits->bitIndex	= 0;
+	bits->byteSize	= byteSize;
+}
+
+// BitBufferRead
+//
+uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits )
+{
+	uint32_t		returnBits;
+	
+	//Assert( numBits <= 16 );
+
+	returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]);
+	returnBits = returnBits << bits->bitIndex;
+	returnBits &= 0x00FFFFFF;
+	
+	bits->bitIndex += numBits;
+	
+	returnBits = returnBits >> (24 - numBits);
+	
+	bits->cur		+= (bits->bitIndex >> 3);
+	bits->bitIndex	&= 7;
+	
+	//Assert( bits->cur <= bits->end );
+	
+	return returnBits;
+}
+
+// BitBufferReadSmall
+//
+// Reads up to 8 bits
+uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits )
+{
+	uint16_t		returnBits;
+	
+	//Assert( numBits <= 8 );
+	
+	returnBits = (bits->cur[0] << 8) | bits->cur[1];
+	returnBits = returnBits << bits->bitIndex;
+	
+	bits->bitIndex += numBits;
+	
+	returnBits = returnBits >> (16 - numBits);
+	
+	bits->cur		+= (bits->bitIndex >> 3);
+	bits->bitIndex	&= 7;
+	
+	//Assert( bits->cur <= bits->end );
+	
+	return (uint8_t)returnBits;
+}
+
+// BitBufferReadOne
+//
+// Reads one byte
+uint8_t BitBufferReadOne( BitBuffer * bits )
+{
+	uint8_t		returnBits;
+
+	returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1;
+
+	bits->bitIndex++;
+	
+	bits->cur		+= (bits->bitIndex >> 3);
+	bits->bitIndex	&= 7;
+	
+	//Assert( bits->cur <= bits->end );
+	
+	return returnBits;
+}
+
+// BitBufferPeek
+//
+uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits )
+{
+	return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) |
+			((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits));
+}
+
+// BitBufferPeekOne
+//
+uint32_t BitBufferPeekOne( BitBuffer * bits )
+{
+	return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1);
+}
+
+// BitBufferUnpackBERSize
+//
+uint32_t BitBufferUnpackBERSize( BitBuffer * bits )
+{
+	uint32_t		size;
+	uint8_t		tmp;
+	
+	for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) )
+		tmp = (uint8_t) BitBufferReadSmall( bits, 8 );
+	
+	return size;
+}
+
+// BitBufferGetPosition
+//
+uint32_t BitBufferGetPosition( BitBuffer * bits )
+{
+	uint8_t *		begin;
+	
+	begin = bits->end - bits->byteSize;
+	
+	return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex;
+}
+
+// BitBufferByteAlign
+//
+void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros )
+{
+	// align bit buffer to next byte boundary, writing zeros if requested
+	if ( bits->bitIndex == 0 )
+		return;
+
+	if ( addZeros )
+		BitBufferWrite( bits, 0, 8 - bits->bitIndex );
+	else	
+		BitBufferAdvance( bits, 8 - bits->bitIndex );	
+}
+
+// BitBufferAdvance
+//
+void BitBufferAdvance( BitBuffer * bits, uint32_t numBits )
+{
+	if ( numBits )
+	{
+		bits->bitIndex += numBits;
+		bits->cur += (bits->bitIndex >> 3);
+		bits->bitIndex &= 7;
+	}
+}
+
+// BitBufferRewind
+//
+void BitBufferRewind( BitBuffer * bits, uint32_t numBits )
+{
+	uint32_t	numBytes;
+	
+	if ( numBits == 0 )
+		return;
+	
+	if ( bits->bitIndex >= numBits )
+	{
+		bits->bitIndex -= numBits;
+		return;
+	}
+	
+	numBits -= bits->bitIndex;
+	bits->bitIndex = 0;
+
+	numBytes	= numBits / 8;
+	numBits		= numBits % 8;
+	
+	bits->cur -= numBytes;
+	
+	if ( numBits > 0 )
+	{
+		bits->bitIndex = 8 - numBits;
+		bits->cur--;
+	}
+	
+	if ( bits->cur < (bits->end - bits->byteSize) )
+	{
+		//DebugCMsg("BitBufferRewind: Rewound too far.");
+
+		bits->cur		= (bits->end - bits->byteSize);
+		bits->bitIndex	= 0;
+	}
+}
+
+// BitBufferWrite
+//
+void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits )
+{
+	uint32_t				invBitIndex;
+	
+	RequireAction( bits != nil, return; );
+	RequireActionSilent( numBits > 0, return; );
+
+	invBitIndex = 8 - bits->bitIndex;
+
+	while ( numBits > 0 )
+	{
+		uint32_t		tmp;
+		uint8_t		shift;
+		uint8_t		mask;
+		uint32_t		curNum;
+
+		curNum = MIN( invBitIndex, numBits );
+
+		tmp = bitValues >> (numBits - curNum);
+
+		shift  = (uint8_t)(invBitIndex - curNum);
+		mask   = 0xffu >> (8 - curNum);		// must be done in two steps to avoid compiler sequencing ambiguity
+		mask <<= shift;
+
+		bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift)  & mask);
+		numBits -= curNum;
+
+		// increment to next byte if need be
+		invBitIndex -= curNum;
+		if ( invBitIndex == 0 )
+		{
+			invBitIndex = 8;
+			bits->cur++;
+		}
+	}
+
+	bits->bitIndex = 8 - invBitIndex;
+}
+
+void	BitBufferReset( BitBuffer * bits )
+//void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
+{
+	bits->cur		= bits->end - bits->byteSize;
+    bits->bitIndex	= 0;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif

+ 104 - 0
components/spotify/cspot/bell/external/alac/codec/ALACBitUtilities.h

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*=============================================================================
+    File:		ALACBitUtilities.h
+	
+	$NoKeywords: $
+=============================================================================*/
+
+#ifndef __ALACBITUTILITIES_H
+#define __ALACBITUTILITIES_H
+
+#include <stdint.h>
+
+#ifndef MIN
+#define MIN(x, y) 			( (x)<(y) ?(x) :(y) )
+#endif //MIN
+#ifndef MAX
+#define MAX(x, y) 			( (x)>(y) ?(x): (y) )
+#endif //MAX
+
+#ifndef nil
+#define nil NULL
+#endif
+
+#define RequireAction(condition, action)			if (!(condition)) { action }
+#define RequireActionSilent(condition, action)			if (!(condition)) { action }
+#define RequireNoErr(condition, action)			if ((condition)) { action }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum
+{
+    ALAC_noErr = 0
+};
+    
+
+typedef enum
+{
+    
+    ID_SCE = 0,						/* Single Channel Element   */
+    ID_CPE = 1,						/* Channel Pair Element     */
+    ID_CCE = 2,						/* Coupling Channel Element */
+    ID_LFE = 3,						/* LFE Channel Element      */
+    ID_DSE = 4,						/* not yet supported        */
+    ID_PCE = 5,
+    ID_FIL = 6,
+    ID_END = 7
+} ELEMENT_TYPE;
+
+// types
+typedef struct BitBuffer
+{
+	uint8_t *		cur;
+	uint8_t *		end;
+	uint32_t		bitIndex;
+	uint32_t		byteSize;
+	
+} BitBuffer;
+
+/*
+	BitBuffer routines
+	- these routines take a fixed size buffer and read/write to it
+	- bounds checking must be done by the client
+*/
+void	BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize );
+uint32_t	BitBufferRead( BitBuffer * bits, uint8_t numBits );   // note: cannot read more than 16 bits at a time
+uint8_t	BitBufferReadSmall( BitBuffer * bits, uint8_t numBits );
+uint8_t	BitBufferReadOne( BitBuffer * bits );
+uint32_t	BitBufferPeek( BitBuffer * bits, uint8_t numBits );   // note: cannot read more than 16 bits at a time
+uint32_t	BitBufferPeekOne( BitBuffer * bits );
+uint32_t	BitBufferUnpackBERSize( BitBuffer * bits );
+uint32_t	BitBufferGetPosition( BitBuffer * bits );
+void	BitBufferByteAlign( BitBuffer * bits, int32_t addZeros );
+void	BitBufferAdvance( BitBuffer * bits, uint32_t numBits );
+void	BitBufferRewind( BitBuffer * bits, uint32_t numBits );
+void	BitBufferWrite( BitBuffer * bits, uint32_t value, uint32_t numBits );
+void	BitBufferReset( BitBuffer * bits);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __BITUTILITIES_H */

+ 737 - 0
components/spotify/cspot/bell/external/alac/codec/ALACDecoder.cpp

@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACDecoder.cpp
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ALACDecoder.h"
+
+#include "dplib.h"
+#include "aglib.h"
+#include "matrixlib.h"
+
+#include "ALACBitUtilities.h"
+#include "EndianPortable.h"
+
+#if (__GNUC__) > 4 || defined (__APPLE__)
+#pragma GCC diagnostic ignored "-Wunused-const-variable"
+#endif
+#if !defined(__APPLE__) 
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+
+// constants/data
+const uint32_t kMaxBitDepth = 32;			// max allowed bit depth is 32
+
+
+// prototypes
+static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride );
+static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride );
+static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride );
+
+/*
+	Constructor
+*/
+ALACDecoder::ALACDecoder() :
+	mMixBufferU( nil ),
+	mMixBufferV( nil ),
+	mPredictor( nil ),
+	mShiftBuffer( nil )
+{
+	memset( &mConfig, 0, sizeof(mConfig) );
+}
+
+/*
+	Destructor
+*/
+ALACDecoder::~ALACDecoder()
+{
+	// delete the matrix mixing buffers
+	if ( mMixBufferU )
+    {
+		free(mMixBufferU);
+        mMixBufferU = NULL;
+    }
+	if ( mMixBufferV )
+    {
+		free(mMixBufferV);
+        mMixBufferV = NULL;
+    }
+	
+	// delete the dynamic predictor's "corrector" buffer
+	// - note: mShiftBuffer shares memory with this buffer
+	if ( mPredictor )
+    {
+		free(mPredictor);
+        mPredictor = NULL;
+    }
+}
+
+/*
+	Init()
+	- initialize the decoder with the given configuration
+*/
+int32_t ALACDecoder::Init( void * inMagicCookie, uint32_t inMagicCookieSize )
+{
+	int32_t		status = ALAC_noErr;
+    ALACSpecificConfig theConfig;
+    uint8_t * theActualCookie = (uint8_t *)inMagicCookie;
+    uint32_t theCookieBytesRemaining = inMagicCookieSize;
+
+    // For historical reasons the decoder needs to be resilient to magic cookies vended by older encoders.
+    // As specified in the ALACMagicCookieDescription.txt document, there may be additional data encapsulating 
+    // the ALACSpecificConfig. This would consist of format ('frma') and 'alac' atoms which precede the
+    // ALACSpecificConfig. 
+    // See ALACMagicCookieDescription.txt for additional documentation concerning the 'magic cookie'
+    
+    // skip format ('frma') atom if present
+    if (theActualCookie[4] == 'f' && theActualCookie[5] == 'r' && theActualCookie[6] == 'm' && theActualCookie[7] == 'a')
+    {
+        theActualCookie += 12;
+        theCookieBytesRemaining -= 12;
+    }
+    
+    // skip 'alac' atom header if present
+    if (theActualCookie[4] == 'a' && theActualCookie[5] == 'l' && theActualCookie[6] == 'a' && theActualCookie[7] == 'c')
+    {
+        theActualCookie += 12;
+        theCookieBytesRemaining -= 12;
+    }
+
+    // read the ALACSpecificConfig
+    if (theCookieBytesRemaining >= sizeof(ALACSpecificConfig))
+    {
+        theConfig.frameLength = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->frameLength);
+        theConfig.compatibleVersion = ((ALACSpecificConfig *)theActualCookie)->compatibleVersion;
+        theConfig.bitDepth = ((ALACSpecificConfig *)theActualCookie)->bitDepth;
+        theConfig.pb = ((ALACSpecificConfig *)theActualCookie)->pb;
+        theConfig.mb = ((ALACSpecificConfig *)theActualCookie)->mb;
+        theConfig.kb = ((ALACSpecificConfig *)theActualCookie)->kb;
+        theConfig.numChannels = ((ALACSpecificConfig *)theActualCookie)->numChannels;
+        theConfig.maxRun = Swap16BtoN(((ALACSpecificConfig *)theActualCookie)->maxRun);
+        theConfig.maxFrameBytes = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->maxFrameBytes);
+        theConfig.avgBitRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->avgBitRate);
+        theConfig.sampleRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->sampleRate);
+
+        mConfig = theConfig;
+        
+        RequireAction( mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError; );
+
+        // allocate mix buffers
+        mMixBufferU = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
+        mMixBufferV = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
+
+        // allocate dynamic predictor buffer
+        mPredictor = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
+
+        // "shift off" buffer shares memory with predictor buffer
+        mShiftBuffer = (uint16_t *) mPredictor;
+        
+        RequireAction( (mMixBufferU != nil) && (mMixBufferV != nil) && (mPredictor != nil),
+                        status = kALAC_MemFullError; goto Exit; );
+     }
+    else
+    {
+        status = kALAC_ParamError;
+    }
+
+    // skip to Channel Layout Info
+    // theActualCookie += sizeof(ALACSpecificConfig);
+    
+    // Currently, the Channel Layout Info portion of the magic cookie (as defined in the 
+    // ALACMagicCookieDescription.txt document) is unused by the decoder. 
+    
+Exit:
+	return status;
+}
+
+/*
+	Decode()
+	- the decoded samples are interleaved into the output buffer in the order they arrive in
+	  the bitstream
+*/
+int32_t ALACDecoder::Decode( BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples )
+{
+	BitBuffer			shiftBits;
+	uint32_t            bits1, bits2;
+	uint8_t				tag;
+	uint8_t				elementInstanceTag;
+	AGParamRec			agParams;
+	uint32_t				channelIndex;
+	int16_t				coefsU[32];		// max possible size is 32 although NUMCOEPAIRS is the current limit
+	int16_t				coefsV[32];
+	uint8_t				numU, numV;
+	uint8_t				mixBits;
+	int8_t				mixRes;
+	uint16_t			unusedHeader;
+	uint8_t				escapeFlag;
+	uint32_t			chanBits;
+	uint8_t				bytesShifted;
+	uint32_t			shift;
+	uint8_t				modeU, modeV;
+	uint32_t			denShiftU, denShiftV;
+	uint16_t			pbFactorU, pbFactorV;
+	uint16_t			pb;
+	int16_t *			samples;
+	int16_t *			out16;
+	uint8_t *			out20;
+	uint8_t *			out24;
+	int32_t *			out32;
+	uint8_t				headerByte;
+	uint8_t				partialFrame;
+	uint32_t			extraBits;
+	int32_t				val;
+	uint32_t			i, j;
+	int32_t             status;
+	
+	RequireAction( (bits != nil) && (sampleBuffer != nil) && (outNumSamples != nil), return kALAC_ParamError; );
+	RequireAction( numChannels > 0, return kALAC_ParamError; );
+
+	mActiveElements = 0;
+	channelIndex	= 0;
+	
+	samples = (int16_t *) sampleBuffer;
+
+	status = ALAC_noErr;
+	*outNumSamples = numSamples;
+
+	while ( status == ALAC_noErr )
+	{
+		// bail if we ran off the end of the buffer
+    	RequireAction( bits->cur < bits->end, status = kALAC_ParamError; goto Exit; );
+
+		// copy global decode params for this element
+		pb = mConfig.pb;
+
+		// read element tag
+		tag = BitBufferReadSmall( bits, 3 );
+		switch ( tag )
+		{
+			case ID_SCE:
+			case ID_LFE:
+			{
+				// mono/LFE channel
+				elementInstanceTag = BitBufferReadSmall( bits, 4 );
+				mActiveElements |= (1u << elementInstanceTag);
+
+				// read the 12 unused header bits
+				unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
+				RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
+
+				// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
+				headerByte = (uint8_t) BitBufferRead( bits, 4 );
+				
+				partialFrame = headerByte >> 3;
+				
+				bytesShifted = (headerByte >> 1) & 0x3u;
+				RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
+
+				shift = bytesShifted * 8;
+
+				escapeFlag = headerByte & 0x1;
+
+				chanBits = mConfig.bitDepth - (bytesShifted * 8);
+				
+				// check for partial frame to override requested numSamples
+				if ( partialFrame != 0 )
+				{
+					numSamples  = BitBufferRead( bits, 16 ) << 16;
+					numSamples |= BitBufferRead( bits, 16 );
+				}
+
+				if ( escapeFlag == 0 )
+				{
+					// compressed frame, read rest of parameters
+					mixBits	= (uint8_t) BitBufferRead( bits, 8 );
+					mixRes	= (int8_t) BitBufferRead( bits, 8 );
+					//Assert( (mixBits == 0) && (mixRes == 0) );		// no mixing for mono
+
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					modeU		= headerByte >> 4;
+					denShiftU	= headerByte & 0xfu;
+					
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					pbFactorU	= headerByte >> 5;
+					numU		= headerByte & 0x1fu;
+
+					for ( i = 0; i < numU; i++ )
+						coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
+					
+					// if shift active, skip the the shift buffer but remember where it starts
+					if ( bytesShifted != 0 )
+					{
+						shiftBits = *bits;
+						BitBufferAdvance( bits, (bytesShifted * 8) * numSamples ); 
+					}
+
+					// decompress
+					set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
+					status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 );
+					RequireNoErr( status, goto Exit; );
+
+					if ( modeU == 0 )
+					{
+						unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
+					}
+					else
+					{
+						// the special "numActive == 31" mode can be done in-place
+						unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
+						unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
+					}
+				}
+				else
+				{
+					//Assert( bytesShifted == 0 );
+
+					// uncompressed frame, copy data into the mix buffer to use common output code
+					shift = 32 - chanBits;
+					if ( chanBits <= 16 )
+					{
+						for ( i = 0; i < numSamples; i++ )
+						{
+							val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
+							val = (val << shift) >> shift;
+							mMixBufferU[i] = val;
+						}
+					}
+					else
+					{
+						// BitBufferRead() can't read more than 16 bits at a time so break up the reads
+						extraBits = chanBits - 16;
+						for ( i = 0; i < numSamples; i++ )
+						{
+							val = (int32_t) BitBufferRead( bits, 16 );
+							val = (val << 16) >> shift;
+							mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t) extraBits );
+						}
+					}
+
+					mixBits = mixRes = 0;
+					bits1 = chanBits * numSamples;
+					bytesShifted = 0;
+				}
+
+				// now read the shifted values into the shift buffer
+				if ( bytesShifted != 0 )
+				{
+					shift = bytesShifted * 8;
+					//Assert( shift <= 16 );
+
+					for ( i = 0; i < numSamples; i++ )
+						mShiftBuffer[i] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
+				}
+
+				// convert 32-bit integers into output buffer
+				switch ( mConfig.bitDepth )
+				{
+					case 16:
+						out16 = &((int16_t *)sampleBuffer)[channelIndex];
+						for ( i = 0, j = 0; i < numSamples; i++, j += numChannels )
+							out16[j] = (int16_t) mMixBufferU[i];
+						break;
+					case 20:
+						out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
+						copyPredictorTo20( mMixBufferU, out20, numChannels, numSamples );
+						break;
+					case 24:
+						out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
+						if ( bytesShifted != 0 )
+							copyPredictorTo24Shift( mMixBufferU, mShiftBuffer, out24, numChannels, numSamples, bytesShifted );
+						else
+							copyPredictorTo24( mMixBufferU, out24, numChannels, numSamples );							
+						break;
+					case 32:
+						out32 = &((int32_t *)sampleBuffer)[channelIndex];
+						if ( bytesShifted != 0 )
+							copyPredictorTo32Shift( mMixBufferU, mShiftBuffer, out32, numChannels, numSamples, bytesShifted );
+						else
+							copyPredictorTo32( mMixBufferU, out32, numChannels, numSamples);
+						break;
+				}
+
+				channelIndex += 1;
+				*outNumSamples = numSamples;
+				break;
+			}
+
+			case ID_CPE:
+			{
+				// if decoding this pair would take us over the max channels limit, bail
+				if ( (channelIndex + 2) > numChannels )
+					goto NoMoreChannels;
+
+				// stereo channel pair
+				elementInstanceTag = BitBufferReadSmall( bits, 4 );
+				mActiveElements |= (1u << elementInstanceTag);
+
+				// read the 12 unused header bits
+				unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
+				RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
+
+				// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
+				headerByte = (uint8_t) BitBufferRead( bits, 4 );
+				
+				partialFrame = headerByte >> 3;
+				
+				bytesShifted = (headerByte >> 1) & 0x3u;
+				RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
+
+				shift = bytesShifted * 8;
+
+				escapeFlag = headerByte & 0x1;
+
+				chanBits = mConfig.bitDepth - (bytesShifted * 8) + 1;
+				
+				// check for partial frame length to override requested numSamples
+				if ( partialFrame != 0 )
+				{
+					numSamples  = BitBufferRead( bits, 16 ) << 16;
+					numSamples |= BitBufferRead( bits, 16 );
+				}
+
+				if ( escapeFlag == 0 )
+				{
+					// compressed frame, read rest of parameters
+					mixBits		= (uint8_t) BitBufferRead( bits, 8 );
+					mixRes		= (int8_t) BitBufferRead( bits, 8 );
+
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					modeU		= headerByte >> 4;
+					denShiftU	= headerByte & 0xfu;
+					
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					pbFactorU	= headerByte >> 5;
+					numU		= headerByte & 0x1fu;
+					for ( i = 0; i < numU; i++ )
+						coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
+
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					modeV		= headerByte >> 4;
+					denShiftV	= headerByte & 0xfu;
+					
+					headerByte	= (uint8_t) BitBufferRead( bits, 8 );
+					pbFactorV	= headerByte >> 5;
+					numV		= headerByte & 0x1fu;
+					for ( i = 0; i < numV; i++ )
+						coefsV[i] = (int16_t) BitBufferRead( bits, 16 );
+
+					// if shift active, skip the interleaved shifted values but remember where they start
+					if ( bytesShifted != 0 )
+					{
+						shiftBits = *bits;
+						BitBufferAdvance( bits, (bytesShifted * 8) * 2 * numSamples );
+					}
+
+					// decompress and run predictor for "left" channel
+					set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
+					status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 );
+					RequireNoErr( status, goto Exit; );
+
+					if ( modeU == 0 )
+					{
+						unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
+					}
+					else
+					{
+						// the special "numActive == 31" mode can be done in-place
+						unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
+						unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
+					}
+
+					// decompress and run predictor for "right" channel
+					set_ag_params( &agParams, mConfig.mb, (pb * pbFactorV) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
+					status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits2 );
+					RequireNoErr( status, goto Exit; );
+
+					if ( modeV == 0 )
+					{
+						unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
+					}
+					else
+					{
+						// the special "numActive == 31" mode can be done in-place
+						unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
+						unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
+					}
+				}
+				else
+				{
+					//Assert( bytesShifted == 0 );
+
+					// uncompressed frame, copy data into the mix buffers to use common output code
+					chanBits = mConfig.bitDepth;
+					shift = 32 - chanBits;
+					if ( chanBits <= 16 )
+					{
+						for ( i = 0; i < numSamples; i++ )
+						{
+							val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
+							val = (val << shift) >> shift;
+							mMixBufferU[i] = val;
+
+							val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
+							val = (val << shift) >> shift;
+							mMixBufferV[i] = val;
+						}
+					}
+					else
+					{
+						// BitBufferRead() can't read more than 16 bits at a time so break up the reads
+						extraBits = chanBits - 16;
+						for ( i = 0; i < numSamples; i++ )
+						{
+							val = (int32_t) BitBufferRead( bits, 16 );
+							val = (val << 16) >> shift;
+							mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
+
+							val = (int32_t) BitBufferRead( bits, 16 );
+							val = (val << 16) >> shift;
+							mMixBufferV[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
+						}
+					}
+
+					bits1 = chanBits * numSamples;
+					bits2 = chanBits * numSamples;
+					mixBits = mixRes = 0;
+					bytesShifted = 0;
+				}
+
+				// now read the shifted values into the shift buffer
+				if ( bytesShifted != 0 )
+				{
+					shift = bytesShifted * 8;
+					//Assert( shift <= 16 );
+
+					for ( i = 0; i < (numSamples * 2); i += 2 )
+					{
+						mShiftBuffer[i + 0] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
+						mShiftBuffer[i + 1] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
+					}
+				}
+
+				// un-mix the data and convert to output format
+				// - note that mixRes = 0 means just interleave so we use that path for uncompressed frames
+				switch ( mConfig.bitDepth )
+				{
+					case 16:
+						out16 = &((int16_t *)sampleBuffer)[channelIndex];
+						unmix16( mMixBufferU, mMixBufferV, out16, numChannels, numSamples, mixBits, mixRes );
+						break;
+					case 20:
+						out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
+						unmix20( mMixBufferU, mMixBufferV, out20, numChannels, numSamples, mixBits, mixRes );
+						break;
+					case 24:
+						out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
+						unmix24( mMixBufferU, mMixBufferV, out24, numChannels, numSamples,
+									mixBits, mixRes, mShiftBuffer, bytesShifted );
+						break;
+					case 32:
+						out32 = &((int32_t *)sampleBuffer)[channelIndex];
+						unmix32( mMixBufferU, mMixBufferV, out32, numChannels, numSamples,
+									mixBits, mixRes, mShiftBuffer, bytesShifted );
+						break;
+				}
+
+				channelIndex += 2;
+				*outNumSamples = numSamples;
+				break;
+			}
+
+			case ID_CCE:
+			case ID_PCE:
+			{
+				// unsupported element, bail
+				//AssertNoErr( tag );
+				status = kALAC_ParamError;
+				break;
+			}
+
+			case ID_DSE:
+			{
+				// data stream element -- parse but ignore
+				status = this->DataStreamElement( bits );
+				break;
+			}
+			
+			case ID_FIL:
+			{
+				// fill element -- parse but ignore
+				status = this->FillElement( bits );
+				break;
+			}
+
+			case ID_END:
+			{
+				// frame end, all done so byte align the frame and check for overruns
+				BitBufferByteAlign( bits, false );
+				//Assert( bits->cur == bits->end );
+				goto Exit;
+			}
+		}
+
+#if ! DEBUG
+		// if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits)
+		// - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits
+		if ( channelIndex >= numChannels )
+			break;
+#endif
+	}
+
+NoMoreChannels:
+
+	// if we get here and haven't decoded all of the requested channels, fill the remaining channels with zeros
+	for ( ; channelIndex < numChannels; channelIndex++ )
+	{
+		switch ( mConfig.bitDepth )
+		{
+			case 16:
+			{
+				int16_t *	fill16 = &((int16_t *)sampleBuffer)[channelIndex];
+				Zero16( fill16, numSamples, numChannels );
+				break;
+			}
+			case 24:
+			{
+				uint8_t *	fill24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
+				Zero24( fill24, numSamples, numChannels );
+				break;
+			}
+			case 32:
+			{
+				int32_t *	fill32 = &((int32_t *)sampleBuffer)[channelIndex];
+				Zero32( fill32, numSamples, numChannels );
+				break;
+			}
+		}
+	}
+
+Exit:
+	return status;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+/*
+	FillElement()
+	- they're just filler so we don't need 'em
+*/
+int32_t ALACDecoder::FillElement( BitBuffer * bits )
+{
+	int16_t		count;
+	
+	// 4-bit count or (4-bit + 8-bit count) if 4-bit count == 15
+	// - plus this weird -1 thing I still don't fully understand
+	count = BitBufferReadSmall( bits, 4 );
+	if ( count == 15 )
+		count += (int16_t) BitBufferReadSmall( bits, 8 ) - 1;
+
+	BitBufferAdvance( bits, count * 8 );
+
+	RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
+
+	return ALAC_noErr;	
+}
+
+/*
+	DataStreamElement()
+	- we don't care about data stream elements so just skip them
+*/
+int32_t ALACDecoder::DataStreamElement( BitBuffer * bits )
+{
+	uint8_t		element_instance_tag;
+	int32_t		data_byte_align_flag;
+	uint16_t		count;
+	
+	// the tag associates this data stream element with a given audio element
+	element_instance_tag = BitBufferReadSmall( bits, 4 );
+	
+	data_byte_align_flag = BitBufferReadOne( bits );
+
+	// 8-bit count or (8-bit + 8-bit count) if 8-bit count == 255
+	count = BitBufferReadSmall( bits, 8 );
+	if ( count == 255 )
+		count += BitBufferReadSmall( bits, 8 );
+
+	// the align flag means the bitstream should be byte-aligned before reading the following data bytes
+	if ( data_byte_align_flag )
+		BitBufferByteAlign( bits, false );
+
+	// skip the data bytes
+	BitBufferAdvance( bits, count * 8 );
+
+	RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
+
+	return ALAC_noErr;
+}
+
+/*
+	ZeroN()
+	- helper routines to clear out output channel buffers when decoding fewer channels than requested
+*/
+static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride )
+{
+	if ( stride == 1 )
+	{
+		memset( buffer, 0, numItems * sizeof(int16_t) );
+	}
+	else
+	{
+		for ( uint32_t index = 0; index < (numItems * stride); index += stride )
+			buffer[index] = 0;
+	}
+}
+
+static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride )
+{
+	if ( stride == 1 )
+	{
+		memset( buffer, 0, numItems * 3 );
+	}
+	else
+	{
+		for ( uint32_t index = 0; index < (numItems * stride * 3); index += (stride * 3) )
+		{
+			buffer[index + 0] = 0;
+			buffer[index + 1] = 0;
+			buffer[index + 2] = 0;
+		}
+	}
+}
+
+static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride )
+{
+	if ( stride == 1 )
+	{
+		memset( buffer, 0, numItems * sizeof(int32_t) );
+	}
+	else
+	{
+		for ( uint32_t index = 0; index < (numItems * stride); index += stride )
+			buffer[index] = 0;
+	}
+}

+ 65 - 0
components/spotify/cspot/bell/external/alac/codec/ALACDecoder.h

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACDecoder.h
+*/
+
+#ifndef _ALACDECODER_H
+#define _ALACDECODER_H
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#include <stdint.h>
+
+#include "ALACAudioTypes.h"
+
+struct BitBuffer;
+
+class ALACDecoder
+{
+	public:
+		ALACDecoder();
+		~ALACDecoder();
+
+		int32_t	Init( void * inMagicCookie, uint32_t inMagicCookieSize );
+		int32_t	Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
+
+	public:
+		// decoding parameters (public for use in the analyzer)
+		ALACSpecificConfig		mConfig;
+
+	protected:
+		int32_t	FillElement( struct BitBuffer * bits );
+		int32_t	DataStreamElement( struct BitBuffer * bits );
+
+		uint16_t					mActiveElements;
+
+		// decoding buffers
+		int32_t *				mMixBufferU;
+		int32_t *				mMixBufferV;
+		int32_t *				mPredictor;
+		uint16_t *				mShiftBuffer;	// note: this points to mPredictor's memory but different
+												//		 variable for clarity and type difference
+};
+
+#endif	/* _ALACDECODER_H */

+ 1432 - 0
components/spotify/cspot/bell/external/alac/codec/ALACEncoder.cpp

@@ -0,0 +1,1432 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACEncoder.cpp
+*/
+
+// build stuff
+#define VERBOSE_DEBUG		0
+
+// headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ALACEncoder.h"
+
+#include "aglib.h"
+#include "dplib.h"
+#include "matrixlib.h"
+
+#include "ALACBitUtilities.h"
+#include "ALACAudioTypes.h"
+#include "EndianPortable.h"
+
+#if (__GNUC__) > 4 || defined (__APPLE__)
+#pragma GCC diagnostic ignored "-Wunused-const-variable"
+#endif
+#if !defined(__APPLE__) 
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+
+// Note: in C you can't typecast to a 2-dimensional array pointer but that's what we need when
+// picking which coefs to use so we declare this typedef b/c we *can* typecast to this type
+typedef int16_t (*SearchCoefs)[kALACMaxCoefs];
+
+// defines/constants
+const uint32_t kALACEncoderMagic	= 'dpge';
+const uint32_t kMaxSampleSize		= 32;			// max allowed bit width is 32
+const uint32_t kDefaultMixBits	= 2;
+const uint32_t kDefaultMixRes		= 0;
+const uint32_t kMaxRes			= 4;
+const uint32_t kDefaultNumUV		= 8;
+const uint32_t kMinUV				= 4;
+const uint32_t kMaxUV				= 8;
+
+// static functions
+#if VERBOSE_DEBUG
+static void AddFiller( BitBuffer * bits, int32_t numBytes );
+#endif
+
+
+/*
+	Map Format: 3-bit field per channel which is the same as the "element tag" that should be placed
+				at the beginning of the frame for that channel.  Indicates whether SCE, CPE, or LFE.
+				Each particular field is accessed via the current channel index.  Note that the channel
+				index increments by two for channel pairs.
+				
+	For example:
+	
+			C L R 3-channel input		= (ID_CPE << 3) | (ID_SCE)
+				index 0 value = (map & (0x7ul << (0 * 3))) >> (0 * 3)
+				index 1 value = (map & (0x7ul << (1 * 3))) >> (1 * 3)
+
+			C L R Ls Rs LFE 5.1-channel input = (ID_LFE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE)
+				index 0 value = (map & (0x7ul << (0 * 3))) >> (0 * 3)
+				index 1 value = (map & (0x7ul << (1 * 3))) >> (1 * 3)
+				index 3 value = (map & (0x7ul << (3 * 3))) >> (3 * 3)
+				index 5 value = (map & (0x7ul << (5 * 3))) >> (5 * 3)
+				index 7 value = (map & (0x7ul << (7 * 3))) >> (7 * 3)
+*/
+static const uint32_t	sChannelMaps[kALACMaxChannels] =
+{
+	ID_SCE,
+	ID_CPE,
+	(ID_CPE << 3) | (ID_SCE),
+	(ID_SCE << 9) | (ID_CPE << 3) | (ID_SCE),
+	(ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE),
+	(ID_SCE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE),
+	(ID_SCE << 18) | (ID_SCE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE),
+	(ID_SCE << 21) | (ID_CPE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE)
+};
+
+static const uint32_t sSupportediPodSampleRates[] =
+{
+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+};
+
+/*
+	Constructor
+*/
+ALACEncoder::ALACEncoder() :
+	mBitDepth( 0 ),
+    mFastMode( 0 ),
+	mMixBufferU( nil ),
+	mMixBufferV( nil ),
+	mPredictorU( nil ),
+	mPredictorV( nil ),
+	mShiftBufferUV( nil ),
+	mWorkBuffer( nil ),
+
+
+	mTotalBytesGenerated( 0 ),
+	mAvgBitRate( 0 ),
+	mMaxFrameBytes( 0 )
+{
+	// overrides
+	mFrameSize = kALACDefaultFrameSize;
+}
+
+/*
+	Destructor
+*/
+ALACEncoder::~ALACEncoder()
+{
+	// delete the matrix mixing buffers
+	if ( mMixBufferU )
+    {
+		free(mMixBufferU);
+        mMixBufferU = NULL;
+    }
+	if ( mMixBufferV )
+    {
+		free(mMixBufferV);
+        mMixBufferV = NULL;
+    }
+	
+	// delete the dynamic predictor's "corrector" buffers
+	if ( mPredictorU )
+    {
+		free(mPredictorU);
+        mPredictorU = NULL;
+    }
+	if ( mPredictorV )
+    {
+		free(mPredictorV);
+        mPredictorV = NULL;
+    }
+
+	// delete the unused byte shift buffer
+	if ( mShiftBufferUV )
+    {
+		free(mShiftBufferUV);
+        mShiftBufferUV = NULL;
+    }
+
+	// delete the work buffer
+	if ( mWorkBuffer )
+    {
+		free(mWorkBuffer);
+        mWorkBuffer = NULL;
+    }	
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+/*
+	HEADER SPECIFICATION  
+
+        For every segment we adopt the following header:
+        
+			1 byte reserved			(always 0)
+			1 byte flags			(see below)
+			[4 byte frame length]	(optional, see below)
+			     ---Next, the per-segment ALAC parameters---
+			1 byte mixBits			(middle-side parameter)
+			1 byte mixRes			(middle-side parameter, interpreted as signed char)
+
+			1 byte shiftU			(4 bits modeU, 4 bits denShiftU)
+			1 byte filterU			(3 bits pbFactorU, 5 bits numU)
+			(numU) shorts			(signed DP coefficients for V channel)
+			     ---Next, 2nd-channel ALAC parameters in case of stereo mode---
+			1 byte shiftV			(4 bits modeV, 4 bits denShiftV)
+			1 byte filterV			(3 bits pbFactorV, 5 bits numV)
+			(numV) shorts			(signed DP coefficients for V channel)
+			     ---After this come the shift-off bytes for (>= 24)-bit data (n-byte shift) if indicated---
+			     ---Then comes the AG-compressor bitstream---
+
+
+        FLAGS
+        -----
+
+		The presence of certain flag bits changes the header format such that the parameters might
+		not even be sent.  The currently defined flags format is:
+
+			0000psse
+			
+			where		0 	= reserved, must be 0
+						p	= 1-bit field "partial frame" flag indicating 32-bit frame length follows this byte
+						ss	= 2-bit field indicating "number of shift-off bytes ignored by compression"
+						e	= 1-bit field indicating "escape"
+
+		The "partial frame" flag means that the following segment is not equal to the frame length specified
+		in the out-of-band decoder configuration.  This allows the decoder to deal with end-of-file partial
+		segments without incurring the 32-bit overhead for each segment.
+
+		The "shift-off" field indicates the number of bytes at the bottom of the word that were passed through
+		uncompressed.  The reason for this is that the entropy inherent in the LS bytes of >= 24-bit words
+		quite often means that the frame would have to be "escaped" b/c the compressed size would be >= the
+		uncompressed size.  However, by shifting the input values down and running the remaining bits through
+		the normal compression algorithm, a net win can be achieved.  If this field is non-zero, it means that
+		the shifted-off bytes follow after the parameter section of the header and before the compressed
+		bitstream.  Note that doing this also allows us to use matrixing on 32-bit inputs after one or more
+		bytes are shifted off the bottom which helps the eventual compression ratio.  For stereo channels,
+		the shifted off bytes are interleaved.
+
+        The "escape" flag means that this segment was not compressed b/c the compressed size would be
+        >= uncompressed size.  In that case, the audio data was passed through uncompressed after the header.
+        The other header parameter bytes will not be sent.
+        
+
+		PARAMETERS
+		----------
+
+		If the segment is not a partial or escape segment, the total header size (in bytes) is given exactly by:
+
+			4 + (2 + 2 * numU)                   (mono mode)
+			4 + (2 + 2 * numV) + (2 + 2 * numV)  (stereo mode)
+
+        where the ALAC filter-lengths numU, numV are bounded by a
+        constant (in the current source, numU, numV <= NUMCOEPAIRS), and
+        this forces an absolute upper bound on header size.
+
+        Each segment-decode process loads up these bytes from the front of the
+        local stream, in the above order, then follows with the entropy-encoded
+        bits for the given segment.
+
+        To generalize middle-side, there are various mixing modes including middle-side, each lossless,
+        as embodied in the mix() and unmix() functions.  These functions exploit a generalized middle-side
+        transformation:
+
+        u := [(rL + (m-r)R)/m];
+        v := L - R;
+
+        where [ ] denotes integer floor.  The (lossless) inverse is
+
+        L = u + v - [rV/m];
+        R = L - v;
+
+        In the segment header, m and r are encoded in mixBits and mixRes.
+        Classical "middle-side" is obtained with m = 2, r = 1, but now
+        we have more generalized mixes.
+
+        NOTES
+        -----
+        The relevance of the ALAC coefficients is explained in detail
+        in patent documents.
+*/
+
+/*
+	EncodeStereo()
+	- encode a channel pair
+*/
+int32_t ALACEncoder::EncodeStereo( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples )
+{
+	BitBuffer		workBits;
+	BitBuffer		startBits = *bitstream;			// squirrel away copy of current state in case we need to go back and do an escape packet
+	AGParamRec		agParams;
+	uint32_t          bits1, bits2;
+	uint32_t			dilate;
+	int32_t			mixBits, mixRes, maxRes;
+	uint32_t			minBits, minBits1, minBits2;
+	uint32_t			numU, numV;
+	uint32_t			mode;
+	uint32_t			pbFactor;
+	uint32_t			chanBits;
+	uint32_t			denShift;
+	uint8_t			bytesShifted;
+	SearchCoefs		coefsU;
+	SearchCoefs		coefsV;
+	uint32_t			index;
+	uint8_t			partialFrame;
+	uint32_t			escapeBits;
+	bool			doEscape;
+	int32_t		status = ALAC_noErr;
+
+	// make sure we handle this bit-depth before we get going
+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; );
+
+	// reload coefs pointers for this channel pair
+	// - note that, while you might think they should be re-initialized per block, retaining state across blocks
+	//	 actually results in better overall compression
+	// - strangely, re-using the same coefs for the different passes of the "mixRes" search loop instead of using
+	//	 different coefs for the different passes of "mixRes" results in even better compression
+	coefsU = (SearchCoefs) mCoefsU[channelIndex];
+	coefsV = (SearchCoefs) mCoefsV[channelIndex];
+
+	// matrix encoding adds an extra bit but 32-bit inputs cannot be matrixed b/c 33 is too many
+	// so enable 16-bit "shift off" and encode in 17-bit mode
+	// - in addition, 24-bit mode really improves with one byte shifted off
+	if ( mBitDepth == 32 )
+		bytesShifted = 2;
+	else if ( mBitDepth >= 24 )
+		bytesShifted = 1;
+	else
+		bytesShifted = 0;
+
+	chanBits = mBitDepth - (bytesShifted * 8) + 1;
+	
+	// flag whether or not this is a partial frame
+	partialFrame = (numSamples == mFrameSize) ? 0 : 1;
+
+	// brute-force encode optimization loop
+	// - run over variations of the encoding params to find the best choice
+	mixBits		= kDefaultMixBits;
+	maxRes		= kMaxRes;
+	numU = numV = kDefaultNumUV;
+	denShift	= DENSHIFT_DEFAULT;
+	mode		= 0;
+	pbFactor	= 4;
+	dilate		= 8;
+
+	minBits	= minBits1 = minBits2 = 1ul << 31;
+	
+    int32_t		bestRes = mLastMixRes[channelIndex];
+
+    for ( mixRes = 0; mixRes <= maxRes; mixRes++ )
+    {
+        // mix the stereo inputs
+        switch ( mBitDepth )
+        {
+            case 16:
+                mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, mixBits, mixRes );
+                break;
+            case 20:
+                mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, mixBits, mixRes );
+                break;
+            case 24:
+                // includes extraction of shifted-off bytes
+                mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate,
+                        mixBits, mixRes, mShiftBufferUV, bytesShifted );
+                break;
+            case 32:
+                // includes extraction of shifted-off bytes
+                mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate,
+                        mixBits, mixRes, mShiftBufferUV, bytesShifted );
+                break;
+        }
+
+        BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes );
+        
+        // run the dynamic predictors
+        pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT );
+        pc_block( mMixBufferV, mPredictorV, numSamples/dilate, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT );
+
+        // run the lossless compressor on each channel
+        set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT );
+        status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 );
+        RequireNoErr( status, goto Exit; );
+
+        set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT );
+        status = dyn_comp( &agParams, mPredictorV, &workBits, numSamples/dilate, chanBits, &bits2 );
+        RequireNoErr( status, goto Exit; );
+
+        // look for best match
+        if ( (bits1 + bits2) < minBits1 )
+        {
+            minBits1 = bits1 + bits2;
+            bestRes = mixRes;
+        }
+    }
+    
+    mLastMixRes[channelIndex] = (int16_t)bestRes;
+
+	// mix the stereo inputs with the current best mixRes
+	mixRes = mLastMixRes[channelIndex];
+	switch ( mBitDepth )
+	{
+		case 16:
+			mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes );
+			break;
+		case 20:
+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes );
+			break;
+		case 24:
+			// also extracts the shifted off bytes into the shift buffers
+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples,
+					mixBits, mixRes, mShiftBufferUV, bytesShifted );
+			break;
+		case 32:
+			// also extracts the shifted off bytes into the shift buffers
+			mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples,
+					mixBits, mixRes, mShiftBufferUV, bytesShifted );
+			break;
+	}
+
+	// now it's time for the predictor coefficient search loop
+	numU = numV = kMinUV;
+	minBits1 = minBits2 = 1ul << 31;
+
+	for ( uint32_t numUV = kMinUV; numUV <= kMaxUV; numUV += 4 )
+	{
+		BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes );		
+
+		dilate = 32;
+
+		// run the predictor over the same data multiple times to help it converge
+		for ( uint32_t converge = 0; converge < 8; converge++ )
+		{
+		    pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numUV-1], numUV, chanBits, DENSHIFT_DEFAULT );
+		    pc_block( mMixBufferV, mPredictorV, numSamples/dilate, coefsV[numUV-1], numUV, chanBits, DENSHIFT_DEFAULT );
+		}
+
+		dilate = 8;
+
+		set_ag_params( &agParams, MB0, (pbFactor * PB0)/4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT );
+		status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 );
+
+		if ( (bits1 * dilate + 16 * numUV) < minBits1 )
+		{
+			minBits1 = bits1 * dilate + 16 * numUV;
+			numU = numUV;
+		}
+
+		set_ag_params( &agParams, MB0, (pbFactor * PB0)/4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT );
+		status = dyn_comp( &agParams, mPredictorV, &workBits, numSamples/dilate, chanBits, &bits2 );
+
+		if ( (bits2 * dilate + 16 * numUV) < minBits2 )
+		{
+			minBits2 = bits2 * dilate + 16 * numUV;
+			numV = numUV;
+		}
+	}
+
+	// test for escape hatch if best calculated compressed size turns out to be more than the input size
+	minBits = minBits1 + minBits2 + (8 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0);
+	if ( bytesShifted != 0 )
+		minBits += (numSamples * (bytesShifted * 8) * 2);
+
+	escapeBits = (numSamples * mBitDepth * 2) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */
+
+	doEscape = (minBits >= escapeBits) ? true : false;
+
+	if ( doEscape == false )
+	{
+		// write bitstream header and coefs
+		BitBufferWrite( bitstream, 0, 12 );
+		BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 );
+		if ( partialFrame )
+			BitBufferWrite( bitstream, numSamples, 32 );
+		BitBufferWrite( bitstream, mixBits, 8 );
+		BitBufferWrite( bitstream, mixRes, 8 );
+		
+		//Assert( (mode < 16) && (DENSHIFT_DEFAULT < 16) );
+		//Assert( (pbFactor < 8) && (numU < 32) );
+		//Assert( (pbFactor < 8) && (numV < 32) );
+
+		BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 );
+		BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 );
+		for ( index = 0; index < numU; index++ )
+			BitBufferWrite( bitstream, coefsU[numU - 1][index], 16 );
+
+		BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 );
+		BitBufferWrite( bitstream, (pbFactor << 5) | numV, 8 );
+		for ( index = 0; index < numV; index++ )
+			BitBufferWrite( bitstream, coefsV[numV - 1][index], 16 );
+
+		// if shift active, write the interleaved shift buffers
+		if ( bytesShifted != 0 )
+		{
+			uint32_t		bitShift = bytesShifted * 8;
+
+			//Assert( bitShift <= 16 );
+
+			for ( index = 0; index < (numSamples * 2); index += 2 )
+			{
+				uint32_t			shiftedVal;
+				
+				shiftedVal = ((uint32_t)mShiftBufferUV[index + 0] << bitShift) | (uint32_t)mShiftBufferUV[index + 1];
+				BitBufferWrite( bitstream, shiftedVal, bitShift * 2 );
+			}
+		}
+
+		// run the dynamic predictor and lossless compression for the "left" channel
+		// - note: to avoid allocating more buffers, we're mixing and matching between the available buffers instead
+		//		   of only using "U" buffers for the U-channel and "V" buffers for the V-channel
+		if ( mode == 0 )
+		{
+			pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT );
+		}
+		else
+		{
+			pc_block( mMixBufferU, mPredictorV, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT );
+			pc_block( mPredictorV, mPredictorU, numSamples, nil, 31, chanBits, 0 );
+		}
+
+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT );
+		status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 );
+		RequireNoErr( status, goto Exit; );
+
+		// run the dynamic predictor and lossless compression for the "right" channel
+		if ( mode == 0 )
+		{
+			pc_block( mMixBufferV, mPredictorV, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT );
+		}
+		else
+		{
+			pc_block( mMixBufferV, mPredictorU, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT );
+			pc_block( mPredictorU, mPredictorV, numSamples, nil, 31, chanBits, 0 );
+		}
+
+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT );
+		status = dyn_comp( &agParams, mPredictorV, bitstream, numSamples, chanBits, &bits2 );
+		RequireNoErr( status, goto Exit; );
+
+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be,
+			chuck it and do an escape packet
+		*/
+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits );
+		if ( minBits >= escapeBits )
+		{
+			*bitstream = startBits;		// reset bitstream state
+			doEscape = true;
+			printf( "compressed frame too big: %u vs. %u \n", minBits, escapeBits );
+		}
+	}
+
+	if ( doEscape == true )
+	{
+		/* escape */
+		status = this->EncodeStereoEscape( bitstream, inputBuffer, stride, numSamples );
+
+#if VERBOSE_DEBUG		
+		DebugMsg( "escape!: %lu vs %lu", minBits, escapeBits );
+#endif
+	}
+	
+Exit:
+	return status;
+}
+
+/*
+	EncodeStereoFast()
+	- encode a channel pair without the search loop for maximum possible speed
+*/
+int32_t ALACEncoder::EncodeStereoFast( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples )
+{
+	BitBuffer		startBits = *bitstream;			// squirrel away current bit position in case we decide to use escape hatch
+	AGParamRec		agParams;
+	uint32_t	bits1, bits2;
+	int32_t			mixBits, mixRes;
+	uint32_t			minBits, minBits1, minBits2;
+	uint32_t			numU, numV;
+	uint32_t			mode;
+	uint32_t			pbFactor;
+	uint32_t			chanBits;
+	uint32_t			denShift;
+	uint8_t			bytesShifted;
+	SearchCoefs		coefsU;
+	SearchCoefs		coefsV;
+	uint32_t			index;
+	uint8_t			partialFrame;
+	uint32_t			escapeBits;
+	bool			doEscape;	
+	int32_t		status;
+
+	// make sure we handle this bit-depth before we get going
+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; );
+
+	// reload coefs pointers for this channel pair
+	// - note that, while you might think they should be re-initialized per block, retaining state across blocks
+	//	 actually results in better overall compression
+	// - strangely, re-using the same coefs for the different passes of the "mixRes" search loop instead of using
+	//	 different coefs for the different passes of "mixRes" results in even better compression
+	coefsU = (SearchCoefs) mCoefsU[channelIndex];
+	coefsV = (SearchCoefs) mCoefsV[channelIndex];
+
+	// matrix encoding adds an extra bit but 32-bit inputs cannot be matrixed b/c 33 is too many
+	// so enable 16-bit "shift off" and encode in 17-bit mode
+	// - in addition, 24-bit mode really improves with one byte shifted off
+	if ( mBitDepth == 32 )
+		bytesShifted = 2;
+	else if ( mBitDepth >= 24 )
+		bytesShifted = 1;
+	else
+		bytesShifted = 0;
+
+	chanBits = mBitDepth - (bytesShifted * 8) + 1;
+	
+	// flag whether or not this is a partial frame
+	partialFrame = (numSamples == mFrameSize) ? 0 : 1;
+
+	// set up default encoding parameters for "fast" mode
+	mixBits		= kDefaultMixBits;
+	mixRes		= kDefaultMixRes;
+	numU = numV = kDefaultNumUV;
+	denShift	= DENSHIFT_DEFAULT;
+	mode		= 0;
+	pbFactor	= 4;
+
+	minBits	= minBits1 = minBits2 = 1ul << 31;
+	
+	// mix the stereo inputs with default mixBits/mixRes
+	switch ( mBitDepth )
+	{
+		case 16:
+			mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes );
+			break;
+		case 20:
+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes );
+			break;
+		case 24:
+			// also extracts the shifted off bytes into the shift buffers
+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples,
+					mixBits, mixRes, mShiftBufferUV, bytesShifted );
+			break;
+		case 32:
+			// also extracts the shifted off bytes into the shift buffers
+			mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples,
+					mixBits, mixRes, mShiftBufferUV, bytesShifted );
+			break;
+	}
+
+	/* speculatively write the bitstream assuming the compressed version will be smaller */
+
+	// write bitstream header and coefs
+	BitBufferWrite( bitstream, 0, 12 );
+	BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 );
+	if ( partialFrame )
+		BitBufferWrite( bitstream, numSamples, 32 );
+	BitBufferWrite( bitstream, mixBits, 8 );
+	BitBufferWrite( bitstream, mixRes, 8 );
+	
+	//Assert( (mode < 16) && (DENSHIFT_DEFAULT < 16) );
+	//Assert( (pbFactor < 8) && (numU < 32) );
+	//Assert( (pbFactor < 8) && (numV < 32) );
+
+	BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 );
+	BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 );
+	for ( index = 0; index < numU; index++ )
+		BitBufferWrite( bitstream, coefsU[numU - 1][index], 16 );
+
+	BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 );
+	BitBufferWrite( bitstream, (pbFactor << 5) | numV, 8 );
+	for ( index = 0; index < numV; index++ )
+		BitBufferWrite( bitstream, coefsV[numV - 1][index], 16 );
+
+	// if shift active, write the interleaved shift buffers
+	if ( bytesShifted != 0 )
+	{
+		uint32_t		bitShift = bytesShifted * 8;
+
+		//Assert( bitShift <= 16 );
+
+		for ( index = 0; index < (numSamples * 2); index += 2 )
+		{
+			uint32_t			shiftedVal;
+			
+			shiftedVal = ((uint32_t)mShiftBufferUV[index + 0] << bitShift) | (uint32_t)mShiftBufferUV[index + 1];
+			BitBufferWrite( bitstream, shiftedVal, bitShift * 2 );
+		}
+	}
+
+	// run the dynamic predictor and lossless compression for the "left" channel
+	// - note: we always use mode 0 in the "fast" path so we don't need the code for mode != 0
+	pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT );
+
+	set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT );
+	status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 );
+	RequireNoErr( status, goto Exit; );
+
+	// run the dynamic predictor and lossless compression for the "right" channel
+	pc_block( mMixBufferV, mPredictorV, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT );
+
+	set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT );
+	status = dyn_comp( &agParams, mPredictorV, bitstream, numSamples, chanBits, &bits2 );
+	RequireNoErr( status, goto Exit; );
+
+	// do bit requirement calculations
+	minBits1 = bits1 + (numU * sizeof(int16_t) * 8);
+	minBits2 = bits2 + (numV * sizeof(int16_t) * 8);
+
+	// test for escape hatch if best calculated compressed size turns out to be more than the input size
+	minBits = minBits1 + minBits2 + (8 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0);
+	if ( bytesShifted != 0 )
+		minBits += (numSamples * (bytesShifted * 8) * 2);
+
+	escapeBits = (numSamples * mBitDepth * 2) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */
+
+	doEscape = (minBits >= escapeBits) ? true : false;
+
+	if ( doEscape == false )
+	{
+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be,
+			chuck it and do an escape packet
+		*/
+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits );
+		if ( minBits >= escapeBits )
+		{
+			doEscape = true;
+			printf( "compressed frame too big: %u vs. %u\n", minBits, escapeBits );
+		}
+
+	}
+
+	if ( doEscape == true )
+	{
+		/* escape */
+
+		// reset bitstream position since we speculatively wrote the compressed version
+		*bitstream = startBits;
+
+		// write escape frame
+		status = this->EncodeStereoEscape( bitstream, inputBuffer, stride, numSamples );
+
+#if VERBOSE_DEBUG		
+		DebugMsg( "escape!: %u vs %u", minBits, (numSamples * mBitDepth * 2) );
+#endif
+	}
+	
+Exit:
+	return status;
+}
+
+/*
+	EncodeStereoEscape()
+	- encode stereo escape frame
+*/
+int32_t ALACEncoder::EncodeStereoEscape( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t numSamples )
+{
+	int16_t *		input16;
+	int32_t *		input32;
+	uint8_t			partialFrame;
+	uint32_t			index;
+
+	// flag whether or not this is a partial frame
+	partialFrame = (numSamples == mFrameSize) ? 0 : 1;
+
+	// write bitstream header
+	BitBufferWrite( bitstream, 0, 12 );
+	BitBufferWrite( bitstream, (partialFrame << 3) | 1, 4 );	// LSB = 1 means "frame not compressed"
+	if ( partialFrame )
+		BitBufferWrite( bitstream, numSamples, 32 );
+
+	// just copy the input data to the output buffer
+	switch ( mBitDepth )
+	{
+		case 16:
+			input16 = (int16_t *) inputBuffer;
+			
+			for ( index = 0; index < (numSamples * stride); index += stride )
+			{
+				BitBufferWrite( bitstream, input16[index + 0], 16 );
+				BitBufferWrite( bitstream, input16[index + 1], 16 );
+			}
+			break;
+		case 20:
+			// mix20() with mixres param = 0 means de-interleave so use it to simplify things
+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 0, 0 );
+			for ( index = 0; index < numSamples; index++ )
+			{
+				BitBufferWrite( bitstream, mMixBufferU[index], 20 );
+				BitBufferWrite( bitstream, mMixBufferV[index], 20 );
+			}				
+			break;
+		case 24:
+			// mix24() with mixres param = 0 means de-interleave so use it to simplify things
+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 0, 0, mShiftBufferUV, 0 );
+			for ( index = 0; index < numSamples; index++ )
+			{
+				BitBufferWrite( bitstream, mMixBufferU[index], 24 );
+				BitBufferWrite( bitstream, mMixBufferV[index], 24 );
+			}				
+			break;
+		case 32:
+			input32 = (int32_t *) inputBuffer;
+
+			for ( index = 0; index < (numSamples * stride); index += stride )
+			{
+				BitBufferWrite( bitstream, input32[index + 0], 32 );
+				BitBufferWrite( bitstream, input32[index + 1], 32 );
+			}				
+			break;
+	}
+	
+	return ALAC_noErr;
+}
+
+/*
+	EncodeMono()
+	- encode a mono input buffer
+*/
+int32_t ALACEncoder::EncodeMono( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples )
+{
+	BitBuffer		startBits = *bitstream;			// squirrel away copy of current state in case we need to go back and do an escape packet
+	AGParamRec		agParams;
+	uint32_t	bits1;
+	uint32_t			numU;
+	SearchCoefs		coefsU;
+	uint32_t			dilate;
+	uint32_t			minBits, bestU;
+	uint32_t			minU, maxU;
+	uint32_t			index, index2;
+	uint8_t			bytesShifted;
+	uint32_t			shift;
+	uint32_t			mask;
+	uint32_t			chanBits;
+	uint8_t			pbFactor;
+	uint8_t			partialFrame;
+	int16_t *		input16;
+	int32_t *		input32;
+	uint32_t			escapeBits;
+	bool			doEscape;
+	int32_t		status;
+
+	// make sure we handle this bit-depth before we get going
+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; );
+
+	status = ALAC_noErr;
+	
+	// reload coefs array from previous frame
+	coefsU = (SearchCoefs) mCoefsU[channelIndex];
+
+	// pick bit depth for actual encoding
+	// - we lop off the lower byte(s) for 24-/32-bit encodings
+	if ( mBitDepth == 32 )
+		bytesShifted = 2;
+	else if ( mBitDepth >= 24 )
+		bytesShifted = 1;
+	else
+		bytesShifted = 0;
+
+	shift = bytesShifted * 8;
+	mask = (1ul << shift) - 1;
+	chanBits = mBitDepth - (bytesShifted * 8);
+
+	// flag whether or not this is a partial frame
+	partialFrame = (numSamples == mFrameSize) ? 0 : 1;
+
+	// convert N-bit data to 32-bit for predictor
+	switch ( mBitDepth )
+	{
+		case 16:
+		{
+			// convert 16-bit data to 32-bit for predictor
+			input16 = (int16_t *) inputBuffer;
+			for ( index = 0, index2 = 0; index < numSamples; index++, index2 += stride )
+				mMixBufferU[index] = (int32_t) input16[index2];
+			break;
+		}
+		case 20:
+			// convert 20-bit data to 32-bit for predictor
+			copy20ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples );
+			break;
+		case 24:
+			// convert 24-bit data to 32-bit for the predictor and extract the shifted off byte(s)
+			copy24ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples );
+			for ( index = 0; index < numSamples; index++ )
+			{
+				mShiftBufferUV[index] = (uint16_t)(mMixBufferU[index] & mask);
+				mMixBufferU[index] >>= shift;
+			}
+			break;
+		case 32:
+		{
+			// just copy the 32-bit input data for the predictor and extract the shifted off byte(s)
+			input32 = (int32_t *) inputBuffer;
+
+			for ( index = 0, index2 = 0; index < numSamples; index++, index2 += stride )
+			{
+				int32_t			val = input32[index2];
+				
+				mShiftBufferUV[index] = (uint16_t)(val & mask);
+				mMixBufferU[index] = val >> shift;
+			}
+			break;
+		}
+	}
+
+	// brute-force encode optimization loop (implied "encode depth" of 0 if comparing to cmd line tool)
+	// - run over variations of the encoding params to find the best choice
+	minU		= 4;
+	maxU		= 8;
+	minBits		= 1ul << 31;
+	pbFactor	= 4;
+	
+	minBits	= 1ul << 31;
+	bestU	= minU;
+
+	for ( numU = minU; numU <= maxU; numU += 4 )
+	{
+		BitBuffer		workBits;
+		uint32_t			numBits;
+
+		BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes );
+	
+		dilate = 32;
+		for ( uint32_t converge = 0; converge < 7; converge++ )	
+			pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT );
+
+		dilate = 8;
+		pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT );
+
+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT );
+		status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 );
+		RequireNoErr( status, goto Exit; );
+
+		numBits = (dilate * bits1) + (16 * numU);
+		if ( numBits < minBits )
+		{
+			bestU	= numU;
+			minBits = numBits;
+		}
+	}             
+
+	// test for escape hatch if best calculated compressed size turns out to be more than the input size
+	// - first, add bits for the header bytes mixRes/maxRes/shiftU/filterU
+	minBits += (4 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0);
+	if ( bytesShifted != 0 )
+		minBits += (numSamples * (bytesShifted * 8));
+
+	escapeBits = (numSamples * mBitDepth) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */
+
+	doEscape = (minBits >= escapeBits) ? true : false;
+
+	if ( doEscape == false )
+	{
+		// write bitstream header
+		BitBufferWrite( bitstream, 0, 12 );
+		BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 );
+		if ( partialFrame )
+			BitBufferWrite( bitstream, numSamples, 32 );
+		BitBufferWrite( bitstream, 0, 16 );								// mixBits = mixRes = 0
+		
+		// write the params and predictor coefs
+		numU = bestU;
+		BitBufferWrite( bitstream, (0 << 4) | DENSHIFT_DEFAULT, 8 );	// modeU = 0
+		BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 );
+		for ( index = 0; index < numU; index++ )
+			BitBufferWrite( bitstream, coefsU[numU-1][index], 16 );
+
+		// if shift active, write the interleaved shift buffers
+		if ( bytesShifted != 0 )
+		{
+			for ( index = 0; index < numSamples; index++ )
+				BitBufferWrite( bitstream, mShiftBufferUV[index], shift );
+		}
+
+		// run the dynamic predictor with the best result
+		pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT );
+
+		// do lossless compression
+		set_standard_ag_params( &agParams, numSamples, numSamples );
+		status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 );
+		//AssertNoErr( status );
+
+
+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be,
+			chuck it and do an escape packet
+		*/
+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits );
+		if ( minBits >= escapeBits )
+		{
+			*bitstream = startBits;		// reset bitstream state
+			doEscape = true;
+			printf( "compressed frame too big: %u vs. %u\n", minBits, escapeBits );
+		}
+	}
+
+	if ( doEscape == true )
+	{
+		// write bitstream header and coefs
+		BitBufferWrite( bitstream, 0, 12 );
+		BitBufferWrite( bitstream, (partialFrame << 3) | 1, 4 );	// LSB = 1 means "frame not compressed"
+		if ( partialFrame )
+			BitBufferWrite( bitstream, numSamples, 32 );
+
+		// just copy the input data to the output buffer
+		switch ( mBitDepth )
+		{
+			case 16:
+				input16 = (int16_t *) inputBuffer;
+				for ( index = 0; index < (numSamples * stride); index += stride )
+					BitBufferWrite( bitstream, input16[index], 16 );
+				break;
+			case 20:
+				// convert 20-bit data to 32-bit for simplicity
+				copy20ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples );
+				for ( index = 0; index < numSamples; index++ )
+					BitBufferWrite( bitstream, mMixBufferU[index], 20 );
+				break;
+			case 24:
+				// convert 24-bit data to 32-bit for simplicity
+				copy24ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples );
+				for ( index = 0; index < numSamples; index++ )
+					BitBufferWrite( bitstream, mMixBufferU[index], 24 );
+				break;
+			case 32:
+				input32 = (int32_t *) inputBuffer;
+				for ( index = 0; index < (numSamples * stride); index += stride )
+					BitBufferWrite( bitstream, input32[index], 32 );
+				break;
+		}
+#if VERBOSE_DEBUG		
+		DebugMsg( "escape!: %lu vs %lu", minBits, (numSamples * mBitDepth) );
+#endif
+	}
+
+Exit:
+	return status;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+/*
+	Encode()
+	- encode the next block of samples
+*/
+int32_t ALACEncoder::Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
+                             unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes)
+{
+	uint32_t				numFrames;
+	uint32_t				outputSize;
+	BitBuffer			bitstream;
+	int32_t			status;
+
+	numFrames = *ioNumBytes/theInputFormat.mBytesPerPacket;
+
+	// create a bit buffer structure pointing to our output buffer
+	BitBufferInit( &bitstream, theWriteBuffer, mMaxOutputBytes );
+
+	if ( theInputFormat.mChannelsPerFrame == 2 )
+	{
+		// add 3-bit frame start tag ID_CPE = channel pair & 4-bit element instance tag = 0
+		BitBufferWrite( &bitstream, ID_CPE, 3 );
+		BitBufferWrite( &bitstream, 0, 4 );
+
+		// encode stereo input buffer
+		if ( mFastMode == false )
+			status = this->EncodeStereo( &bitstream, theReadBuffer, 2, 0, numFrames );
+		else
+			status = this->EncodeStereoFast( &bitstream, theReadBuffer, 2, 0, numFrames );
+		RequireNoErr( status, goto Exit; );
+	}
+	else if ( theInputFormat.mChannelsPerFrame == 1 )
+	{
+		// add 3-bit frame start tag ID_SCE = mono channel & 4-bit element instance tag = 0
+		BitBufferWrite( &bitstream, ID_SCE, 3 );
+		BitBufferWrite( &bitstream, 0, 4 );
+
+		// encode mono input buffer
+		status = this->EncodeMono( &bitstream, theReadBuffer, 1, 0, numFrames );
+		RequireNoErr( status, goto Exit; );
+	}
+	else
+	{
+		char *					inputBuffer;
+		uint32_t				tag;
+		uint32_t				channelIndex;
+		uint32_t				inputIncrement;
+		uint8_t				stereoElementTag;
+		uint8_t				monoElementTag;
+		uint8_t				lfeElementTag;
+		
+		inputBuffer		= (char *) theReadBuffer;
+		inputIncrement	= ((mBitDepth + 7) / 8);
+		
+		stereoElementTag	= 0;
+		monoElementTag		= 0;
+		lfeElementTag		= 0;
+
+		for ( channelIndex = 0; channelIndex < theInputFormat.mChannelsPerFrame; )
+		{
+			tag = (sChannelMaps[theInputFormat.mChannelsPerFrame - 1] & (0x7ul << (channelIndex * 3))) >> (channelIndex * 3);
+	
+			BitBufferWrite( &bitstream, tag, 3 );
+			switch ( tag )
+			{
+				case ID_SCE:
+					// mono
+					BitBufferWrite( &bitstream, monoElementTag, 4 );
+
+					status = this->EncodeMono( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames );
+					
+					inputBuffer += inputIncrement;
+					channelIndex++;
+					monoElementTag++;
+					break;
+
+				case ID_CPE:
+					// stereo
+					BitBufferWrite( &bitstream, stereoElementTag, 4 );
+
+					status = this->EncodeStereo( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames );
+
+					inputBuffer += (inputIncrement * 2);
+					channelIndex += 2;
+					stereoElementTag++;
+					break;
+
+				case ID_LFE:
+					// LFE channel (subwoofer)
+					BitBufferWrite( &bitstream, lfeElementTag, 4 );
+
+					status = this->EncodeMono( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames );
+
+					inputBuffer += inputIncrement;
+					channelIndex++;
+					lfeElementTag++;
+					break;
+
+				default:
+					printf( "That ain't right! (%u)\n", tag );
+					status = kALAC_ParamError;
+					goto Exit;
+			}
+
+			RequireNoErr( status, goto Exit; );
+		}
+	}
+
+#if VERBOSE_DEBUG
+{
+	// if there is room left in the output buffer, add some random fill data to test decoder
+	int32_t			bitsLeft;
+	int32_t			bytesLeft;
+	
+	bitsLeft = BitBufferGetPosition( &bitstream ) - 3;	// - 3 for ID_END tag
+	bytesLeft = bitstream.byteSize - ((bitsLeft + 7) / 8);
+	
+	if ( (bytesLeft > 20) && ((bytesLeft & 0x4u) != 0) )
+		AddFiller( &bitstream, bytesLeft );
+}
+#endif
+
+	// add 3-bit frame end tag: ID_END
+	BitBufferWrite( &bitstream, ID_END, 3 );
+
+	// byte-align the output data
+	BitBufferByteAlign( &bitstream, true );
+
+	outputSize = BitBufferGetPosition( &bitstream ) / 8;
+	//Assert( outputSize <= mMaxOutputBytes );
+
+
+	// all good, let iTunes know what happened and remember the total number of input sample frames
+	*ioNumBytes = outputSize;
+	//mEncodedFrames		   	   += encodeMsg->numInputSamples;
+
+	// gather encoding stats
+	mTotalBytesGenerated += outputSize;
+	mMaxFrameBytes = MAX( mMaxFrameBytes, outputSize );
+
+	status = ALAC_noErr;
+
+Exit:
+	return status;
+}
+
+/*
+	Finish()
+	- drain out any leftover samples
+*/
+
+int32_t ALACEncoder::Finish()
+{
+/*	// finalize bit rate statistics
+	if ( mSampleSize.numEntries != 0 )
+		mAvgBitRate = (uint32_t)( (((float)mTotalBytesGenerated * 8.0f) / (float)mSampleSize.numEntries) * ((float)mSampleRate / (float)mFrameSize) );
+	else
+		mAvgBitRate = 0;
+*/
+	return ALAC_noErr;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+/*
+	GetConfig()
+*/
+void ALACEncoder::GetConfig( ALACSpecificConfig & config )
+{
+	config.frameLength			= Swap32NtoB(mFrameSize);
+	config.compatibleVersion	= (uint8_t) kALACCompatibleVersion;
+	config.bitDepth				= (uint8_t) mBitDepth;
+	config.pb					= (uint8_t) PB0;
+	config.kb					= (uint8_t) KB0;
+	config.mb					= (uint8_t) MB0;
+	config.numChannels			= (uint8_t) mNumChannels;
+	config.maxRun				= Swap16NtoB((uint16_t) MAX_RUN_DEFAULT);
+	config.maxFrameBytes		= Swap32NtoB(mMaxFrameBytes);
+	config.avgBitRate			= Swap32NtoB(mAvgBitRate);
+	config.sampleRate			= Swap32NtoB(mOutputSampleRate);
+}
+
+uint32_t ALACEncoder::GetMagicCookieSize(uint32_t inNumChannels)
+{
+    if (inNumChannels > 2)
+    {
+        return sizeof(ALACSpecificConfig) + kChannelAtomSize + sizeof(ALACAudioChannelLayout);
+    }
+    else
+    {
+        return sizeof(ALACSpecificConfig);
+    }
+}
+
+void ALACEncoder::GetMagicCookie(void * outCookie, uint32_t * ioSize)
+{
+    ALACSpecificConfig theConfig = {0};
+    ALACAudioChannelLayout theChannelLayout = {0};
+    uint8_t theChannelAtom[kChannelAtomSize] = {0, 0, 0, 0, 'c', 'h', 'a', 'n', 0, 0, 0, 0};
+    uint32_t theCookieSize = sizeof(ALACSpecificConfig);
+    uint8_t * theCookiePointer = (uint8_t *)outCookie;
+    
+    GetConfig(theConfig);
+    if (theConfig.numChannels > 2)
+    {
+        theChannelLayout.mChannelLayoutTag = ALACChannelLayoutTags[theConfig.numChannels - 1];
+        theCookieSize += (sizeof(ALACAudioChannelLayout) + kChannelAtomSize);
+    }
+     if (*ioSize >= theCookieSize)
+    {
+        memcpy(theCookiePointer, &theConfig, sizeof(ALACSpecificConfig));
+        theChannelAtom[3] = (sizeof(ALACAudioChannelLayout) + kChannelAtomSize);
+        if (theConfig.numChannels > 2)
+        {
+            theCookiePointer += sizeof(ALACSpecificConfig);
+            memcpy(theCookiePointer, theChannelAtom, kChannelAtomSize);
+            theCookiePointer += kChannelAtomSize;
+            memcpy(theCookiePointer, &theChannelLayout, sizeof(ALACAudioChannelLayout));
+        }
+        *ioSize = theCookieSize;
+    }
+    else
+    {
+        *ioSize = 0; // no incomplete cookies
+    }
+}
+
+/*
+	InitializeEncoder()
+	- initialize the encoder component with the current config
+*/
+int32_t ALACEncoder::InitializeEncoder(AudioFormatDescription theOutputFormat)
+{
+	int32_t			status;
+    
+    mOutputSampleRate = theOutputFormat.mSampleRate;
+    mNumChannels = theOutputFormat.mChannelsPerFrame;
+    switch(theOutputFormat.mFormatFlags)
+    {
+        case 1:
+            mBitDepth = 16;
+            break;
+        case 2:
+            mBitDepth = 20;
+            break;
+        case 3:
+            mBitDepth = 24;
+            break;
+        case 4:
+            mBitDepth = 32;
+            break;
+        default:
+            break;
+    }
+
+	// set up default encoding parameters and state
+	// - note: mFrameSize is set in the constructor or via SetFrameSize() which must be called before this routine
+	for ( uint32_t index = 0; index < kALACMaxChannels; index++ )
+		mLastMixRes[index] = kDefaultMixRes;
+
+	// the maximum output frame size can be no bigger than (samplesPerBlock * numChannels * ((10 + sampleSize)/8) + 1)
+	// but note that this can be bigger than the input size!
+	// - since we don't yet know what our input format will be, use our max allowed sample size in the calculation
+	mMaxOutputBytes = mFrameSize * mNumChannels * ((10 + kMaxSampleSize) / 8)  + 1;
+
+	// allocate mix buffers
+	mMixBufferU = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 );
+	mMixBufferV = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 );
+
+	// allocate dynamic predictor buffers
+	mPredictorU = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 );
+	mPredictorV = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 );
+	
+	// allocate combined shift buffer
+	mShiftBufferUV = (uint16_t *) calloc( mFrameSize * 2 * sizeof(uint16_t),1 );
+	
+	// allocate work buffer for search loop
+	mWorkBuffer = (uint8_t *) calloc( mMaxOutputBytes, 1 );
+
+	RequireAction( (mMixBufferU != nil) && (mMixBufferV != nil) &&
+					(mPredictorU != nil) && (mPredictorV != nil) &&
+					(mShiftBufferUV != nil) && (mWorkBuffer != nil ),
+					status = kALAC_MemFullError; goto Exit; );
+
+	status = ALAC_noErr;
+
+
+	// initialize coefs arrays once b/c retaining state across blocks actually improves the encode ratio
+	for ( int32_t channel = 0; channel < (int32_t)mNumChannels; channel++ )
+	{
+		for ( int32_t search = 0; search < kALACMaxSearches; search++ )
+		{
+			init_coefs( mCoefsU[channel][search], DENSHIFT_DEFAULT, kALACMaxCoefs );
+			init_coefs( mCoefsV[channel][search], DENSHIFT_DEFAULT, kALACMaxCoefs );
+		}
+	}
+
+Exit:
+	return status;
+}
+
+/*
+	GetSourceFormat()
+	- given the input format, return one of our supported formats
+*/
+void ALACEncoder::GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output )
+{
+	// default is 16-bit native endian
+	// - note: for float input we assume that's coming from one of our decoders (mp3, aac) so it only makes sense
+	//		   to encode to 16-bit since the source was lossy in the first place
+	// - note: if not a supported bit depth, find the closest supported bit depth to the input one
+	if ( (source->mFormatID != kALACFormatLinearPCM) || ((source->mFormatFlags & kALACFormatFlagIsFloat) != 0) ||
+		( source->mBitsPerChannel <= 16 ) )
+		mBitDepth = 16;
+	else if ( source->mBitsPerChannel <= 20 )
+		mBitDepth = 20;
+	else if ( source->mBitsPerChannel <= 24 )
+		mBitDepth = 24;
+	else
+		mBitDepth = 32;
+		
+	// we support 16/20/24/32-bit integer data at any sample rate and our target number of channels
+	// and sample rate were specified when we were configured
+	/*
+    MakeUncompressedAudioFormat( mNumChannels, (float) mOutputSampleRate, mBitDepth, kAudioFormatFlagsNativeIntegerPacked, output );
+     */
+}
+
+
+
+#if VERBOSE_DEBUG
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+/*
+	AddFiller()
+	- add fill and data stream elements to the bitstream to test the decoder
+*/
+static void AddFiller( BitBuffer * bits, int32_t numBytes )
+{
+	uint8_t		tag;
+	uint32_t		index;
+
+	// out of lameness, subtract 6 bytes to deal with header + alignment as required for fill/data elements
+	numBytes -= 6;
+	if ( numBytes <= 0 )
+		return;
+	
+	// randomly pick Fill or Data Stream Element based on numBytes requested
+	tag = (numBytes & 0x8) ? ID_FIL : ID_DSE;
+
+	BitBufferWrite( bits, tag, 3 );
+	if ( tag == ID_FIL )
+	{
+		// can't write more than 269 bytes in a fill element
+		numBytes = (numBytes > 269) ? 269 : numBytes;
+
+		// fill element = 4-bit size unless >= 15 then 4-bit size + 8-bit extension size
+		if ( numBytes >= 15 )
+		{
+			uint16_t			extensionSize;
+
+			BitBufferWrite( bits, 15, 4 );
+
+			// 8-bit extension count field is "extra + 1" which is weird but I didn't define the syntax
+			// - otherwise, there's no way to represent 15
+			// - for example, to really mean 15 bytes you must encode extensionSize = 1
+			// - why it's not like data stream elements I have no idea
+			extensionSize = (numBytes - 15) + 1;
+			Assert( extensionSize <= 255 );
+			BitBufferWrite( bits, extensionSize, 8 );
+		}
+		else
+			BitBufferWrite( bits, numBytes, 4 );
+
+		BitBufferWrite( bits, 0x10, 8 );		// extension_type = FILL_DATA = b0001 or'ed with fill_nibble = b0000
+		for ( index = 0; index < (numBytes - 1); index++ )
+			BitBufferWrite( bits, 0xa5, 8 );	// fill_byte = b10100101 = 0xa5
+	}
+	else
+	{
+		// can't write more than 510 bytes in a data stream element
+		numBytes = (numBytes > 510) ? 510 : numBytes;
+
+		BitBufferWrite( bits, 0, 4 );			// element instance tag
+		BitBufferWrite( bits, 1, 1 );			// byte-align flag = true
+
+		// data stream element = 8-bit size unless >= 255 then 8-bit size + 8-bit size
+		if ( numBytes >= 255 )
+		{
+			BitBufferWrite( bits, 255, 8 );
+			BitBufferWrite( bits, numBytes - 255, 8 );
+		}
+		else
+			BitBufferWrite( bits, numBytes, 8 );
+		
+		BitBufferByteAlign( bits, true );		// byte-align with zeros
+
+		for ( index = 0; index < numBytes; index++ )
+			BitBufferWrite( bits, 0x5a, 8 );
+	}
+}
+
+#endif	/* VERBOSE_DEBUG */

+ 92 - 0
components/spotify/cspot/bell/external/alac/codec/ALACEncoder.h

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACEncoder.h
+*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include "ALACAudioTypes.h"
+
+
+struct BitBuffer;
+
+class ALACEncoder
+{
+	public:
+		ALACEncoder();
+		virtual ~ALACEncoder();
+
+		virtual int32_t	Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
+                                   unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
+		virtual int32_t	Finish( );
+
+		void				SetFastMode( bool fast ) { mFastMode = fast; };
+
+		// this must be called *before* InitializeEncoder()
+		void				SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
+
+		void				GetConfig( ALACSpecificConfig & config );
+        uint32_t            GetMagicCookieSize(uint32_t inNumChannels);
+        void				GetMagicCookie( void * config, uint32_t * ioSize ); 
+
+        virtual int32_t	InitializeEncoder(AudioFormatDescription theOutputFormat);
+
+    protected:
+		virtual void		GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
+		
+		int32_t			EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+		int32_t			EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+		int32_t			EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
+		int32_t			EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+
+
+		// ALAC encoder parameters
+		int16_t					mBitDepth;
+		bool					mFastMode;
+
+		// encoding state
+		int16_t					mLastMixRes[kALACMaxChannels];
+
+		// encoding buffers
+		int32_t *				mMixBufferU;
+		int32_t *				mMixBufferV;
+		int32_t *				mPredictorU;
+		int32_t *				mPredictorV;
+		uint16_t *				mShiftBufferUV;
+		
+		uint8_t *					mWorkBuffer;
+
+		// per-channel coefficients buffers
+		int16_t					mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
+		int16_t					mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
+
+		// encoding statistics
+		uint32_t					mTotalBytesGenerated;
+		uint32_t					mAvgBitRate;
+		uint32_t					mMaxFrameBytes;
+        uint32_t                  mFrameSize;
+        uint32_t                  mMaxOutputBytes;
+        uint32_t                  mNumChannels;
+        uint32_t                  mOutputSampleRate;		
+};

+ 335 - 0
components/spotify/cspot/bell/external/alac/codec/APPLE_LICENSE.txt

@@ -0,0 +1,335 @@
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 -  August 6, 2003
+
+Please read this License carefully before downloading this software.  By
+downloading or using this software, you are agreeing to be bound by the terms
+of this License.  If you do not or cannot agree to the terms of this License,
+please do not download or use the software.
+
+Apple Note:  In January 2007, Apple changed its corporate name from "Apple
+Computer, Inc." to "Apple Inc."  This change has been reflected below and
+copyright years updated, but no other changes have been made to the APSL 2.0.
+
+1.	General; Definitions.  This License applies to any program or other
+work which Apple Inc. ("Apple") makes publicly available and which contains a
+notice placed by Apple identifying such program or work as "Original Code" and
+stating that it is subject to the terms of this Apple Public Source License
+version 2.0 ("License").  As used in this License:
+
+1.1	 "Applicable Patent Rights" mean:  (a) in the case where Apple is the
+grantor of rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to Apple and (ii) that cover subject matter contained in
+the Original Code, but only to the extent necessary to use, reproduce and/or
+distribute the Original Code without infringement; and (b) in the case where
+You are the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to You and (ii) that cover subject matter in
+Your Modifications, taken alone or in combination with Original Code.
+
+1.2	"Contributor" means any person or entity that creates or contributes to
+the creation of Modifications.
+
+1.3	 "Covered Code" means the Original Code, Modifications, the combination
+of Original Code and any Modifications, and/or any respective portions thereof.
+
+1.4	"Externally Deploy" means: (a) to sublicense, distribute or otherwise
+make Covered Code available, directly or indirectly, to anyone other than You;
+and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way
+to provide a service, including but not limited to delivery of content, through
+electronic communication with a client other than You.
+
+1.5	"Larger Work" means a work which combines Covered Code or portions
+thereof with code not governed by the terms of this License.
+
+1.6	"Modifications" mean any addition to, deletion from, and/or change to,
+the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous Modifications,
+and/or any respective portions thereof.  When code is released as a series of
+files, a Modification is:  (a) any addition to or deletion from the contents of
+a file containing Covered Code; and/or (b) any new file or other representation
+of computer program statements that contains any part of Covered Code. 
+
+1.7	"Original Code" means (a) the Source Code of a program or other work as
+originally made available by Apple under this License, including the Source
+Code of any updates or upgrades to such programs or works made available by
+Apple under this License, and that has been expressly identified by Apple as
+such in the header file(s) of such work; and (b) the object code compiled from
+such Source Code and originally made available by Apple under this License
+
+1.8	"Source Code" means the human readable form of a program or other work
+that is suitable for making modifications to it, including all modules it
+contains, plus any associated interface definition files, scripts used to
+control compilation and installation of an executable (object code).
+
+1.9	"You" or "Your" means an individual or a legal entity exercising rights
+under this License.  For legal entities, "You" or "Your" includes any entity
+which controls, is controlled by, or is under common control with, You, where
+"control" means (a) the power, direct or indirect, to cause the direction or
+management of such entity, whether by contract or otherwise, or (b) ownership
+of fifty percent (50%) or more of the outstanding shares or beneficial
+ownership of such entity.
+
+2.	Permitted Uses; Conditions & Restrictions.   Subject to the terms and
+conditions of this License, Apple hereby grants You, effective on the date You
+accept this License and download the Original Code, a world-wide, royalty-free,
+non-exclusive license, to the extent of Apple's Applicable Patent Rights and
+copyrights covering the Original Code, to do the following:
+
+2.1	Unmodified Code.  You may use, reproduce, display, perform, internally
+distribute within Your organization, and Externally Deploy verbatim, unmodified
+copies of the Original Code, for commercial or non-commercial purposes,
+provided that in each instance:
+
+(a)	You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as they appear
+in the Original Code, and keep intact all notices in the Original Code that
+refer to this License; and
+
+(b) 	You must include a copy of this License with every copy of Source Code
+of Covered Code and documentation You distribute or Externally Deploy, and You
+may not offer or impose any terms on such Source Code that alter or restrict
+this License or the recipients' rights hereunder, except as permitted under
+Section 6.
+
+2.2	Modified Code.  You may modify Covered Code and use, reproduce,
+display, perform, internally distribute within Your organization, and
+Externally Deploy Your Modifications and Covered Code, for commercial or
+non-commercial purposes, provided that in each instance You also meet all of
+these conditions:
+
+(a)	You must satisfy all the conditions of Section 2.1 with respect to the
+Source Code of the Covered Code; 
+
+(b)	You must duplicate, to the extent it does not already exist, the notice
+in Exhibit A in each file of the Source Code of all Your Modifications, and
+cause the modified files to carry prominent notices stating that You changed
+the files and the date of any change; and
+
+(c)	If You Externally Deploy Your Modifications, You must make Source Code
+of all Your Externally Deployed Modifications either available to those to whom
+You have Externally Deployed Your Modifications, or publicly available.  Source
+Code of Your Externally Deployed Modifications must be released under the terms
+set forth in this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve (12)
+months from the date of initial External Deployment, whichever is longer. You
+should preferably distribute the Source Code of Your Externally Deployed
+Modifications electronically (e.g. download from a web site).
+
+2.3	Distribution of Executable Versions.  In addition, if You Externally
+Deploy Covered Code (Original Code and/or Modifications) in object code,
+executable form only, You must include a prominent notice, in the code itself
+as well as in related documentation, stating that Source Code of the Covered
+Code is available under the terms of this License with information on how and
+where to obtain such Source Code.  
+
+2.4	Third Party Rights.  You expressly acknowledge and agree that although
+Apple and each Contributor grants the licenses to their respective portions of
+the Covered Code set forth herein, no assurances are provided by Apple or any
+Contributor that the Covered Code does not infringe the patent or other
+intellectual property rights of any other entity. Apple and each Contributor
+disclaim any liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a condition to
+exercising the rights and licenses granted hereunder, You hereby assume sole
+responsibility to secure any other intellectual property rights needed, if any.
+For example, if a third party patent license is required to allow You to
+distribute the Covered Code, it is Your responsibility to acquire that license
+before distributing the Covered Code.
+
+3.	Your Grants.  In consideration of, and as a condition to, the licenses
+granted to You under this License, You hereby grant to any person or entity
+receiving or distributing Covered Code under this License a non-exclusive,
+royalty-free, perpetual, irrevocable license, under Your Applicable Patent
+Rights and other intellectual property rights (other than patent) owned or
+controlled by You, to use, reproduce, display, perform, modify, sublicense,
+distribute and Externally Deploy Your Modifications of the same scope and
+extent as Apple's licenses under Sections 2.1 and 2.2 above.  
+
+4.	Larger Works.  You may create a Larger Work by combining Covered Code
+with other code not governed by the terms of this License and distribute the
+Larger Work as a single product.  In each such instance, You must make sure the
+requirements of this License are fulfilled for the Covered Code or any portion
+thereof. 
+
+5.	Limitations on Patent License.   Except as expressly stated in Section
+2, no other patent rights, express or implied, are granted by Apple herein.
+Modifications and/or Larger Works may require additional patent licenses from
+Apple which Apple may grant in its sole discretion.  
+
+6.	Additional Terms.  You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other rights
+consistent with the scope of the license granted herein ("Additional Terms") to
+one or more recipients of Covered Code. However, You may do so only on Your own
+behalf and as Your sole responsibility, and not on behalf of Apple or any
+Contributor. You must obtain the recipient's agreement that any such Additional
+Terms are offered by You alone, and You hereby agree to indemnify, defend and
+hold Apple and every Contributor harmless for any liability incurred by or
+claims asserted against Apple or such Contributor by reason of any such
+Additional Terms. 
+
+7.	Versions of the License.  Apple may publish revised and/or new versions
+of this License from time to time.  Each version will be given a distinguishing
+version number.  Once Original Code has been published under a particular
+version of this License, You may continue to use it under the terms of that
+version. You may also choose to use such Original Code under the terms of any
+subsequent version of this License published by Apple.  No one other than Apple
+has the right to modify the terms applicable to Covered Code created under this
+License.  
+
+8.	NO WARRANTY OR SUPPORT.  The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works.  The Covered Code may
+contain errors that could cause failures or loss of data, and may be incomplete
+or contain inaccuracies.  You expressly acknowledge and agree that use of the
+Covered Code, or any portion thereof, is at Your sole and entire risk.  THE
+COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF
+ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE"
+FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF
+SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF
+QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  APPLE AND EACH
+CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE
+COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR
+REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED.  NO ORAL OR
+WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED
+REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.  You acknowledge
+that the Covered Code is not intended for use in the operation of nuclear
+facilities, aircraft navigation, communication systems, or air traffic control
+machines in which case the failure of the Covered Code could lead to death,
+personal injury, or severe physical or environmental damage.
+
+9.	LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
+INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR
+YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER
+UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS
+LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL
+PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF
+LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT
+APPLY TO YOU. In no event shall Apple's total liability to You for all damages
+(other than as may be required by applicable law) under this License exceed the
+amount of fifty dollars ($50.00).
+
+10.	Trademarks.  This License does not grant any rights to use the
+trademarks or trade names  "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime
+Streaming Server" or any other trademarks, service marks, logos or trade names
+belonging to Apple (collectively "Apple Marks") or to any trademark, service
+mark, logo or trade name belonging to any Contributor.  You agree not to use
+any Apple Marks in or as part of the name of products derived from the Original
+Code or to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times with
+Apple's third party trademark usage guidelines which are posted at
+http://www.apple.com/legal/guidelinesfor3rdparties.html.  
+
+11.	Ownership. Subject to the licenses granted under this License, each
+Contributor retains all rights, title and interest in and to any Modifications
+made by such Contributor.  Apple retains all rights, title and interest in and
+to the Original Code and any Modifications made by or on behalf of Apple
+("Apple Modifications"), and such Apple Modifications will not be automatically
+subject to this License.  Apple may, at its sole discretion, choose to license
+such Apple Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.  
+
+12.	Termination.  
+
+12.1	Termination.  This License and the rights granted hereunder will
+terminate:
+
+(a)	automatically without notice from Apple if You fail to comply with any
+term(s) of this License and fail to cure such breach within 30 days of becoming
+aware of such breach;
+(b)	immediately in the event of the circumstances described in Section
+13.5(b); or
+(c)	automatically without notice from Apple if You, at any time during the
+term of this License, commence an action for patent infringement against Apple;
+provided that Apple did not first commence an action for patent infringement
+against You in that instance.
+
+12.2	Effect of Termination.  Upon termination, You agree to immediately stop
+any further use, reproduction, modification, sublicensing and distribution of
+the Covered Code.  All sublicenses to the Covered Code which have been properly
+granted prior to termination shall survive any termination of this License.
+Provisions which, by their nature, should remain in effect beyond the
+termination of this License shall survive, including but not limited to
+Sections 3, 5, 8, 9, 10, 11, 12.2 and 13.  No party will be liable to any other
+for compensation, indemnity or damages of any sort solely as a result of
+terminating this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of any party.
+
+13. 	Miscellaneous.
+
+13.1	Government End Users.   The Covered Code is a "commercial item" as
+defined in FAR 2.101.  Government software and technical data rights in the
+Covered Code include only those rights customarily provided to the public as
+defined in this License. This customary commercial license in technical data
+and software is provided in accordance with FAR 12.211 (Technical Data) and
+12.212 (Computer Software) and, for Department of Defense purchases, DFAR
+252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in
+Commercial Computer Software or Computer Software Documentation).  Accordingly,
+all U.S. Government End Users acquire Covered Code with only those rights set
+forth herein.
+
+13.2	Relationship of Parties.  This License will not be construed as
+creating an agency, partnership, joint venture or any other form of legal
+association between or among You, Apple or any Contributor, and You will not
+represent to the contrary, whether expressly, by implication, appearance or
+otherwise.
+
+13.3	Independent Development.   Nothing in this License will impair Apple's
+right to acquire, license, develop, have others develop for it, market and/or
+distribute technology or products that perform the same or similar functions
+as, or otherwise compete with, Modifications, Larger Works, technology or
+products that You may develop, produce, market or distribute.
+
+13.4	Waiver; Construction.  Failure by Apple or any Contributor to enforce
+any provision of this License will not be deemed a waiver of future enforcement
+of that or any other provision.  Any law or regulation which provides that the
+language of a contract shall be construed against the drafter will not apply to
+this License.
+
+13.5	Severability.  (a) If for any reason a court of competent jurisdiction
+finds any provision of this License, or portion thereof, to be unenforceable,
+that provision of the License will be enforced to the maximum extent
+permissible so as to effect the economic benefits and intent of the parties,
+and the remainder of this License will continue in full force and effect.  (b)
+Notwithstanding the foregoing, if applicable law prohibits or restricts You
+from fully and/or specifically complying with Sections 2 and/or 3 or prevents
+the enforceability of either of those Sections, this License will immediately
+terminate and You must immediately discontinue any use of the Covered Code and
+destroy all copies of it that are in your possession or control.
+
+13.6	Dispute Resolution.  Any litigation or other dispute resolution between
+You and Apple relating to this License shall take place in the Northern
+District of California, and You and Apple hereby consent to the personal
+jurisdiction of, and venue in, the state and federal courts within that
+District with respect to this License. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is expressly
+excluded.
+
+13.7	Entire Agreement; Governing Law.  This License constitutes the entire
+agreement between the parties with respect to the subject matter hereof.  This
+License shall be governed by the laws of the United States and the State of
+California, except that body of California law concerning conflicts of law. 
+
+Where You are located in the province of Quebec, Canada, the following clause
+applies:  The parties hereby confirm that they have requested that this License
+and all related documents be drafted in English. Les parties ont exigé que le
+présent contrat et tous les documents connexes soient rédigés en anglais. 
+
+EXHIBIT A. 
+
+"Portions Copyright (c) 1999-2007 Apple Inc.  All Rights Reserved.
+
+This file contains Original Code and/or Modifications of Original Code as
+defined in and that are subject to the Apple Public Source License Version 2.0
+(the 'License').  You may not use this file except in compliance with the
+License.  Please obtain a copy of the License at
+http://www.opensource.apple.com/apsl/ and read it before using this file.
+
+The Original Code and all software distributed under the License are
+distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please see the License for the
+specific language governing rights and limitations under the License." 
+

+ 177 - 0
components/spotify/cspot/bell/external/alac/codec/EndianPortable.c

@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+//
+//  EndianPortable.c
+//
+//  Copyright 2011 Apple Inc. All rights reserved.
+//
+
+#include <stdio.h>
+#include "EndianPortable.h"
+
+#define BSWAP16(x) (((x << 8) | ((x >> 8) & 0x00ff)))
+#define BSWAP32(x) (((x << 24) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff)))
+#define BSWAP64(x) ((((int64_t)x << 56) | (((int64_t)x << 40) & 0x00ff000000000000LL) | \
+                    (((int64_t)x << 24) & 0x0000ff0000000000LL) | (((int64_t)x << 8) & 0x000000ff00000000LL) | \
+                    (((int64_t)x >> 8) & 0x00000000ff000000LL) | (((int64_t)x >> 24) & 0x0000000000ff0000LL) | \
+                    (((int64_t)x >> 40) & 0x000000000000ff00LL) | (((int64_t)x >> 56) & 0x00000000000000ffLL)))
+
+#if defined(__i386__)
+#define TARGET_RT_LITTLE_ENDIAN 1
+#elif defined(__x86_64__)
+#define TARGET_RT_LITTLE_ENDIAN 1
+#elif defined (TARGET_OS_WIN32)
+#define TARGET_RT_LITTLE_ENDIAN 1
+#elif defined (__arm__) || defined(__aarch64__)
+#define TARGET_RT_LITTLE_ENDIAN 1
+#endif
+
+uint16_t Swap16NtoB(uint16_t inUInt16)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP16(inUInt16);
+#else
+    return inUInt16;
+#endif
+}
+
+uint16_t Swap16BtoN(uint16_t inUInt16)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP16(inUInt16);
+#else
+    return inUInt16;
+#endif
+}
+
+uint32_t Swap32NtoB(uint32_t inUInt32)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP32(inUInt32);
+#else
+    return inUInt32;
+#endif
+}
+
+uint32_t Swap32BtoN(uint32_t inUInt32)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP32(inUInt32);
+#else
+    return inUInt32;
+#endif
+}
+
+uint64_t Swap64BtoN(uint64_t inUInt64)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP64(inUInt64);
+#else
+    return inUInt64;
+#endif
+}
+
+uint64_t Swap64NtoB(uint64_t inUInt64)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+    return BSWAP64(inUInt64);
+#else
+    return inUInt64;
+#endif
+}
+
+float SwapFloat32BtoN(float in)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+	union {
+		float f;
+		int32_t i;
+	} x;
+	x.f = in;	
+	x.i = BSWAP32(x.i);
+	return x.f;
+#else
+	return in;
+#endif
+}
+
+float SwapFloat32NtoB(float in)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+	union {
+		float f;
+		int32_t i;
+	} x;
+	x.f = in;	
+	x.i = BSWAP32(x.i);
+	return x.f;
+#else
+	return in;
+#endif
+}
+
+double SwapFloat64BtoN(double in)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+	union {
+		double f;
+		int64_t i;
+	} x;
+	x.f = in;	
+	x.i = BSWAP64(x.i);
+	return x.f;
+#else
+	return in;
+#endif
+}
+
+double SwapFloat64NtoB(double in)
+{
+#if TARGET_RT_LITTLE_ENDIAN
+	union {
+		double f;
+		int64_t i;
+	} x;
+	x.f = in;	
+	x.i = BSWAP64(x.i);
+	return x.f;
+#else
+	return in;
+#endif
+}
+
+void Swap16(uint16_t * inUInt16)
+{
+	*inUInt16 = BSWAP16(*inUInt16);
+}
+
+void Swap24(uint8_t * inUInt24)
+{
+	uint8_t tempVal = inUInt24[0];
+	inUInt24[0] = inUInt24[2];
+	inUInt24[2] = tempVal;
+}
+
+void Swap32(uint32_t * inUInt32)
+{
+	*inUInt32 = BSWAP32(*inUInt32);
+}
+

+ 59 - 0
components/spotify/cspot/bell/external/alac/codec/EndianPortable.h

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+//
+//  EndianPortable.h
+//
+//  Copyright 2011 Apple Inc. All rights reserved.
+//
+
+#ifndef _EndianPortable_h
+#define _EndianPortable_h
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint16_t Swap16NtoB(uint16_t inUInt16);
+uint16_t Swap16BtoN(uint16_t inUInt16);
+
+uint32_t Swap32NtoB(uint32_t inUInt32);
+uint32_t Swap32BtoN(uint32_t inUInt32);
+
+uint64_t Swap64BtoN(uint64_t inUInt64);
+uint64_t Swap64NtoB(uint64_t inUInt64);
+
+float SwapFloat32BtoN(float in);
+float SwapFloat32NtoB(float in);
+
+double SwapFloat64BtoN(double in);
+double SwapFloat64NtoB(double in);
+
+void Swap16(uint16_t * inUInt16);
+void Swap24(uint8_t * inUInt24);
+void Swap32(uint32_t * inUInt32);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 362 - 0
components/spotify/cspot/bell/external/alac/codec/ag_dec.c

@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ag_dec.c
+	
+	Contains:   Adaptive Golomb decode routines.
+
+	Copyright:	(c) 2001-2011 Apple, Inc.
+*/
+
+#include "aglib.h"
+#include "ALACBitUtilities.h"
+#include "ALACAudioTypes.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if __GNUC__ && TARGET_OS_MAC
+	#if __POWERPC__
+		#include <ppc_intrinsics.h>
+	#else
+		#include <libkern/OSByteOrder.h>
+	#endif
+#endif
+
+#define CODE_TO_LONG_MAXBITS	32
+#define N_MAX_MEAN_CLAMP		0xffff
+#define N_MEAN_CLAMP_VAL		0xffff
+#define REPORT_VAL  40
+
+#if __GNUC__
+#define ALWAYS_INLINE		__attribute__((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+/*	And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
+	to help the compiler out.   In many cases this required manual inlining or a macro.  Sorry
+	if it is ugly but the performance gains are well worth it.
+	- WSK 5/19/04
+*/
+
+void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth)
+{
+	/* Use
+		fullwidth = sectorwidth = numOfSamples, for analog 1-dimensional type-short data,
+		but use
+		fullwidth = full image width, sectorwidth = sector (patch) width
+		for such as image (2-dim.) data.
+	*/
+	set_ag_params( params, MB0, PB0, KB0, fullwidth, sectorwidth, MAX_RUN_DEFAULT );
+}
+
+void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun)
+{
+	params->mb = params->mb0 = m;
+	params->pb = p;
+	params->kb = k;
+	params->wb = (1u<<params->kb)-1;
+	params->qb = QB-params->pb; 
+	params->fw = f;
+	params->sw = s;
+	params->maxrun = maxrun;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+
+// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
+static inline int32_t lead( int32_t m )
+{
+	long j;
+	unsigned long c = (1ul << 31);
+
+	for(j=0; j < 32; j++)
+	{
+		if((c & m) != 0)
+			break;
+		c >>= 1;
+	}
+	return (j);
+}
+
+#define arithmin(a, b) ((a) < (b) ? (a) : (b))
+
+static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
+{
+    int32_t result;
+
+    x += 3;
+    result = lead(x);
+
+    return 31 - result;
+}
+
+static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
+{
+	// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
+	uint32_t		value;
+	
+	value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
+			 ((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
+	return value;
+
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+#define get_next_fromlong(inlong, suff)		((inlong) >> (32 - (suff)))
+
+
+static inline uint32_t ALWAYS_INLINE
+getstreambits( uint8_t *in, int32_t bitoffset, int32_t numbits )
+{
+	uint32_t	load1, load2;
+	uint32_t	byteoffset = bitoffset / 8;
+	uint32_t	result;
+	
+	//Assert( numbits <= 32 );
+
+	load1 = read32bit( in + byteoffset );
+
+	if ( (numbits + (bitoffset & 0x7)) > 32)
+	{
+		int32_t load2shift;
+
+		result = load1 << (bitoffset & 0x7);
+		load2 = (uint32_t) in[byteoffset+4];
+		load2shift = (8-(numbits + (bitoffset & 0x7)-32));
+		load2 >>= load2shift;
+		result >>= (32-numbits);
+		result |= load2;		
+	}
+	else
+	{
+		result = load1 >> (32-numbits-(bitoffset & 7));
+	}
+
+	// a shift of >= "the number of bits in the type of the value being shifted" results in undefined
+	// behavior so don't try to shift by 32
+	if ( numbits != (sizeof(result) * 8) )
+		result &= ~(0xfffffffful << numbits);
+	
+	return result;
+}
+
+
+static inline int32_t dyn_get(unsigned char *in, uint32_t *bitPos, uint32_t m, uint32_t k)
+{
+    uint32_t	tempbits = *bitPos;
+    uint32_t		result;
+    uint32_t		pre = 0, v;
+    uint32_t		streamlong;
+
+	streamlong = read32bit( in + (tempbits >> 3) );
+    streamlong <<= (tempbits & 7);
+
+    /* find the number of bits in the prefix */ 
+    {
+        uint32_t	notI = ~streamlong;
+    	pre = lead( notI);
+    }
+
+    if(pre >= MAX_PREFIX_16)
+    {
+        pre = MAX_PREFIX_16;
+        tempbits += pre;
+        streamlong <<= pre;
+        result = get_next_fromlong(streamlong,MAX_DATATYPE_BITS_16);
+        tempbits += MAX_DATATYPE_BITS_16;
+
+    }
+    else
+    {
+        // all of the bits must fit within the long we have loaded
+        //Assert(pre+1+k <= 32);
+
+        tempbits += pre;
+        tempbits += 1;
+        streamlong <<= pre+1;
+        v = get_next_fromlong(streamlong, k);
+        tempbits += k;
+    
+        result = pre*m + v-1;
+
+        if(v<2) {
+            result -= (v-1);
+            tempbits -= 1;
+        }
+    }
+
+    *bitPos = tempbits;
+    return result;
+}
+
+
+static inline int32_t dyn_get_32bit( uint8_t * in, uint32_t * bitPos, int32_t m, int32_t k, int32_t maxbits )
+{
+	uint32_t	tempbits = *bitPos;
+	uint32_t		v;
+	uint32_t		streamlong;
+	uint32_t		result;
+	
+	streamlong = read32bit( in + (tempbits >> 3) );
+	streamlong <<= (tempbits & 7);
+
+	/* find the number of bits in the prefix */ 
+	{
+		uint32_t notI = ~streamlong;
+		result = lead( notI);
+	}
+	
+	if(result >= MAX_PREFIX_32)
+	{
+		result = getstreambits(in, tempbits+MAX_PREFIX_32, maxbits);
+		tempbits += MAX_PREFIX_32 + maxbits;
+	}
+	else
+	{		
+		/* all of the bits must fit within the long we have loaded*/
+		//Assert(k<=14);
+		//Assert(result<MAX_PREFIX_32);
+		//Assert(result+1+k <= 32);
+		
+		tempbits += result;
+		tempbits += 1;
+		
+		if (k != 1)
+		{
+			streamlong <<= result+1;
+			v = get_next_fromlong(streamlong, k);
+			tempbits += k;
+			tempbits -= 1;
+			result = result*m;
+			
+			if(v>=2)
+			{
+				result += (v-1);
+				tempbits += 1;
+			}
+		}
+	}
+
+	*bitPos = tempbits;
+
+	return result;
+}
+
+int32_t dyn_decomp( AGParamRecPtr params, BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits )
+{
+    uint8_t 		*in;
+    int32_t			*outPtr = pc;
+    uint32_t 	bitPos, startPos, maxPos;
+    uint32_t		j, m, k, n, c, mz;
+    int32_t			del, zmode;
+    uint32_t 	mb;
+    uint32_t	pb_local = params->pb;
+    uint32_t	kb_local = params->kb;
+    uint32_t	wb_local = params->wb;
+    int32_t				status;
+
+	RequireAction( (bitstream != nil) && (pc != nil) && (outNumBits != nil), return kALAC_ParamError; );
+	*outNumBits = 0;
+
+	in = bitstream->cur;
+	startPos = bitstream->bitIndex;
+	maxPos = bitstream->byteSize * 8;
+	bitPos = startPos;
+
+    mb = params->mb0;
+    zmode = 0;
+
+    c = 0;
+	status = ALAC_noErr;
+
+    while (c < numSamples)
+    {
+		// bail if we've run off the end of the buffer
+    	RequireAction( bitPos < maxPos, status = kALAC_ParamError; goto Exit; );
+
+        m = (mb)>>QBSHIFT;
+        k = lg3a(m);
+
+        k = arithmin(k, kb_local);
+        m = (1<<k)-1;
+        
+		n = dyn_get_32bit( in, &bitPos, m, k, maxSize );
+
+        // least significant bit is sign bit
+        {
+        	uint32_t	ndecode = n + zmode;
+            int32_t		multiplier = (- (ndecode&1));
+
+            multiplier |= 1;
+            del = ((ndecode+1) >> 1) * (multiplier);
+        }
+
+        *outPtr++ = del;
+
+        c++;
+
+        mb = pb_local*(n+zmode) + mb - ((pb_local*mb)>>QBSHIFT);
+
+		// update mean tracking
+		if (n > N_MAX_MEAN_CLAMP)
+			mb = N_MEAN_CLAMP_VAL;
+
+        zmode = 0;
+
+        if (((mb << MMULSHIFT) < QB) && (c < numSamples))
+        {
+            zmode = 1;
+            k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
+            mz = ((1<<k)-1) & wb_local;
+
+            n = dyn_get(in, &bitPos, mz, k);
+
+            RequireAction(c+n <= numSamples, status = kALAC_ParamError; goto Exit; );
+
+            for(j=0; j < n; j++)
+            {
+                *outPtr++ = 0;
+                ++c;                    
+            }
+
+            if(n >= 65535)
+            	zmode = 0;
+
+            mb = 0;
+        }
+    }
+
+Exit:
+	*outNumBits = (bitPos - startPos);
+	BitBufferAdvance( bitstream, *outNumBits );
+	RequireAction( bitstream->cur <= bitstream->end, status = kALAC_ParamError; );
+
+    return status;
+}

+ 370 - 0
components/spotify/cspot/bell/external/alac/codec/ag_enc.c

@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ag_enc.c
+	
+	Contains:   Adaptive Golomb encode routines.
+
+	Copyright:	(c) 2001-2011 Apple, Inc.
+*/
+
+#include "aglib.h"
+#include "ALACBitUtilities.h"
+#include "EndianPortable.h"
+#include "ALACAudioTypes.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if __GNUC__ && TARGET_OS_MAC
+	#if __POWERPC__
+		#include <ppc_intrinsics.h>
+	#else
+		#include <libkern/OSByteOrder.h>
+	#endif
+#endif
+
+#define CODE_TO_LONG_MAXBITS	32
+#define N_MAX_MEAN_CLAMP		0xffff
+#define N_MEAN_CLAMP_VAL		0xffff
+#define REPORT_VAL  40
+
+#if __GNUC__
+#define ALWAYS_INLINE		__attribute__((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+
+/*	And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
+	to help the compiler out.   In many cases this required manual inlining or a macro.  Sorry
+	if it is ugly but the performance gains are well worth it.
+	- WSK 5/19/04
+*/
+
+// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
+static inline int32_t lead( int32_t m )
+{
+	long j;
+	unsigned long c = (1ul << 31);
+
+	for(j=0; j < 32; j++)
+	{
+		if((c & m) != 0)
+			break;
+		c >>= 1;
+	}
+	return (j);
+}
+
+#define arithmin(a, b) ((a) < (b) ? (a) : (b))
+
+static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
+{
+    int32_t result;
+
+    x += 3;
+    result = lead(x);
+
+    return 31 - result;
+}
+
+static inline int32_t ALWAYS_INLINE abs_func( int32_t a )
+{
+	// note: the CW PPC intrinsic __abs() turns into these instructions so no need to try and use it
+	int32_t isneg  = a >> 31;
+	int32_t xorval = a ^ isneg;
+	int32_t result = xorval-isneg;
+	
+	return result;	
+}
+
+static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
+{
+	// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
+	uint32_t		value;
+	
+	value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
+			 ((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
+	return value;
+}
+
+#if PRAGMA_MARK
+#pragma mark -
+#endif
+
+static inline int32_t dyn_code(int32_t m, int32_t k, int32_t n, uint32_t *outNumBits)
+{
+	uint32_t 	div, mod, de;
+	uint32_t	numBits;
+	uint32_t	value;
+
+	//Assert( n >= 0 );
+
+	div = n/m;
+
+	if(div >= MAX_PREFIX_16)
+	{
+		numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
+		value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
+	}
+	else
+	{
+		mod = n%m;
+		de = (mod == 0);
+		numBits = div + k + 1 - de;
+		value = (((1<<div)-1)<<(numBits-div)) + mod + 1 - de;
+
+		// if coding this way is bigger than doing escape, then do escape
+		if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16)
+		{
+		    numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
+		    value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;            
+		}
+	}
+	
+	*outNumBits = numBits;
+
+	return (int32_t) value;
+}
+
+
+static inline int32_t dyn_code_32bit(int32_t maxbits, uint32_t m, uint32_t k, uint32_t n, uint32_t *outNumBits, uint32_t *outValue, uint32_t *overflow, uint32_t *overflowbits)
+{
+	uint32_t 	div, mod, de;
+	uint32_t	numBits;
+	uint32_t	value;
+	int32_t			didOverflow = 0;
+
+	div = n/m;
+
+	if (div < MAX_PREFIX_32)
+	{
+		mod = n - (m * div);
+
+		de = (mod == 0);
+		numBits = div + k + 1 - de;
+		value = (((1<<div)-1)<<(numBits-div)) + mod + 1 - de;		
+		if (numBits > 25)
+			goto codeasescape;
+	}
+	else
+	{
+codeasescape:
+		numBits = MAX_PREFIX_32;
+		value = (((1<<MAX_PREFIX_32)-1));
+		*overflow = n;
+		*overflowbits = maxbits;
+		didOverflow = 1;
+	}
+	
+	*outNumBits = numBits;
+	*outValue = value;
+
+	return didOverflow;
+}
+
+
+static inline void ALWAYS_INLINE dyn_jam_noDeref(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
+{
+	uint32_t	*i = (uint32_t *)(out + (bitPos >> 3));
+	uint32_t	mask;
+	uint32_t	curr;
+	uint32_t	shift;
+
+	//Assert( numBits <= 32 );
+
+	curr = *i;
+	curr = Swap32NtoB( curr );
+
+	shift = 32 - (bitPos & 7) - numBits;
+
+	mask = ~0u >> (32 - numBits);		// mask must be created in two steps to avoid compiler sequencing ambiguity
+	mask <<= shift;
+
+	value  = (value << shift) & mask;
+	value |= curr & ~mask;
+	
+	*i = Swap32BtoN( value );
+}
+
+
+static inline void ALWAYS_INLINE dyn_jam_noDeref_large(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
+{
+	uint32_t *	i = (uint32_t *)(out + (bitPos>>3));
+	uint32_t	w;
+	uint32_t	curr;
+	uint32_t	mask;
+	int32_t			shiftvalue = (32 - (bitPos&7) - numBits);
+	
+	//Assert(numBits <= 32);
+
+	curr = *i;
+	curr = Swap32NtoB( curr );
+
+	if (shiftvalue < 0)
+	{
+		uint8_t 	tailbyte;
+		uint8_t 	*tailptr;
+
+		w = value >> -shiftvalue;
+		mask = ~0u >> -shiftvalue;
+		w |= (curr & ~mask);
+
+		tailptr = ((uint8_t *)i) + 4;
+		tailbyte = (value << ((8+shiftvalue))) & 0xff;
+		*tailptr = (uint8_t)tailbyte;
+	}
+	else
+	{
+		mask = ~0u >> (32 - numBits);
+		mask <<= shiftvalue;			// mask must be created in two steps to avoid compiler sequencing ambiguity
+
+		w  = (value << shiftvalue) & mask;
+		w |= curr & ~mask;
+	}
+	
+	*i = Swap32BtoN( w );
+}
+
+
+int32_t dyn_comp( AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits )
+{
+    unsigned char *		out;
+    uint32_t		bitPos, startPos;
+    uint32_t			m, k, n, c, mz, nz;
+    uint32_t		numBits;
+    uint32_t			value;
+    int32_t				del, zmode;
+	uint32_t		overflow, overflowbits;
+    int32_t					status;
+
+    // shadow the variables in params so there's not the dereferencing overhead
+    uint32_t		mb, pb, kb, wb;
+    int32_t					rowPos = 0;
+    int32_t					rowSize = params->sw;
+    int32_t					rowJump = (params->fw) - rowSize;
+    int32_t *			inPtr = pc;
+
+	*outNumBits = 0;
+	RequireAction( (bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError; );
+
+	out = bitstream->cur;
+	startPos = bitstream->bitIndex;
+    bitPos = startPos;
+
+    mb = params->mb = params->mb0;
+    pb = params->pb;
+    kb = params->kb;
+    wb = params->wb;
+    zmode = 0;
+
+    c=0;
+	status = ALAC_noErr;
+
+    while (c < numSamples)
+    {
+        m  = mb >> QBSHIFT;
+        k = lg3a(m);
+        if ( k > kb)
+        {
+        	k = kb;
+        }
+        m = (1<<k)-1;
+
+        del = *inPtr++;
+        rowPos++;
+
+        n = (abs_func(del) << 1) - ((del >> 31) & 1) - zmode;
+		//Assert( 32-lead(n) <= bitSize );
+
+		if ( dyn_code_32bit(bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits) )
+		{
+			dyn_jam_noDeref(out, bitPos, numBits, value);
+			bitPos += numBits;			
+			dyn_jam_noDeref_large(out, bitPos, overflowbits, overflow);			
+			bitPos += overflowbits;
+		}
+		else
+		{
+			dyn_jam_noDeref(out, bitPos, numBits, value);
+			bitPos += numBits;
+		}
+      
+        c++;
+        if ( rowPos >= rowSize)
+        {
+        	rowPos = 0;
+        	inPtr += rowJump;
+        }
+
+        mb = pb * (n + zmode) + mb - ((pb *mb)>>QBSHIFT);
+
+		// update mean tracking if it's overflowed
+		if (n > N_MAX_MEAN_CLAMP)
+			mb = N_MEAN_CLAMP_VAL;
+
+        zmode = 0;
+
+        RequireAction(c <= numSamples, status = kALAC_ParamError; goto Exit; );
+
+        if (((mb << MMULSHIFT) < QB) && (c < numSamples))
+        {
+            zmode = 1;
+            nz = 0;
+
+            while(c<numSamples && *inPtr == 0)
+            {
+            	/* Take care of wrap-around globals. */
+                ++inPtr;
+                ++nz;
+                ++c;
+                if ( ++rowPos >= rowSize)
+                {
+                	rowPos = 0;
+                	inPtr += rowJump;
+                }
+
+                if(nz >= 65535)
+                {
+                	zmode = 0;
+                	break;
+                }
+            }
+
+            k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
+            mz = ((1<<k)-1) & wb;
+
+            value = dyn_code(mz, k, nz, &numBits);
+            dyn_jam_noDeref(out, bitPos, numBits, value);
+            bitPos += numBits;
+
+            mb = 0;
+        }
+    }
+
+    *outNumBits = (bitPos - startPos);
+	BitBufferAdvance( bitstream, *outNumBits );
+
+Exit:
+	return status;
+}

+ 81 - 0
components/spotify/cspot/bell/external/alac/codec/aglib.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		aglib.h
+	
+	Copyright:	(C) 2001-2011 Apple, Inc.
+*/
+
+#ifndef AGLIB_H
+#define AGLIB_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QBSHIFT 9
+#define QB (1<<QBSHIFT)
+#define PB0 40
+#define MB0 10
+#define KB0 14
+#define MAX_RUN_DEFAULT 255
+
+#define MMULSHIFT 2
+#define MDENSHIFT (QBSHIFT - MMULSHIFT - 1)
+#define MOFF ((1<<(MDENSHIFT-2)))
+
+#define BITOFF 24
+
+/* Max. prefix of 1's. */
+#define MAX_PREFIX_16			9
+#define MAX_PREFIX_TOLONG_16	15
+#define MAX_PREFIX_32			9
+
+/* Max. bits in 16-bit data type */
+#define MAX_DATATYPE_BITS_16	16
+
+typedef struct AGParamRec
+{
+    uint32_t mb, mb0, pb, kb, wb, qb;
+    uint32_t fw, sw;
+
+    uint32_t maxrun;
+
+    // fw = 1, sw = 1;
+
+} AGParamRec, *AGParamRecPtr;
+
+struct BitBuffer;
+
+void	set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth);
+void	set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun);
+
+int32_t		dyn_comp(AGParamRecPtr params, int32_t * pc, struct BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits);
+int32_t		dyn_decomp(AGParamRecPtr params, struct BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //#ifndef AGLIB_H

+ 85 - 0
components/spotify/cspot/bell/external/alac/codec/alac.vcxproj

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="ag_dec.c" />
+    <ClCompile Include="ag_enc.c" />
+    <ClCompile Include="ALACBitUtilities.c" />
+    <ClCompile Include="ALACDecoder.cpp" />
+    <ClCompile Include="ALACEncoder.cpp" />
+    <ClCompile Include="dp_dec.c" />
+    <ClCompile Include="dp_enc.c" />
+    <ClCompile Include="EndianPortable.c" />
+    <ClCompile Include="matrix_dec.c" />
+    <ClCompile Include="matrix_enc.c" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectGuid>{73ae36f4-6af9-46b0-a682-4321d57ef8e7}</ProjectGuid>
+    <RootNamespace>alac</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup>
+    <IntDir>build\$(Configuration)\$(Platform)</IntDir>	
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <OutDir>..\targets\win32\x86</OutDir>	
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <OutDir>..\targets\win32\$(Platform)</OutDir>	
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>false</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <Link>
+      <SubSystem>
+      </SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 42 - 0
components/spotify/cspot/bell/external/alac/codec/build.sh

@@ -0,0 +1,42 @@
+#!/bin/bash
+
+list="x86_64-linux-gnu-gcc i686-linux-gnu-gcc arm-linux-gnueabi-gcc aarch64-linux-gnu-gcc sparc64-linux-gnu-gcc mips-linux-gnu-gcc powerpc-linux-gnu-gcc"
+declare -A alias=( [i686-linux-gnu-gcc]=x86-linux-gnu-gcc )
+declare -a compilers
+
+IFS= read -ra candidates <<< "$list"
+
+# first select platforms/compilers
+for cc in ${candidates[@]}
+do
+	# check compiler first
+	if ! command -v $cc &> /dev/null; then
+		continue
+	fi
+	
+	if [[ $# == 0 ]]; then
+		compilers+=($cc)
+		continue
+	fi
+
+	for arg in $@
+	do
+		if [[ ${alias[$cc]:-$cc} =~ $arg ]]; then 
+			compilers+=($cc)
+		fi
+	done
+done
+
+for cc in ${compilers[@]}
+do
+	IFS=- read -r platform host dummy <<< ${alias[$cc]:-$cc}
+	
+	make clean && make CC=$cc
+	mkdir -p ../targets/$host/$platform
+	cp libalac.a $_
+done
+
+mkdir -p ../targets/include
+cp ALACAudioTypes.h $_
+cp ALACEncoder.h $_
+cp ALACDecoder.h $_

+ 381 - 0
components/spotify/cspot/bell/external/alac/codec/dp_dec.c

@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		dp_dec.c
+
+	Contains:	Dynamic Predictor decode routines
+
+	Copyright:	(c) 2001-2011 Apple, Inc.
+*/
+
+
+#include "dplib.h"
+#include <string.h>
+
+#if __GNUC__
+#define ALWAYS_INLINE		__attribute__((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+#if TARGET_CPU_PPC && (__MWERKS__ >= 0x3200)
+// align loops to a 16 byte boundary to make the G5 happy
+#pragma function_align 16
+#define LOOP_ALIGN			asm { align 16 }
+#else
+#define LOOP_ALIGN
+#endif
+
+static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
+{
+    int32_t negishift;
+	
+    negishift = ((uint32_t)-i) >> 31;
+    return negishift | (i >> 31);
+}
+
+void unpc_block( int32_t * pc1, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
+{
+	register int16_t	a0, a1, a2, a3;
+	register int32_t	b0, b1, b2, b3;
+	int32_t					j, k, lim;
+	int32_t				sum1, sg, sgn, top, dd;
+	int32_t *			pout;
+	int32_t				del, del0;
+	uint32_t			chanshift = 32 - chanbits;
+	int32_t				denhalf = 1<<(denshift-1);
+
+	out[0] = pc1[0];
+	if ( numactive == 0 )
+	{
+		// just copy if numactive == 0 (but don't bother if in/out pointers the same)
+		if ( (num > 1)  && (pc1 != out) )
+			memcpy( &out[1], &pc1[1], (num - 1) * sizeof(int32_t) );
+		return;
+	}
+	if ( numactive == 31 )
+	{
+		// short-circuit if numactive == 31
+		int32_t		prev;
+		
+		/*	this code is written such that the in/out buffers can be the same
+			to conserve buffer space on embedded devices like the iPod
+			
+			(original code)
+			for ( j = 1; j < num; j++ )
+				del = pc1[j] + out[j-1];
+				out[j] = (del << chanshift) >> chanshift;
+		*/
+		prev = out[0];
+		for ( j = 1; j < num; j++ )
+		{
+			del = pc1[j] + prev;
+			prev = (del << chanshift) >> chanshift;
+			out[j] = prev;
+		}
+		return;
+	}
+
+	for ( j = 1; j <= numactive; j++ )
+	{
+		del = pc1[j] + out[j-1];
+		out[j] = (del << chanshift) >> chanshift;
+	}
+
+	lim = numactive + 1;
+
+	if ( numactive == 4 )
+	{
+		// optimization for numactive == 4
+		register int16_t	a0, a1, a2, a3;
+		register int32_t	b0, b1, b2, b3;
+
+		a0 = coefs[0];
+		a1 = coefs[1];
+		a2 = coefs[2];
+		a3 = coefs[3];
+
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			top = out[j - lim];
+			pout = out + j - 1;
+
+			b0 = top - pout[0];
+			b1 = top - pout[-1];
+			b2 = top - pout[-2];
+			b3 = top - pout[-3];
+
+			sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
+
+			del = pc1[j];
+			del0 = del;
+			sg = sign_of_int(del);
+			del += top + sum1;
+
+			out[j] = (del << chanshift) >> chanshift;
+
+			if ( sg > 0 )
+			{
+				sgn = sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= (4 - 3) * ((sgn * b3) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= (4 - 2) * ((sgn * b2) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= (4 - 1) * ((sgn * b1) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				a0 -= sign_of_int( b0 );
+			}
+			else if ( sg < 0 )
+			{
+				// note: to avoid unnecessary negations, we flip the value of "sgn"
+				sgn = -sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= (4 - 3) * ((sgn * b3) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= (4 - 2) * ((sgn * b2) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= (4 - 1) * ((sgn * b1) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				a0 += sign_of_int( b0 );
+			}
+		}
+
+		coefs[0] = a0;
+		coefs[1] = a1;
+		coefs[2] = a2;
+		coefs[3] = a3;
+	}
+	else if ( numactive == 8 )
+	{
+		register int16_t	a4, a5, a6, a7;
+		register int32_t	b4, b5, b6, b7;
+
+		// optimization for numactive == 8
+		a0 = coefs[0];
+		a1 = coefs[1];
+		a2 = coefs[2];
+		a3 = coefs[3];
+		a4 = coefs[4];
+		a5 = coefs[5];
+		a6 = coefs[6];
+		a7 = coefs[7];
+
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			top = out[j - lim];
+			pout = out + j - 1;
+
+			b0 = top - (*pout--);
+			b1 = top - (*pout--);
+			b2 = top - (*pout--);
+			b3 = top - (*pout--);
+			b4 = top - (*pout--);
+			b5 = top - (*pout--);
+			b6 = top - (*pout--);
+			b7 = top - (*pout);
+			pout += 8;
+
+			sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
+					- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
+
+			del = pc1[j];
+			del0 = del;
+			sg = sign_of_int(del);
+			del += top + sum1;
+
+			out[j] = (del << chanshift) >> chanshift;
+
+			if ( sg > 0 )
+			{
+				sgn = sign_of_int( b7 );
+				a7 -= sgn;
+				del0 -= 1 * ((sgn * b7) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b6 );
+				a6 -= sgn;
+				del0 -= 2 * ((sgn * b6) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b5 );
+				a5 -= sgn;
+				del0 -= 3 * ((sgn * b5) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				sgn = sign_of_int( b4 );
+				a4 -= sgn;
+				del0 -= 4 * ((sgn * b4) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= 5 * ((sgn * b3) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= 6 * ((sgn * b2) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= 7 * ((sgn * b1) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				a0 -= sign_of_int( b0 );
+			}
+			else if ( sg < 0 )
+			{
+				// note: to avoid unnecessary negations, we flip the value of "sgn"
+				sgn = -sign_of_int( b7 );
+				a7 -= sgn;
+				del0 -= 1 * ((sgn * b7) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b6 );
+				a6 -= sgn;
+				del0 -= 2 * ((sgn * b6) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b5 );
+				a5 -= sgn;
+				del0 -= 3 * ((sgn * b5) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				sgn = -sign_of_int( b4 );
+				a4 -= sgn;
+				del0 -= 4 * ((sgn * b4) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= 5 * ((sgn * b3) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= 6 * ((sgn * b2) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= 7 * ((sgn * b1) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				a0 += sign_of_int( b0 );
+			}
+		}
+
+		coefs[0] = a0;
+		coefs[1] = a1;
+		coefs[2] = a2;
+		coefs[3] = a3;
+		coefs[4] = a4;
+		coefs[5] = a5;
+		coefs[6] = a6;
+		coefs[7] = a7;
+	}
+	else
+	{
+		// general case
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			sum1 = 0;
+			pout = out + j - 1;
+			top = out[j-lim];
+
+			for ( k = 0; k < numactive; k++ )
+				sum1 += coefs[k] * (pout[-k] - top);
+
+			del = pc1[j];
+			del0 = del;
+			sg = sign_of_int( del );
+			del += top + ((sum1 + denhalf) >> denshift);
+			out[j] = (del << chanshift) >> chanshift;
+
+			if ( sg > 0 )
+			{
+				for ( k = (numactive - 1); k >= 0; k-- )
+				{
+					dd = top - pout[-k];
+					sgn = sign_of_int( dd );
+					coefs[k] -= sgn;
+					del0 -= (numactive - k) * ((sgn * dd) >> denshift);
+					if ( del0 <= 0 )
+						break;
+				}
+			}
+			else if ( sg < 0 )
+			{
+				for ( k = (numactive - 1); k >= 0; k-- )
+				{
+					dd = top - pout[-k];
+					sgn = sign_of_int( dd );
+					coefs[k] += sgn;
+					del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
+					if ( del0 >= 0 )
+						break;
+				}
+			}
+		}
+	}
+}

+ 386 - 0
components/spotify/cspot/bell/external/alac/codec/dp_enc.c

@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		dp_enc.c
+
+	Contains:	Dynamic Predictor encode routines
+
+	Copyright:	(c) 2001-2011 Apple, Inc.
+*/
+
+#include "dplib.h"
+#include <string.h>
+
+#if __GNUC__
+#define ALWAYS_INLINE		__attribute__((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+#if TARGET_CPU_PPC && (__MWERKS__ >= 0x3200)
+// align loops to a 16 byte boundary to make the G5 happy
+#pragma function_align 16
+#define LOOP_ALIGN			asm { align 16 }
+#else
+#define LOOP_ALIGN
+#endif
+
+void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs )
+{
+	int32_t		k;
+	int32_t		den = 1 << denshift;
+
+	coefs[0] = (AINIT * den) >> 4;
+	coefs[1] = (BINIT * den) >> 4;
+	coefs[2] = (CINIT * den) >> 4;
+	for ( k = 3; k < numPairs; k++ )
+		coefs[k]  = 0;
+}
+
+void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs )
+{
+	int32_t k;
+
+	for ( k = 0; k < numPairs; k++ )
+		dstCoefs[k] = srcCoefs[k];
+}
+
+static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
+{
+    int32_t negishift;
+	
+    negishift = ((uint32_t)-i) >> 31;
+    return negishift | (i >> 31);
+}
+
+void pc_block( int32_t * in, int32_t * pc1, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
+{
+	register int16_t	a0, a1, a2, a3;
+	register int32_t	b0, b1, b2, b3;
+	int32_t					j, k, lim;
+	int32_t *			pin;
+	int32_t				sum1, dd;
+	int32_t				sg, sgn;
+	int32_t				top;
+	int32_t				del, del0;
+	uint32_t			chanshift = 32 - chanbits;
+	int32_t				denhalf = 1 << (denshift - 1);
+
+	pc1[0] = in[0];
+	if ( numactive == 0 )
+	{
+		// just copy if numactive == 0 (but don't bother if in/out pointers the same)
+		if ( (num > 1) && (in != pc1) )
+			memcpy( &pc1[1], &in[1], (num - 1) * sizeof(int32_t) );
+		return;
+	}
+	if ( numactive == 31 )
+	{
+		// short-circuit if numactive == 31
+		for( j = 1; j < num; j++ )
+		{
+			del = in[j] - in[j-1];
+			pc1[j] = (del << chanshift) >> chanshift;
+		}
+		return;
+	}
+	
+	for ( j = 1; j <= numactive; j++ )
+	{
+		del = in[j] - in[j-1];
+		pc1[j] = (del << chanshift) >> chanshift;
+	}
+
+	lim = numactive + 1;
+
+	if ( numactive == 4 )
+	{
+		// optimization for numactive == 4
+		a0 = coefs[0];
+		a1 = coefs[1];
+		a2 = coefs[2];
+		a3 = coefs[3];
+
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			top = in[j - lim];
+			pin = in + j - 1;
+
+			b0 = top - pin[0];
+			b1 = top - pin[-1];
+			b2 = top - pin[-2];
+			b3 = top - pin[-3];
+
+			sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
+
+			del = in[j] - top - sum1;
+			del = (del << chanshift) >> chanshift;
+			pc1[j] = del;	     
+			del0 = del;
+
+			sg = sign_of_int(del);
+			if ( sg > 0 )
+			{
+				sgn = sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= (4 - 3) * ((sgn * b3) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= (4 - 2) * ((sgn * b2) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= (4 - 1) * ((sgn * b1) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				a0 -= sign_of_int( b0 );
+			}
+			else if ( sg < 0 )
+			{
+				// note: to avoid unnecessary negations, we flip the value of "sgn"
+				sgn = -sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= (4 - 3) * ((sgn * b3) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= (4 - 2) * ((sgn * b2) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= (4 - 1) * ((sgn * b1) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				a0 += sign_of_int( b0 );
+			}
+		}
+
+		coefs[0] = a0;
+		coefs[1] = a1;
+		coefs[2] = a2;
+		coefs[3] = a3;
+	}
+	else if ( numactive == 8 )
+	{
+		// optimization for numactive == 8
+		register int16_t	a4, a5, a6, a7;
+		register int32_t	b4, b5, b6, b7;
+
+		a0 = coefs[0];
+		a1 = coefs[1];
+		a2 = coefs[2];
+		a3 = coefs[3];
+		a4 = coefs[4];
+		a5 = coefs[5];
+		a6 = coefs[6];
+		a7 = coefs[7];
+
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			top = in[j - lim];
+			pin = in + j - 1;
+
+			b0 = top - (*pin--);
+			b1 = top - (*pin--);
+			b2 = top - (*pin--);
+			b3 = top - (*pin--);
+			b4 = top - (*pin--);
+			b5 = top - (*pin--);
+			b6 = top - (*pin--);
+			b7 = top - (*pin);
+			pin += 8;
+
+			sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
+					- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
+
+			del = in[j] - top - sum1;
+			del = (del << chanshift) >> chanshift;
+			pc1[j] = del;	     
+			del0 = del;
+
+			sg = sign_of_int(del);
+			if ( sg > 0 )
+			{
+				sgn = sign_of_int( b7 );
+				a7 -= sgn;
+				del0 -= 1 * ((sgn * b7) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b6 );
+				a6 -= sgn;
+				del0 -= 2 * ((sgn * b6) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b5 );
+				a5 -= sgn;
+				del0 -= 3 * ((sgn * b5) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				sgn = sign_of_int( b4 );
+				a4 -= sgn;
+				del0 -= 4 * ((sgn * b4) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= 5 * ((sgn * b3) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= 6 * ((sgn * b2) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+				
+				sgn = sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= 7 * ((sgn * b1) >> denshift);
+				if ( del0 <= 0 )
+					continue;
+
+				a0 -= sign_of_int( b0 );
+			}
+			else if ( sg < 0 )
+			{
+				// note: to avoid unnecessary negations, we flip the value of "sgn"
+				sgn = -sign_of_int( b7 );
+				a7 -= sgn;
+				del0 -= 1 * ((sgn * b7) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b6 );
+				a6 -= sgn;
+				del0 -= 2 * ((sgn * b6) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b5 );
+				a5 -= sgn;
+				del0 -= 3 * ((sgn * b5) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				sgn = -sign_of_int( b4 );
+				a4 -= sgn;
+				del0 -= 4 * ((sgn * b4) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b3 );
+				a3 -= sgn;
+				del0 -= 5 * ((sgn * b3) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b2 );
+				a2 -= sgn;
+				del0 -= 6 * ((sgn * b2) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+				
+				sgn = -sign_of_int( b1 );
+				a1 -= sgn;
+				del0 -= 7 * ((sgn * b1) >> denshift);
+				if ( del0 >= 0 )
+					continue;
+
+				a0 += sign_of_int( b0 );
+			}
+		}
+
+		coefs[0] = a0;
+		coefs[1] = a1;
+		coefs[2] = a2;
+		coefs[3] = a3;
+		coefs[4] = a4;
+		coefs[5] = a5;
+		coefs[6] = a6;
+		coefs[7] = a7;
+	}
+	else
+	{
+//pc_block_general:
+		// general case
+		for ( j = lim; j < num; j++ )
+		{
+			LOOP_ALIGN
+
+			top = in[j - lim];
+			pin = in + j - 1;
+
+			sum1 = 0;
+			for ( k = 0; k < numactive; k++ )
+				sum1 -= coefs[k] * (top - pin[-k]);
+		
+			del = in[j] - top - ((sum1 + denhalf) >> denshift);
+			del = (del << chanshift) >> chanshift;
+			pc1[j] = del;
+			del0 = del;
+
+			sg = sign_of_int( del );
+			if ( sg > 0 )
+			{
+				for ( k = (numactive - 1); k >= 0; k-- )
+				{
+					dd = top - pin[-k];
+					sgn = sign_of_int( dd );
+					coefs[k] -= sgn;
+					del0 -= (numactive - k) * ((sgn * dd) >> denshift);
+					if ( del0 <= 0 )
+						break;
+				}
+			}
+			else if ( sg < 0 )
+			{
+				for ( k = (numactive - 1); k >= 0; k-- )
+				{
+					dd = top - pin[-k];
+					sgn = sign_of_int( dd );
+					coefs[k] += sgn;
+					del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
+					if ( del0 >= 0 )
+						break;
+				}
+			}
+		}
+	}
+}

+ 61 - 0
components/spotify/cspot/bell/external/alac/codec/dplib.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		dplib.h
+	
+	Contains:	Dynamic Predictor routines
+
+	Copyright:	Copyright (C) 2001-2011 Apple, Inc.
+*/
+
+#ifndef __DPLIB_H__
+#define __DPLIB_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// defines
+
+#define DENSHIFT_MAX  15
+#define DENSHIFT_DEFAULT 9
+#define AINIT 38
+#define BINIT (-29)
+#define CINIT (-2)
+#define NUMCOEPAIRS 16
+
+// prototypes
+
+void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs );
+void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs );
+
+// NOTE: these routines read at least "numactive" samples so the i/o buffers must be at least that big
+
+void pc_block( int32_t * in, int32_t * pc, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
+void unpc_block( int32_t * pc, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __DPLIB_H__ */

+ 390 - 0
components/spotify/cspot/bell/external/alac/codec/matrix_dec.c

@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		matrix_dec.c
+	
+	Contains:	ALAC mixing/matrixing decode routines.
+
+	Copyright:	(c) 2004-2011 Apple, Inc.
+*/
+
+#include "matrixlib.h"
+#include "ALACAudioTypes.h"
+
+// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
+#if TARGET_RT_BIG_ENDIAN
+	#define LBYTE	2
+	#define MBYTE	1
+	#define HBYTE	0
+#else
+	#define LBYTE	0
+	#define MBYTE	1
+	#define HBYTE	2
+#endif
+
+/*
+    There is no plain middle-side option; instead there are various mixing
+    modes including middle-side, each lossless, as embodied in the mix()
+    and unmix() functions.  These functions exploit a generalized middle-side
+    transformation:
+    
+    u := [(rL + (m-r)R)/m];
+    v := L - R;
+    
+    where [ ] denotes integer floor.  The (lossless) inverse is
+    
+    L = u + v - [rV/m];
+    R = L - v;
+*/
+
+// 16-bit routines
+
+void unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
+{
+	int16_t *	op = out;
+	int32_t 		j;
+
+	if ( mixres != 0 )
+	{
+		/* matrixed stereo */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			int32_t		l, r;
+
+			l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
+			r = l - v[j];
+
+			op[0] = (int16_t) l;
+			op[1] = (int16_t) r;
+			op += stride;
+		} 
+	}
+	else
+	{
+		/* Conventional separated stereo. */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			op[0] = (int16_t) u[j];
+			op[1] = (int16_t) v[j];
+			op += stride;
+		}
+	}
+}
+
+// 20-bit routines
+// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
+
+void unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
+{
+	uint8_t *	op = out;
+	int32_t 		j;
+
+	if ( mixres != 0 )
+	{
+		/* matrixed stereo */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			int32_t		l, r;
+
+			l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
+			r = l - v[j];
+
+			l <<= 4;
+			r <<= 4;
+
+			op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
+			op[MBYTE] = (uint8_t)((l >>  8) & 0xffu);
+			op[LBYTE] = (uint8_t)((l >>  0) & 0xffu);
+			op += 3;
+
+			op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
+			op[MBYTE] = (uint8_t)((r >>  8) & 0xffu);
+			op[LBYTE] = (uint8_t)((r >>  0) & 0xffu);
+
+			op += (stride - 1) * 3;
+		}
+	}
+	else 
+	{
+		/* Conventional separated stereo. */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			int32_t		val;
+
+			val = u[j] << 4;
+			op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+			op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+			op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+			op += 3;
+
+			val = v[j] << 4;
+			op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+			op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+			op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+
+			op += (stride - 1) * 3;
+		}
+	}
+}
+
+// 24-bit routines
+// - the 24 bits of data are right-justified in the input/output predictor buffers
+
+void unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
+				int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
+{
+	uint8_t *	op = out;
+	int32_t			shift = bytesShifted * 8;
+	int32_t		l, r;
+	int32_t 		j, k;
+
+	if ( mixres != 0 )
+	{
+		/* matrixed stereo */
+		if ( bytesShifted != 0 )
+		{
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
+				r = l - v[j];
+
+				l = (l << shift) | (uint32_t) shiftUV[k + 0];
+				r = (r << shift) | (uint32_t) shiftUV[k + 1];
+
+				op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((l >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((l >>  0) & 0xffu);
+				op += 3;
+
+				op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((r >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((r >>  0) & 0xffu);
+
+				op += (stride - 1) * 3;
+			}
+		}
+		else
+		{
+			for ( j = 0; j < numSamples; j++ )
+			{
+				l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
+				r = l - v[j];
+
+				op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((l >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((l >>  0) & 0xffu);
+				op += 3;
+
+				op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((r >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((r >>  0) & 0xffu);
+
+				op += (stride - 1) * 3;
+			}
+		}
+	}
+	else 
+	{
+		/* Conventional separated stereo. */
+		if ( bytesShifted != 0 )
+		{
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				l = u[j];
+				r = v[j];
+
+				l = (l << shift) | (uint32_t) shiftUV[k + 0];
+				r = (r << shift) | (uint32_t) shiftUV[k + 1];
+
+				op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((l >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((l >>  0) & 0xffu);
+				op += 3;
+
+				op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((r >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((r >>  0) & 0xffu);
+
+				op += (stride - 1) * 3;
+			}
+		}
+		else
+		{
+			for ( j = 0; j < numSamples; j++ )
+			{
+				int32_t		val;
+
+				val = u[j];
+				op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+				op += 3;
+
+				val = v[j];
+				op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+				op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+				op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+
+				op += (stride - 1) * 3;
+			}
+		}
+	}
+}
+
+// 32-bit routines
+// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
+// - otherwise, the calculations might overflow into the 33rd bit and be lost
+// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
+
+void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
+				int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
+{
+	int32_t *	op = out;
+	int32_t			shift = bytesShifted * 8;
+	int32_t		l, r;
+	int32_t 		j, k;
+
+	if ( mixres != 0 )
+	{
+		//Assert( bytesShifted != 0 );
+
+		/* matrixed stereo with shift */
+		for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+		{
+			int32_t		lt, rt;
+
+			lt = u[j];
+			rt = v[j];
+			
+			l = lt + rt - ((mixres * rt) >> mixbits);
+			r = l - rt;
+
+			op[0] = (l << shift) | (uint32_t) shiftUV[k + 0];
+			op[1] = (r << shift) | (uint32_t) shiftUV[k + 1];
+			op += stride;
+		} 
+	}
+	else
+	{
+		if ( bytesShifted == 0 )
+		{
+			/* interleaving w/o shift */
+			for ( j = 0; j < numSamples; j++ )
+			{
+				op[0] = u[j];
+				op[1] = v[j];
+				op += stride;
+			}
+		}
+		else
+		{
+			/* interleaving with shift */
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				op[0] = (u[j] << shift) | (uint32_t) shiftUV[k + 0];
+				op[1] = (v[j] << shift) | (uint32_t) shiftUV[k + 1];
+				op += stride;
+			}
+		}
+	}
+}
+
+// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
+
+void copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
+{
+	uint8_t *	op = out;
+	int32_t			j;
+
+	for ( j = 0; j < numSamples; j++ )
+	{
+		int32_t		val = in[j];
+
+		op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+		op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+		op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+		op += (stride * 3);
+	}
+}
+
+void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
+{
+	uint8_t *	op = out;
+	int32_t			shiftVal = bytesShifted * 8;
+	int32_t			j;
+
+	//Assert( bytesShifted != 0 );
+
+	for ( j = 0; j < numSamples; j++ )
+	{
+		int32_t		val = in[j];
+
+		val = (val << shiftVal) | (uint32_t) shift[j];
+
+		op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
+		op[MBYTE] = (uint8_t)((val >>  8) & 0xffu);
+		op[LBYTE] = (uint8_t)((val >>  0) & 0xffu);
+		op += (stride * 3);
+	}
+}
+
+void copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
+{
+	uint8_t *	op = out;
+	int32_t			j;
+
+	// 32-bit predictor values are right-aligned but 20-bit output values should be left-aligned
+	// in the 24-bit output buffer
+	for ( j = 0; j < numSamples; j++ )
+	{
+		int32_t		val = in[j];
+
+		op[HBYTE] = (uint8_t)((val >> 12) & 0xffu);
+		op[MBYTE] = (uint8_t)((val >>  4) & 0xffu);
+		op[LBYTE] = (uint8_t)((val <<  4) & 0xffu);
+		op += (stride * 3);
+	}
+}
+
+void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
+{
+	int32_t			i, j;
+
+	// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
+	for ( i = 0, j = 0; i < numSamples; i++, j += stride )
+		out[j] = in[i];
+}
+
+void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
+{
+	int32_t *		op = out;
+	uint32_t		shiftVal = bytesShifted * 8;
+	int32_t				j;
+
+	//Assert( bytesShifted != 0 );
+
+	// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
+	for ( j = 0; j < numSamples; j++ )
+	{
+		op[0] = (in[j] << shiftVal) | (uint32_t) shift[j];
+		op += stride;
+	}
+}

+ 342 - 0
components/spotify/cspot/bell/external/alac/codec/matrix_enc.c

@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		matrix_enc.c
+	
+	Contains:	ALAC mixing/matrixing encode routines.
+
+	Copyright:	(c) 2004-2011 Apple, Inc.
+*/
+
+#include "matrixlib.h"
+#include "ALACAudioTypes.h"
+
+// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
+#if TARGET_RT_BIG_ENDIAN
+	#define LBYTE	2
+	#define MBYTE	1
+	#define HBYTE	0
+#else
+	#define LBYTE	0
+	#define MBYTE	1
+	#define HBYTE	2
+#endif
+
+/*
+    There is no plain middle-side option; instead there are various mixing
+    modes including middle-side, each lossless, as embodied in the mix()
+    and unmix() functions.  These functions exploit a generalized middle-side
+    transformation:
+    
+    u := [(rL + (m-r)R)/m];
+    v := L - R;
+    
+    where [ ] denotes integer floor.  The (lossless) inverse is
+    
+    L = u + v - [rV/m];
+    R = L - v;
+*/
+
+// 16-bit routines
+
+void mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
+{
+	int16_t	*	ip = in;
+	int32_t			j;
+
+	if ( mixres != 0 )
+	{
+		int32_t		mod = 1 << mixbits;
+		int32_t		m2;
+
+		/* matrixed stereo */
+		m2 = mod - mixres;
+		for ( j = 0; j < numSamples; j++ )
+		{
+			int32_t		l, r;
+
+			l = (int32_t) ip[0];
+			r = (int32_t) ip[1];
+			ip += stride;
+			u[j] = (mixres * l + m2 * r) >> mixbits;
+			v[j] = l - r;
+		}
+	}
+	else
+	{
+		/* Conventional separated stereo. */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			u[j] = (int32_t) ip[0];
+			v[j] = (int32_t) ip[1];
+			ip += stride;
+		}
+	}
+}
+
+// 20-bit routines
+// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
+
+void mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
+{
+	int32_t		l, r;
+	uint8_t *	ip = in;
+	int32_t			j;
+
+	if ( mixres != 0 )
+	{
+		/* matrixed stereo */
+		int32_t		mod = 1 << mixbits;
+		int32_t		m2 = mod - mixres;
+
+		for ( j = 0; j < numSamples; j++ )
+		{
+			l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+			l = (l << 8) >> 12;
+			ip += 3;
+
+			r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+			r = (r << 8) >> 12;
+			ip += (stride - 1) * 3;
+
+			u[j] = (mixres * l + m2 * r) >> mixbits;
+			v[j] = l - r;
+		} 
+	}
+	else
+	{
+		/* Conventional separated stereo. */
+		for ( j = 0; j < numSamples; j++ )
+		{
+			l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+			u[j] = (l << 8) >> 12;
+			ip += 3;
+
+			r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+			v[j] = (r << 8) >> 12;
+			ip += (stride - 1) * 3;
+		}
+	}
+}
+
+// 24-bit routines
+// - the 24 bits of data are right-justified in the input/output predictor buffers
+
+void mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
+			int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
+{	
+	int32_t		l, r;
+	uint8_t *	ip = in;
+	int32_t			shift = bytesShifted * 8;
+	uint32_t	mask  = (1ul << shift) - 1;
+	int32_t			j, k;
+
+	if ( mixres != 0 )
+	{
+		/* matrixed stereo */
+		int32_t		mod = 1 << mixbits;
+		int32_t		m2 = mod - mixres;
+
+		if ( bytesShifted != 0 )
+		{
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				l = (l << 8) >> 8;
+				ip += 3;
+
+				r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				r = (r << 8) >> 8;
+				ip += (stride - 1) * 3;
+
+				shiftUV[k + 0] = (uint16_t)(l & mask);
+				shiftUV[k + 1] = (uint16_t)(r & mask);
+				
+				l >>= shift;
+				r >>= shift;
+
+				u[j] = (mixres * l + m2 * r) >> mixbits;
+				v[j] = l - r;
+			}
+		}
+		else
+		{
+			for ( j = 0; j < numSamples; j++ )
+			{
+				l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				l = (l << 8) >> 8;
+				ip += 3;
+
+				r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				r = (r << 8) >> 8;
+				ip += (stride - 1) * 3;
+
+				u[j] = (mixres * l + m2 * r) >> mixbits;
+				v[j] = l - r;
+			}
+		}
+	}
+	else
+	{
+		/* Conventional separated stereo. */
+		if ( bytesShifted != 0 )
+		{
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				l = (l << 8) >> 8;
+				ip += 3;
+
+				r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				r = (r << 8) >> 8;
+				ip += (stride - 1) * 3;
+
+				shiftUV[k + 0] = (uint16_t)(l & mask);
+				shiftUV[k + 1] = (uint16_t)(r & mask);
+				
+				l >>= shift;
+				r >>= shift;
+
+				u[j] = l;
+				v[j] = r;
+			}
+		}
+		else
+		{
+			for ( j = 0; j < numSamples; j++ )
+			{
+				l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				u[j] = (l << 8) >> 8;
+				ip += 3;
+
+				r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+				v[j] = (r << 8) >> 8;
+				ip += (stride - 1) * 3;
+			}
+		}
+	}
+}
+
+// 32-bit routines
+// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
+// - otherwise, the calculations might overflow into the 33rd bit and be lost
+// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
+
+void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
+			int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
+{
+	int32_t	*	ip = in;
+	int32_t			shift = bytesShifted * 8;
+	uint32_t	mask  = (1ul << shift) - 1;
+	int32_t		l, r;
+	int32_t			j, k;
+
+	if ( mixres != 0 )
+	{
+		int32_t		mod = 1 << mixbits;
+		int32_t		m2;
+
+		//Assert( bytesShifted != 0 );
+
+		/* matrixed stereo with shift */
+		m2 = mod - mixres;
+		for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+		{
+			l = ip[0];
+			r = ip[1];
+			ip += stride;
+
+			shiftUV[k + 0] = (uint16_t)(l & mask);
+			shiftUV[k + 1] = (uint16_t)(r & mask);
+			
+			l >>= shift;
+			r >>= shift;
+
+			u[j] = (mixres * l + m2 * r) >> mixbits;
+			v[j] = l - r;
+		}
+	}
+	else
+	{
+		if ( bytesShifted == 0 )
+		{
+			/* de-interleaving w/o shift */
+			for ( j = 0; j < numSamples; j++ )
+			{
+				u[j] = ip[0];
+				v[j] = ip[1];
+				ip += stride;
+			}
+		}
+		else
+		{
+			/* de-interleaving with shift */
+			for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
+			{
+				l = ip[0];
+				r = ip[1];
+				ip += stride;
+
+				shiftUV[k + 0] = (uint16_t)(l & mask);
+				shiftUV[k + 1] = (uint16_t)(r & mask);
+				
+				l >>= shift;
+				r >>= shift;
+
+				u[j] = l;
+				v[j] = r;
+			}
+		}
+	}
+}
+
+// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
+
+void copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
+{
+	uint8_t *	ip = in;
+	int32_t			j;
+
+	for ( j = 0; j < numSamples; j++ )
+	{
+		int32_t			val;
+
+		// 20-bit values are left-aligned in the 24-bit input buffer but right-aligned in the 32-bit output buffer
+		val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+		out[j] = (val << 8) >> 12;
+		ip += stride * 3;
+	}
+}
+
+void copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
+{
+	uint8_t *	ip = in;
+	int32_t			j;
+
+	for ( j = 0; j < numSamples; j++ )
+	{
+		int32_t			val;
+
+		val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
+		out[j] = (val << 8) >> 8;
+		ip += stride * 3;
+	}
+}

+ 80 - 0
components/spotify/cspot/bell/external/alac/codec/matrixlib.h

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		matrixlib.h
+	
+	Contains:	ALAC mixing/matrixing routines to/from 32-bit predictor buffers.
+
+	Copyright:	Copyright (C) 2004 to 2011 Apple, Inc.
+*/
+
+#ifndef __MATRIXLIB_H
+#define __MATRIXLIB_H
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 16-bit routines
+void	mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
+void	unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
+
+// 20-bit routines
+void	mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
+void	unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
+
+// 24-bit routines
+// - 24-bit data sometimes compresses better by shifting off the bottom byte so these routines deal with
+//	 the specified "unused lower bytes" in the combined "shift" buffer
+void	mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
+				int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
+void	unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
+				 int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
+
+// 32-bit routines
+// - note that these really expect the internal data width to be < 32-bit but the arrays are 32-bit
+// - otherwise, the calculations might overflow into the 33rd bit and be lost
+// - therefore, these routines deal with the specified "unused lower" bytes in the combined "shift" buffer
+void	mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
+				int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
+void	unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
+				 int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
+
+// 20/24/32-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
+void	copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
+void	copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
+
+void	copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
+void	copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
+void	copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
+
+void	copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
+void	copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __MATRIXLIB_H */

+ 20 - 0
components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alacConvert", "alacConvert.vcproj", "{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.Build.0 = Debug|Win32
+		{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.ActiveCfg = Release|Win32
+		{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 379 - 0
components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.vcproj

@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="alacConvert"
+	ProjectGUID="{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
+	RootNamespace="alacConvert"
+	Keyword="ManagedCProj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\codec;.\"
+				PreprocessorDefinitions="WIN32;_DEBUG;TARGET_OS_WIN32"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				AssemblyDebug="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\codec\ag_dec.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\ag_enc.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\ALACBitUtilities.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\ALACDecoder.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\ALACEncoder.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="CAFFileALAC.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\dp_dec.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\dp_enc.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\EndianPortable.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="main.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\matrix_dec.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\codec\matrix_enc.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\codec\aglib.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\ALACAudioTypes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\ALACBitUtilities.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\ALACDecoder.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\ALACEncoder.h"
+				>
+			</File>
+			<File
+				RelativePath="CAFFileALAC.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\dplib.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\EndianPortable.h"
+				>
+			</File>
+			<File
+				RelativePath="..\codec\matrixlib.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdint.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 362 - 0
components/spotify/cspot/bell/external/alac/convert-utility/ALACconvert.xcodeproj/project.pbxproj

@@ -0,0 +1,362 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 071120811405C91B007FF1B0 /* ALACBitUtilities.c */; };
+		074B586A1405B97E0060A703 /* ag_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58611405B97E0060A703 /* ag_dec.c */; };
+		074B586B1405B97E0060A703 /* ag_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58621405B97E0060A703 /* ag_enc.c */; };
+		074B586D1405B97E0060A703 /* dp_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58641405B97E0060A703 /* dp_dec.c */; };
+		074B586E1405B97E0060A703 /* dp_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58651405B97E0060A703 /* dp_enc.c */; };
+		074B58791405B98B0060A703 /* matrix_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58751405B98B0060A703 /* matrix_dec.c */; };
+		074B587A1405B98B0060A703 /* matrix_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58761405B98B0060A703 /* matrix_enc.c */; };
+		075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */; };
+		07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F445141999F800035453 /* ALACDecoder.cpp */; };
+		07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F447141999F800035453 /* ALACEncoder.cpp */; };
+		07E06D00142968F2002489A3 /* EndianPortable.c in Sources */ = {isa = PBXBuildFile; fileRef = 07E06CFE142968F2002489A3 /* EndianPortable.c */; };
+		A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A98FBFAC06EBB5AB00E7B080 /* main.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		8DD76FAF0486AB0100D96B5E /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		071120811405C91B007FF1B0 /* ALACBitUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ALACBitUtilities.c; sourceTree = "<group>"; };
+		071120821405C91B007FF1B0 /* ALACBitUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACBitUtilities.h; sourceTree = "<group>"; };
+		074B58611405B97E0060A703 /* ag_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_dec.c; sourceTree = "<group>"; };
+		074B58621405B97E0060A703 /* ag_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_enc.c; sourceTree = "<group>"; };
+		074B58631405B97E0060A703 /* aglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aglib.h; sourceTree = "<group>"; };
+		074B58641405B97E0060A703 /* dp_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_dec.c; sourceTree = "<group>"; };
+		074B58651405B97E0060A703 /* dp_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_enc.c; sourceTree = "<group>"; };
+		074B58741405B98B0060A703 /* dplib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dplib.h; sourceTree = "<group>"; };
+		074B58751405B98B0060A703 /* matrix_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_dec.c; sourceTree = "<group>"; };
+		074B58761405B98B0060A703 /* matrix_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_enc.c; sourceTree = "<group>"; };
+		074B587B1405B9920060A703 /* matrixlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrixlib.h; sourceTree = "<group>"; };
+		075CBE12141EC2080089DFF0 /* CAFFileALAC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAFFileALAC.h; sourceTree = "<group>"; };
+		075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CAFFileALAC.cpp; sourceTree = "<group>"; };
+		075CBE1F142187450089DFF0 /* ALACAudioTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACAudioTypes.h; sourceTree = "<group>"; };
+		07B7F445141999F800035453 /* ALACDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACDecoder.cpp; sourceTree = "<group>"; };
+		07B7F446141999F800035453 /* ALACDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACDecoder.h; sourceTree = "<group>"; };
+		07B7F447141999F800035453 /* ALACEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACEncoder.cpp; sourceTree = "<group>"; };
+		07B7F448141999F800035453 /* ALACEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACEncoder.h; sourceTree = "<group>"; };
+		07E06CFE142968F2002489A3 /* EndianPortable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EndianPortable.c; sourceTree = "<group>"; };
+		07E06CFF142968F2002489A3 /* EndianPortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EndianPortable.h; sourceTree = "<group>"; };
+		8DD76FB20486AB0100D96B5E /* alacconvert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = alacconvert; sourceTree = BUILT_PRODUCTS_DIR; };
+		A98FBFAC06EBB5AB00E7B080 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		074B58601405B8160060A703 /* codec */ = {
+			isa = PBXGroup;
+			children = (
+				074B58611405B97E0060A703 /* ag_dec.c */,
+				074B58621405B97E0060A703 /* ag_enc.c */,
+				074B58631405B97E0060A703 /* aglib.h */,
+				074B58641405B97E0060A703 /* dp_dec.c */,
+				074B58651405B97E0060A703 /* dp_enc.c */,
+				074B58741405B98B0060A703 /* dplib.h */,
+				074B58751405B98B0060A703 /* matrix_dec.c */,
+				074B58761405B98B0060A703 /* matrix_enc.c */,
+				074B587B1405B9920060A703 /* matrixlib.h */,
+				075CBE1F142187450089DFF0 /* ALACAudioTypes.h */,
+				071120811405C91B007FF1B0 /* ALACBitUtilities.c */,
+				071120821405C91B007FF1B0 /* ALACBitUtilities.h */,
+				07B7F445141999F800035453 /* ALACDecoder.cpp */,
+				07B7F446141999F800035453 /* ALACDecoder.h */,
+				07B7F447141999F800035453 /* ALACEncoder.cpp */,
+				07B7F448141999F800035453 /* ALACEncoder.h */,
+				07E06CFE142968F2002489A3 /* EndianPortable.c */,
+				07E06CFF142968F2002489A3 /* EndianPortable.h */,
+			);
+			name = codec;
+			path = ../codec;
+			sourceTree = SOURCE_ROOT;
+		};
+		08FB7794FE84155DC02AAC07 /* ALACconvert */ = {
+			isa = PBXGroup;
+			children = (
+				08FB7795FE84155DC02AAC07 /* Source */,
+				1AB674ADFE9D54B511CA2CBB /* Products */,
+			);
+			name = ALACconvert;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				A98FBFAC06EBB5AB00E7B080 /* main.cpp */,
+				075CBE12141EC2080089DFF0 /* CAFFileALAC.h */,
+				075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */,
+				074B58601405B8160060A703 /* codec */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		1AB674ADFE9D54B511CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8DD76FB20486AB0100D96B5E /* alacconvert */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		8DD76FAA0486AB0100D96B5E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		8DD76FA90486AB0100D96B5E /* ALACconvert */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */;
+			buildPhases = (
+				8DD76FAA0486AB0100D96B5E /* Headers */,
+				8DD76FAB0486AB0100D96B5E /* Sources */,
+				8DD76FAD0486AB0100D96B5E /* Frameworks */,
+				8DD76FAE0486AB0100D96B5E /* Rez */,
+				8DD76FAF0486AB0100D96B5E /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ALACconvert;
+			productInstallPath = "$(HOME)/bin";
+			productName = ALACconvert;
+			productReference = 8DD76FB20486AB0100D96B5E /* alacconvert */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */;
+			compatibilityVersion = "Xcode 2.4";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 08FB7794FE84155DC02AAC07 /* ALACconvert */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8DD76FA90486AB0100D96B5E /* ALACconvert */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXRezBuildPhase section */
+		8DD76FAE0486AB0100D96B5E /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8DD76FAB0486AB0100D96B5E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */,
+				074B586A1405B97E0060A703 /* ag_dec.c in Sources */,
+				074B586B1405B97E0060A703 /* ag_enc.c in Sources */,
+				074B586D1405B97E0060A703 /* dp_dec.c in Sources */,
+				074B586E1405B97E0060A703 /* dp_enc.c in Sources */,
+				074B58791405B98B0060A703 /* matrix_dec.c in Sources */,
+				074B587A1405B98B0060A703 /* matrix_enc.c in Sources */,
+				071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */,
+				07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */,
+				07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */,
+				075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */,
+				07E06D00142968F2002489A3 /* EndianPortable.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		A9E1644B087DFBDE006BF7C2 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				COPY_PHASE_STRIP = NO;
+				DEBUGGING_SYMBOLS = YES;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_ENABLE_TRIGRAPHS = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = NO;
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = "$(HOME)/bin";
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = alacconvert;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+				WARNING_CFLAGS = (
+					"-Wmost",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Development;
+		};
+		A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				COPY_PHASE_STRIP = YES;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_ENABLE_TRIGRAPHS = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = NO;
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = "$(HOME)/bin";
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = alacconvert;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+				WARNING_CFLAGS = (
+					"-Wmost",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+				);
+				ZERO_LINK = NO;
+			};
+			name = "Deployment - Fat";
+		};
+		A9E1644D087DFBDE006BF7C2 /* Default */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_ENABLE_TRIGRAPHS = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = NO;
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = "$(HOME)/bin";
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = alacconvert;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+				WARNING_CFLAGS = (
+					"-Wmost",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+				);
+			};
+			name = Default;
+		};
+		A9E1644F087DFBDE006BF7C2 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				HEADER_SEARCH_PATHS = "";
+			};
+			name = Development;
+		};
+		A9E16450087DFBDE006BF7C2 /* Deployment - Fat */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				HEADER_SEARCH_PATHS = "";
+			};
+			name = "Deployment - Fat";
+		};
+		A9E16451087DFBDE006BF7C2 /* Default */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+				ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+				HEADER_SEARCH_PATHS = "";
+			};
+			name = Default;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A9E1644B087DFBDE006BF7C2 /* Development */,
+				A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */,
+				A9E1644D087DFBDE006BF7C2 /* Default */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Default;
+		};
+		A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A9E1644F087DFBDE006BF7C2 /* Development */,
+				A9E16450087DFBDE006BF7C2 /* Deployment - Fat */,
+				A9E16451087DFBDE006BF7C2 /* Default */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Default;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}

+ 456 - 0
components/spotify/cspot/bell/external/alac/convert-utility/CAFFileALAC.cpp

@@ -0,0 +1,456 @@
+/*
+ Copyright © 2011 Apple  Inc. All rights reserved.
+ 
+ IMPORTANT:  This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms.  If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software.  Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple.  Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+//  CAFFileALAC.cpp
+//
+//  Copyright 2011 Apple Inc. All rights reserved.
+//
+
+#include <stdio.h>
+#include "CAFFileALAC.h"
+#include "EndianPortable.h"
+
+#define kSizeOfChanAtomPlusChannelLayout 24
+
+int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize)
+{
+    // returns the absolute position within the file
+    int32_t currentPosition = ftell(inputFile); // record the current position
+    uint8_t theReadBuffer[12];
+    uint32_t chunkType = 0, chunkSize = 0;
+    bool done = false;
+    int32_t bytesRead = 8;
+    
+    fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
+    while (!done && bytesRead > 0) // no file size here
+    {
+        bytesRead = fread(theReadBuffer, 1, 12, inputFile);
+        chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+        switch(chunkType)
+        {
+            case 'pakt':
+                *paktPos = ftell(inputFile) + kMinCAFFPacketTableHeaderSize;
+                // big endian size
+                *paktSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
+                done = true;
+                break;
+            default:
+                chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
+                fseek(inputFile, chunkSize, SEEK_CUR);
+                break;
+        }
+    }
+    
+    fseek(inputFile, currentPosition, SEEK_SET); // start at 0
+    
+    return 0;
+    
+}
+
+void WriteCAFFcaffChunk(FILE * outputFile)
+{
+    uint8_t theReadBuffer[8] = {'c', 'a', 'f', 'f', 0, 1, 0, 0};
+    
+    fwrite(theReadBuffer, 1, 8, outputFile);
+}
+
+void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
+{
+    port_CAFAudioDescription theDescription;
+    uint32_t tempFormatFlags = theOutputFormat.mFormatFlags;
+    uint8_t theReadBuffer[12] = {'d', 'e', 's', 'c', 0, 0, 0, 0, 0, 0, 0, 0}; 
+    
+    if (theOutputFormat.mFormatID == kALACFormatLinearPCM)
+    {
+        if (kALACFormatFlagsNativeEndian > 0) // kALACFormatFlagsNativeEndian is 2 on a big endian machine, 0 on little
+        {
+            tempFormatFlags = 0;
+        }
+        else
+        {
+            tempFormatFlags = k_port_CAFLinearPCMFormatFlagIsLittleEndian;
+        }
+    }
+    
+    theDescription.mSampleRate = SwapFloat64NtoB(theOutputFormat.mSampleRate);
+    theDescription.mFormatID = Swap32NtoB(theOutputFormat.mFormatID);
+    theDescription.mFormatFlags = Swap32NtoB(tempFormatFlags);
+    theDescription.mBytesPerPacket = Swap32NtoB(theOutputFormat.mBytesPerPacket);
+    theDescription.mFramesPerPacket = Swap32NtoB(theOutputFormat.mFramesPerPacket);
+    theDescription.mChannelsPerFrame = Swap32NtoB(theOutputFormat.mChannelsPerFrame);
+    theDescription.mBitsPerChannel = Swap32NtoB(theOutputFormat.mBitsPerChannel);
+    
+    theReadBuffer[11] = sizeof(port_CAFAudioDescription);
+    fwrite(theReadBuffer, 1, 12, outputFile);
+    fwrite(&theDescription, 1, sizeof(port_CAFAudioDescription), outputFile);
+}
+
+void WriteCAFFdataChunk(FILE * outputFile)
+{
+    uint8_t theReadBuffer[16] = {'d', 'a', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+    
+    fwrite(theReadBuffer, 1, 16, outputFile);
+}
+
+void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize)
+{
+    uint8_t thekukiHeaderBuffer[12] = {'k', 'u', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0}; 
+    
+    thekukiHeaderBuffer[11] = inCookieSize;
+    fwrite(thekukiHeaderBuffer, 1, 12, outputFile);
+    fwrite(inCookie, 1, inCookieSize, outputFile);
+}
+
+void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes)
+{
+    uint8_t theBuffer[8];
+    
+    theBuffer[0] = (numDataBytes >> 56) & 0xff;
+    theBuffer[1] = (numDataBytes >> 48) & 0xff;
+    theBuffer[2] = (numDataBytes >> 40) & 0xff;
+    theBuffer[3] = (numDataBytes >> 32) & 0xff;
+    theBuffer[4] = (numDataBytes >> 24) & 0xff;
+    theBuffer[5] = (numDataBytes >> 16) & 0xff;
+    theBuffer[6] = (numDataBytes >> 8) & 0xff;
+    theBuffer[7] = numDataBytes & 0xff;
+    fwrite(theBuffer, 1, 8, outputFile);
+}
+
+void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag)
+{
+    uint8_t theBuffer[24] = {'c', 'h', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};    
+    
+    theBuffer[11] = sizeof(ALACAudioChannelLayout);
+    theBuffer[12] = inChannelTag >> 24;
+    theBuffer[13] = (inChannelTag >> 16) & 0xff;
+    theBuffer[14] = (inChannelTag >> 8) & 0xff;
+    theBuffer[15] = inChannelTag & 0xff;
+    
+    fwrite(theBuffer, 1, 24, outputFile);
+}
+
+void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize)
+{
+    uint8_t theBuffer[12] = {'f', 'r', 'e', 'e', 0, 0, 0, 0, 0, 0, 0, 0};
+    uint32_t i = 0;
+    uint32_t theAdjustedSize = theSize - sizeof(port_CAFChunkHeader);
+    
+    if (theSize > theAdjustedSize) // cause we might have wrapped theAdjustedSize
+    {
+        theBuffer[8] = theAdjustedSize >> 24;
+        theBuffer[9] = (theAdjustedSize >> 16) & 0xff;
+        theBuffer[10] = (theAdjustedSize >> 8) & 0xff;
+        theBuffer[11] = theAdjustedSize & 0xff;
+        fwrite(theBuffer, 1, 12, outputFile);
+
+        for (i = 0; i < theAdjustedSize; ++i)
+        {
+            fwrite(&(theBuffer[4]), 1, 1, outputFile);
+        }
+    }
+}
+
+void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize)
+{
+    uint8_t theBuffer[12];
+    // Endian swap!
+    thePacketTableHeader->mNumberPackets = Swap64NtoB(thePacketTableHeader->mNumberPackets);
+    thePacketTableHeader->mNumberValidFrames = Swap64NtoB(thePacketTableHeader->mNumberValidFrames);
+    thePacketTableHeader->mPrimingFrames = Swap32NtoB(thePacketTableHeader->mPrimingFrames);
+    thePacketTableHeader->mRemainderFrames = Swap32NtoB(thePacketTableHeader->mRemainderFrames);
+    // write out the pakt chunk -- big endian!
+    theBuffer[0] = 'p';
+    theBuffer[1] = 'a';
+    theBuffer[2] = 'k';
+    theBuffer[3] = 't';
+    theBuffer[4] = 0;
+    theBuffer[5] = 0;
+    theBuffer[6] = 0;
+    theBuffer[7] = 0;
+    theBuffer[8] = thePacketTableSize >> 24;
+    theBuffer[9] = (thePacketTableSize >> 16) & 0xff;
+    theBuffer[10] = (thePacketTableSize >> 8) & 0xff;
+    theBuffer[11] = thePacketTableSize & 0xff;
+    fwrite(theBuffer, 1, 12, outputFile);
+    
+    fwrite(thePacketTableHeader, 1, kMinCAFFPacketTableHeaderSize, outputFile);
+}
+
+void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize)
+{
+    if ((theOriginalValue & 0x7f) == theOriginalValue)
+    {
+        *theBERSize = 1;
+        theBuffer[0] = theOriginalValue;
+    }
+    else if ((theOriginalValue & 0x3fff) == theOriginalValue)
+    {
+        *theBERSize = 2;
+        theBuffer[0] = theOriginalValue >> 7;
+        theBuffer[0] |= 0x80;
+        theBuffer[1] = theOriginalValue & 0x7f;
+    }
+    else if ((theOriginalValue & 0x1fffff) == theOriginalValue)
+    {
+        *theBERSize = 3;
+        theBuffer[0] = theOriginalValue >> 14;
+        theBuffer[0] |= 0x80;
+        theBuffer[1] = (theOriginalValue >> 7) & 0x7f;
+        theBuffer[1] |= 0x80;
+        theBuffer[2] = theOriginalValue & 0x7f;
+    }
+    else if ((theOriginalValue & 0x0fffffff) == theOriginalValue)
+    {
+        *theBERSize = 4;
+        theBuffer[0] = theOriginalValue >> 21;
+        theBuffer[0] |= 0x80;
+        theBuffer[1] = (theOriginalValue >> 14) & 0x7f;
+        theBuffer[1] |= 0x80;
+        theBuffer[2] = (theOriginalValue >> 7) & 0x7f;
+        theBuffer[2] |= 0x80;
+        theBuffer[3] = theOriginalValue & 0x7f;
+    }
+    else
+    {
+        *theBERSize = 5;
+        theBuffer[0] = theOriginalValue >> 28;
+        theBuffer[0] |= 0x80;
+        theBuffer[1] = (theOriginalValue >> 21) & 0x7f;
+        theBuffer[1] |= 0x80;
+        theBuffer[2] = (theOriginalValue >> 14) & 0x7f;
+        theBuffer[2] |= 0x80;
+        theBuffer[3] = (theOriginalValue >> 7) & 0x7f;
+        theBuffer[3] |= 0x80;
+        theBuffer[4] = theOriginalValue & 0x7f;
+    }
+}
+
+uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes)
+{
+	uint32_t theAnswer = 0;
+	uint8_t theData;
+	int32_t size = 0;
+    do
+	{
+		theData = theInputBuffer[size];
+		theAnswer = (theAnswer << 7) | (theData & 0x7F);
+		if (++size > 5)
+		{
+			size = 0xFFFFFFFF;
+			return 0;
+		}
+	}
+	while(((theData & 0x80) != 0) && (size <= *ioNumBytes));
+    
+    *ioNumBytes = size;
+	
+	return theAnswer;
+}
+
+int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * theMaxPacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader)
+{
+    int32_t theMaxPacketSize = 0, theByteSizeTableEntry = 0;
+    
+    // fill out the header
+    thePacketTableHeader->mNumberValidFrames = inputDataSize/((theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame);
+    thePacketTableHeader->mNumberPackets = thePacketTableHeader->mNumberValidFrames/kALACDefaultFramesPerPacket;
+    thePacketTableHeader->mPrimingFrames = 0;
+    thePacketTableHeader->mRemainderFrames = thePacketTableHeader->mNumberValidFrames - thePacketTableHeader->mNumberPackets * kALACDefaultFramesPerPacket;
+    thePacketTableHeader->mRemainderFrames = kALACDefaultFramesPerPacket - thePacketTableHeader->mRemainderFrames;
+    if (thePacketTableHeader->mRemainderFrames) thePacketTableHeader->mNumberPackets += 1;
+    
+    // Ok, we have to assume the worst case scenario for packet sizes
+    theMaxPacketSize = (theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame * kALACDefaultFramesPerPacket + kALACMaxEscapeHeaderBytes;
+    
+    if (theMaxPacketSize < 16384)
+    {
+        theByteSizeTableEntry = 2;
+    }
+    else
+    {
+        theByteSizeTableEntry = 3;
+    }
+    *theMaxPacketTableSize =  theByteSizeTableEntry * thePacketTableHeader->mNumberPackets;
+    
+    return 0;
+}
+
+uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile)
+{
+    // returns to the current absolute position within the file
+    int32_t currentPosition = ftell(inputFile); // record the current position
+    uint8_t theReadBuffer[sizeof(ALACSpecificConfig)];
+    uint32_t chunkType = 0, chunkSize = 0;
+    bool done = false;
+    int32_t bytesRead = sizeof(port_CAFFileHeader);
+    uint32_t theCookieSize = 0;
+    
+    fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
+    while (!done && bytesRead > 0) // no file size here
+    {
+        bytesRead = fread(theReadBuffer, 1, 12, inputFile);
+        chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+        switch(chunkType)
+        {                    
+            case 'kuki':
+            {
+                theCookieSize = theReadBuffer[11];
+                done = true;
+                break;
+            }
+            default:
+                chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
+                fseek(inputFile, chunkSize, SEEK_CUR);
+                break;
+        }
+    }
+    
+    fseek(inputFile, currentPosition, SEEK_SET); // start at 0
+    
+    if (!done) return -1;
+    
+    return theCookieSize;
+    
+}
+// gets the kuki chunk from a caff file
+int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize)
+{
+    // returns to the current absolute position within the file
+    int32_t currentPosition = ftell(inputFile); // record the current position
+    uint8_t theReadBuffer[12];
+    uint32_t chunkType = 0, chunkSize = 0;
+    bool done = false, cookieFound = false;
+    int32_t bytesRead = sizeof(port_CAFFileHeader);
+    uint32_t theStoredCookieSize = 0;
+    
+    fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
+    while (!done && bytesRead > 0) // no file size here
+    {
+        bytesRead = fread(theReadBuffer, 1, 12, inputFile);
+        chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+        switch(chunkType)
+        {                    
+            case 'kuki':
+            {
+                theStoredCookieSize = theReadBuffer[11];
+                if (*ioMagicCookieSize >= theStoredCookieSize)
+                {
+                    fread(outMagicCookie, 1, theStoredCookieSize, inputFile);
+                    *ioMagicCookieSize = theStoredCookieSize;
+                    cookieFound = true;
+                }
+                else
+                {
+                    *ioMagicCookieSize = 0;
+                }
+                done = true;
+                break;
+            }
+            default:
+                chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
+                fseek(inputFile, chunkSize, SEEK_CUR);
+                break;
+        }
+    }
+    
+    fseek(inputFile, currentPosition, SEEK_SET); // start at 0
+    
+    if (!done || !cookieFound) return -1;
+    
+    return 0;
+}
+
+bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize)
+{
+    bool done = false;
+    int32_t bytesRead = 8;
+    uint32_t chunkType = 0, chunkSize = 0;
+    uint8_t theBuffer[12];
+    
+    fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
+    while (!done && bytesRead > 0) // no file size here
+    {
+        bytesRead = fread(theBuffer, 1, 12, inputFile);
+        chunkType = ((int32_t)(theBuffer[0]) << 24) + ((int32_t)(theBuffer[1]) << 16) + ((int32_t)(theBuffer[2]) << 8) + theBuffer[3];
+        switch(chunkType)
+        {
+            case 'data':
+                *dataPos = ftell(inputFile) + sizeof(uint32_t); // skip the edits
+                // big endian size
+                *dataSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
+                *dataSize -= 4; // the edits are included in the size
+                done = true;
+                break;
+            default:
+                chunkSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
+                fseek(inputFile, chunkSize, SEEK_CUR);
+                break;
+        }
+    }
+    return done;
+}
+
+bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat)
+{
+    bool done = false;
+    uint32_t theChunkSize = 0, theChunkType = 0;
+    uint8_t theReadBuffer[32];
+    
+    fseek(inputFile, 4, SEEK_CUR); // skip 4 bytes
+
+    while (!done)
+    {
+        fread(theReadBuffer, 1, 4, inputFile);
+        theChunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+        switch (theChunkType)
+        {
+            case 'desc':
+                fseek(inputFile, 8, SEEK_CUR); // skip 8 bytes
+                fread(theReadBuffer, 1, sizeof(port_CAFAudioDescription), inputFile);
+                theInputFormat->mFormatID = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatID);
+                theInputFormat->mChannelsPerFrame = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mChannelsPerFrame);
+                theInputFormat->mSampleRate = SwapFloat64BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mSampleRate);
+                theInputFormat->mBitsPerChannel = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBitsPerChannel);
+                theInputFormat->mFormatFlags = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatFlags);
+                theInputFormat->mBytesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBytesPerPacket);
+                if (theInputFormat->mFormatID == kALACFormatAppleLossless)
+                {
+                    theInputFormat->mBytesPerFrame = 0;
+                }
+                else
+                {
+					theInputFormat->mBytesPerFrame = theInputFormat->mBytesPerPacket;
+					if ((theInputFormat->mFormatFlags & 0x02) == 0x02)
+					{
+						theInputFormat->mFormatFlags &= 0xfffffffc;
+					}
+					else
+					{
+						theInputFormat->mFormatFlags |= 0x02;
+					}
+
+                }
+                theInputFormat->mFramesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFramesPerPacket);
+                theInputFormat->mReserved = 0;
+                done = true;
+                break;
+            default:
+                // read the size and skip
+                fread(theReadBuffer, 1, 8, inputFile);
+                theChunkSize = ((int32_t)(theReadBuffer[4]) << 24) + ((int32_t)(theReadBuffer[5]) << 16) + ((int32_t)(theReadBuffer[6]) << 8) + theReadBuffer[7];
+                fseek(inputFile, theChunkSize, SEEK_CUR);
+                break;
+        }
+    }
+    return done;
+}

+ 209 - 0
components/spotify/cspot/bell/external/alac/convert-utility/CAFFileALAC.h

@@ -0,0 +1,209 @@
+/*
+ Copyright © 2011 Apple  Inc. All rights reserved.
+ 
+ IMPORTANT:  This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms.  If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software.  Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple.  Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+//  CAFFileALAC.h
+//  based CAFFile.h in the CoreAudio headers, ALAC specific
+//
+//  Copyright 2011 Apple Inc. All rights reserved.
+//
+
+#ifndef _CAFFilePortable_h
+#define _CAFFilePortable_h
+
+#if TARGET_OS_WIN32
+#define ATTRIBUTE_PACKED
+#pragma pack(push, 1)
+#else
+#define ATTRIBUTE_PACKED __attribute__((__packed__))
+#endif
+
+#include "ALACAudioTypes.h"
+
+#define kMinCAFFPacketTableHeaderSize 24
+
+typedef uint32_t CAFFChannelLayoutTag;
+// These are subset of the channel layout tags listed in CoreAudioTypes.h
+// ALAC and caff both use the same tag values
+enum
+{
+    kCAFFChannelLayoutTag_Mono          = (100<<16) | 1,    // C
+    kCAFFChannelLayoutTag_Stereo        = (101<<16) | 2,	// L R
+    kCAFFChannelLayoutTag_MPEG_3_0_B    = (113<<16) | 3,	// C L R
+    kCAFFChannelLayoutTag_MPEG_4_0_B    = (116<<16) | 4,	// C L R Cs
+    kCAFFChannelLayoutTag_MPEG_5_0_D    = (120<<16) | 5,    // C L R Ls Rs
+    kCAFFChannelLayoutTag_MPEG_5_1_D    = (124<<16) | 6,	// C L R Ls Rs LFE
+    kCAFFChannelLayoutTag_AAC_6_1       = (142<<16) | 7,	// C L R Ls Rs Cs LFE
+    kCAFFChannelLayoutTag_MPEG_7_1_B	= (127<<16) | 8     // C Lc Rc L R Ls Rs LFE
+};
+
+// ALAC currently only utilizes these channels layouts. CAFF supports all those listed in
+// CoreAudioTypes.h. 
+static const CAFFChannelLayoutTag	CAFFChannelLayoutTags[kALACMaxChannels] =
+{
+    kCAFFChannelLayoutTag_Mono,         // C
+    kCAFFChannelLayoutTag_Stereo,		// L R
+    kCAFFChannelLayoutTag_MPEG_3_0_B,	// C L R
+    kCAFFChannelLayoutTag_MPEG_4_0_B,	// C L R Cs
+    kCAFFChannelLayoutTag_MPEG_5_0_D,	// C L R Ls Rs
+    kCAFFChannelLayoutTag_MPEG_5_1_D,	// C L R Ls Rs LFE
+    kCAFFChannelLayoutTag_AAC_6_1,		// C L R Ls Rs Cs LFE
+    kCAFFChannelLayoutTag_MPEG_7_1_B	// C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+
+// In a CAF File all of these types' byte order is big endian.
+// When reading or writing these values the program will need to flip byte order to native endian
+
+// CAF File Header
+enum {
+	k_port__port_CAF_FileType				= 'caff',
+	k_port_CAF_FileVersion_Initial	= 1
+};
+
+// CAF Chunk Types	
+enum {
+	k_port_CAF_StreamDescriptionChunkID = 'desc',
+	k_port_CAF_AudioDataChunkID			= 'data',
+	k_port_CAF_ChannelLayoutChunkID		= 'chan',
+	k_port_CAF_MagicCookieID			= 'kuki',
+	k_port_CAF_PacketTableChunkID		= 'pakt',
+	k_port_CAF_FreeTableChunkID			= 'free'
+};
+
+
+struct port_CAFFileHeader
+{
+    uint32_t          mFileType;			// 'caff'
+    uint16_t			mFileVersion;		//initial revision set to 1
+    uint16_t			mFileFlags;			//initial revision set to 0
+} ATTRIBUTE_PACKED;
+typedef struct CAFFileHeader CAFFileHeader;
+
+
+struct port_CAFChunkHeader
+{
+    uint32_t          mChunkType; // four char code
+    int64_t          mChunkSize;  // size in bytes of the chunk data (not including this header).
+    // mChunkSize is int64_t not uint64_t because negative values for 
+    // the data size can have a special meaning
+} ATTRIBUTE_PACKED;
+
+typedef struct port_CAFChunkHeader port_CAFChunkHeader;
+
+// Every file MUST have this chunk. It MUST be the first chunk in the file
+struct port_CAFAudioDescription
+{
+    double mSampleRate;
+    uint32_t  mFormatID;
+    uint32_t  mFormatFlags;
+    uint32_t  mBytesPerPacket;
+    uint32_t  mFramesPerPacket;
+    uint32_t  mChannelsPerFrame;
+    uint32_t  mBitsPerChannel;
+} ATTRIBUTE_PACKED;
+typedef struct port_CAFAudioDescription  port_CAFAudioDescription;
+
+// these are the flags if the format ID is 'lpcm'
+// <CoreAudio/CoreAudioTypes.h> declares some of the format constants 
+// that can be used as Data Formats in a CAF file
+enum
+{
+    k_port_CAFLinearPCMFormatFlagIsFloat				= (1L << 0),
+    k_port_CAFLinearPCMFormatFlagIsLittleEndian		= (1L << 1)
+};
+
+
+// 'chan'  Optional chunk.
+// struct AudioChannelLayout  as defined in CoreAudioTypes.h.
+
+// 'free'
+// this is a padding chunk for reserving space in the file. content is meaningless.
+
+// 'kuki'
+// this is the magic cookie chunk. bag of bytes.
+
+// 'data'    Every file MUST have this chunk.
+// actual audio data can be any format as described by the 'asbd' chunk.
+
+// if mChunkSize is < 0 then this is the last chunk in the file and the actual length 
+// should be determined from the file size. 
+// The motivation for this is to allow writing the files without seeking to update size fields after every 
+// write in order to keep the file legal.
+// The program can put a -1 in the mChunkSize field and 
+// update it only once at the end of recording. 
+// If the program were to crash during recording then the file is still well defined.
+
+// 'pakt' Required if either/or mBytesPerPacket or mFramesPerPacket in the Format Description are zero
+// For formats that are packetized and have variable sized packets. 
+// The table is stored as an array of one or two variable length integers. 
+// (a) size in bytes of the data of a given packet.
+// (b) number of frames in a given packet.
+// These sizes are encoded as variable length integers
+
+// The packet description entries are either one or two values depending on the format.
+// There are three possibilities
+// (1)
+// If the format has variable bytes per packets (desc.mBytesPerPacket == 0) and constant frames per packet
+// (desc.mFramesPerPacket != 0) then the packet table contains single entries representing the bytes in a given packet
+// (2)
+// If the format is a constant bit rate (desc.mBytesPerPacket != 0) but variable frames per packet
+// (desc.mFramesPerPacket == 0) then the packet table entries contains single entries 
+// representing the number of frames in a given packet
+// (3)
+// If the format has variable frames per packet (asbd.mFramesPerPacket == 0) and variable bytes per packet
+// (desc.mBytesPerPacket == 0) then the packet table entries are a duple of two values. The first value
+// is the number of bytes in a given packet, the second value is the number of frames in a given packet
+
+struct port_CAFPacketTableHeader
+{
+    int64_t  mNumberPackets;
+    int64_t  mNumberValidFrames;
+    int32_t  mPrimingFrames;
+    int32_t  mRemainderFrames;
+    
+    uint8_t   mPacketDescriptions[1]; // this is a variable length array of mNumberPackets elements
+} ATTRIBUTE_PACKED;
+typedef struct port_CAFPacketTableHeader port_CAFPacketTableHeader;
+
+struct port_CAFDataChunk
+{
+    uint32_t mEditCount;
+    uint8_t mData[1]; // this is a variable length data field based off the size of the data chunk
+} ATTRIBUTE_PACKED;
+typedef struct port_CAFDataChunk port_CAFDataChunk;
+
+// prototypes
+int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize);
+void WriteCAFFcaffChunk(FILE * outputFile);
+void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
+void WriteCAFFdataChunk(FILE * outputFile);
+void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize);
+void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes);
+void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag);
+void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize);
+void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize);
+void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize);
+uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes);
+int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * thePacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader);
+uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile);
+int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize);
+bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize);
+bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat);
+
+#if TARGET_OS_WIN32
+#pragma pack(pop)
+#endif
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+#endif

+ 784 - 0
components/spotify/cspot/bell/external/alac/convert-utility/main.cpp

@@ -0,0 +1,784 @@
+/*
+ Copyright © 2011 Apple  Inc. All rights reserved.
+ 
+ IMPORTANT:  This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms.  If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software.  Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple.  Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * main.cpp
+ *
+ * Converts pcm data contained in a .wav or .caf file into Apple Lossless (ALAC) put into a .caf file
+ * or converts ALAC data from a .caf file into pcm data and put into a .wav or .caf file
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// these are headers for the ALAC encoder and decoder
+#include "ALACEncoder.h"
+#include "ALACDecoder.h"
+#include "ALACBitUtilities.h"
+
+// these are utility headers for this sample code
+#include "CAFFileALAC.h"
+#include "EndianPortable.h"
+
+#define kMaxBERSize 5
+#define kCAFFdataChunkEditsSize  4
+
+#define kWAVERIFFChunkSize 12
+#define kWAVEfmtChunkSize 24
+#define kWAVEdataChunkHeaderSize 8
+
+#define VERBOSE 0
+
+// Helper functions
+int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType);
+int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat);
+int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize);
+int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize);
+int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType);
+void GetOutputFileType(char * outputFileName, uint32_t * outputFileType);
+ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame);
+
+// Some crude WAVE writing tools
+void WriteWAVERIFFChunk(FILE * outputFile);
+void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
+void WriteWAVEdataChunk(FILE * outputFile);
+void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes);
+
+// Adapted from CoreAudioTypes.h
+enum
+{
+    kTestFormatFlag_16BitSourceData    = 1,
+    kTestFormatFlag_20BitSourceData    = 2,
+    kTestFormatFlag_24BitSourceData    = 3,
+    kTestFormatFlag_32BitSourceData    = 4
+};
+
+
+int32_t main (int32_t argc, char * argv[]) 
+{
+    char * inputFileName = argv[1];
+    char * outputFileName = argv[2];
+    FILE * inputFile = NULL;
+    FILE * outputFile = NULL;
+		
+	bool malformed = argc < 2;
+	
+    // Parse the commandline and open the necessary files
+    for (int32_t i = 1; i < argc; ++i) 
+	{
+		if (strcmp (argv[i], "-h") == 0)
+		{
+			malformed = true;
+		}
+		else
+		{
+			if (argv[i][0] == '-')
+            {
+				printf ("unknown option: %s\n", argv[i]);
+				malformed = true;
+			}
+			else
+			{
+                if (inputFile == NULL) inputFile = fopen (inputFileName, "rb"); // the b is necessary for Windows -- ignored by Unix
+                if(inputFile == NULL)
+                {
+                    fprintf(stderr," Cannot open file \"%s\"\n", inputFileName);
+                    exit (1);
+                }
+
+                if (outputFile == NULL) outputFile = fopen (outputFileName, "w+b"); // the b is necessary for Windows -- ignored by Unix
+                if(outputFile == NULL)
+                {
+                    fprintf(stderr," Cannot open file \"%s\"\n", outputFileName);
+                    exit (1);
+                }
+			}
+		}
+				
+		if (malformed)
+		{
+			break;
+		}
+	}
+	
+	if (!malformed) 
+	{
+        printf("Input file: %s\n", inputFileName);
+        printf("Output file: %s\n", outputFileName);
+        // So at this point we have the input and output files open. Need to determine what we're dealing with
+        int32_t theError = 0;
+        AudioFormatDescription inputFormat;
+        AudioFormatDescription outputFormat;
+        int32_t inputDataPos = 0, inputDataSize = 0;
+        uint32_t inputFileType = 0; // 'caff' or 'WAVE'
+        uint32_t outputFileType = 0; // 'caff' or 'WAVE'
+        
+        theError = GetInputFormat(inputFile, &inputFormat, &inputFileType);
+        if (theError)
+        {
+            fprintf(stderr," Cannot determine what format file \"%s\" is\n", inputFileName);
+            exit (1);            
+        }
+        
+        if (inputFileType != 'WAVE' && inputFileType != 'caff')
+        {
+            fprintf(stderr," File \"%s\" is of an unsupported type\n", outputFileName);
+            exit (1);                        
+        }
+        
+        if (inputFormat.mFormatID != kALACFormatAppleLossless && inputFormat.mFormatID != kALACFormatLinearPCM)
+        {
+            fprintf(stderr," File \"%s\'s\" data format is of an unsupported type\n", outputFileName);
+            exit (1);                        
+        }
+
+        SetOutputFormat(inputFormat, &outputFormat);
+
+        if (theError)
+        {
+            fprintf(stderr," Cannot determine what format file \"%s\" is\n", outputFileName);
+            exit (1);            
+        }
+        FindDataStart(inputFile, inputFileType, &inputDataPos, &inputDataSize);
+        fseek(inputFile, inputDataPos, SEEK_SET);
+        
+        // We know where we are and we know what we're doing
+        if (outputFormat.mFormatID == kALACFormatAppleLossless)
+        {
+            // encoding
+            EncodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize);
+        }
+        else
+        {
+            // decoding
+            GetOutputFileType(outputFileName, &outputFileType);
+            
+            if (outputFileType == 'WAVE' && outputFormat.mChannelsPerFrame > 2)
+            {
+                // we don't support WAVE because we don't want to reinterleave on output 
+                fprintf(stderr," Cannot decode more than two channels to WAVE\n");
+                exit (1);            
+            }
+            DecodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize, outputFileType);
+        }
+	}
+	
+	if (malformed) {
+		printf ("Usage:\n");
+		printf ("Encode:\n");
+		printf ("        alacconvert <input wav or caf file> <output caf file>\n");
+		printf ("Decode:\n");
+		printf ("        alacconvert <input caf file> <output wav or caf file>\n");
+		printf ("\n");
+		return 1;
+	}
+	
+    if (inputFile) fclose(inputFile);
+    if (outputFile) fclose(outputFile);
+    
+	return 0;
+}
+
+
+int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType)
+{
+    // assumes the file is open
+    uint8_t theReadBuffer[20];
+    bool done = false;
+    uint32_t chunkType = 0;
+
+    fread(theReadBuffer, 1, 4, inputFile);
+    
+    if (theReadBuffer[0] == 'c' && theReadBuffer[1] == 'a' && theReadBuffer[2] == 'f'  & theReadBuffer[3] == 'f')
+    {
+        // It's a caff file!
+        *theFileType = 'caff';
+        // We support pcm data for encode and alac data for decode
+        done = GetCAFFdescFormat(inputFile, theInputFormat);
+    }
+    else if (theReadBuffer[0] == 'R' && theReadBuffer[1] == 'I' && theReadBuffer[2] == 'F'  & theReadBuffer[3] == 'F')
+    {
+        fread(theReadBuffer, 1, 8, inputFile);
+        if (theReadBuffer[4] == 'W' && theReadBuffer[5] == 'A' && theReadBuffer[6] == 'V'  & theReadBuffer[7] == 'E')
+        {
+            // It's a WAVE file!
+            *theFileType = 'WAVE';
+            // We only support pcm data             
+            while (!done)
+            {
+                uint32_t theChunkSize = 0, theSampleRate = 0;
+                fread(theReadBuffer, 1, 4, inputFile);
+                chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+                switch (chunkType)
+                {
+                    case 'fmt ':
+                        fread(theReadBuffer, 1, 20, inputFile);
+                        // Remember campers we're in little endian land
+                        if (theReadBuffer[4] != 1 || theReadBuffer[5] != 0)
+                        {
+                            // we only support PCM
+                            *theFileType = 0; // clear it
+                            return -1;                        
+                        }
+                        theInputFormat->mFormatID = kALACFormatLinearPCM;
+                        theInputFormat->mChannelsPerFrame = theReadBuffer[6];
+                        theSampleRate = ((int32_t)(theReadBuffer[11]) << 24) + ((int32_t)(theReadBuffer[10]) << 16) + ((int32_t)(theReadBuffer[9]) << 8) + theReadBuffer[8];
+                        theInputFormat->mSampleRate = theSampleRate;
+                        theInputFormat->mBitsPerChannel = theReadBuffer[18];
+                        theInputFormat->mFormatFlags = kALACFormatFlagIsSignedInteger | kALACFormatFlagIsPacked; // always little endian
+                        theInputFormat->mBytesPerPacket = theInputFormat->mBytesPerFrame = (theInputFormat->mBitsPerChannel >> 3) * theInputFormat->mChannelsPerFrame;
+                        theInputFormat->mFramesPerPacket = 1;
+                        theInputFormat->mReserved = 0;
+                        done = true;
+                        break;
+                    default:
+                        // read the size and skip
+                        fread(theReadBuffer, 1, 4, inputFile);
+                        theChunkSize = ((int32_t)(theReadBuffer[3]) << 24) + ((int32_t)(theReadBuffer[2]) << 16) + ((int32_t)(theReadBuffer[1]) << 8) + theReadBuffer[0];
+                        fseek(inputFile, theChunkSize, SEEK_CUR);
+                        break;
+                }
+            }
+        }
+        else
+        {
+            *theFileType = 0; // clear it
+            return -1;
+        }
+    }
+    else
+    {
+        *theFileType = 0; // clear it
+        return -1;
+    }
+
+    if (!done) return -1;
+
+    return 0;
+}
+
+int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat)
+{
+    if (theInputFormat.mFormatID == kALACFormatLinearPCM)
+    {
+        // encoding
+        theOutputFormat->mFormatID = kALACFormatAppleLossless;
+        theOutputFormat->mSampleRate =  theInputFormat.mSampleRate;
+        
+        switch(theInputFormat.mBitsPerChannel)
+        {
+            case 16:
+                theOutputFormat->mFormatFlags = kTestFormatFlag_16BitSourceData;
+                break;
+            case 20:
+                theOutputFormat->mFormatFlags = kTestFormatFlag_20BitSourceData;
+                break;
+            case 24:
+                theOutputFormat->mFormatFlags = kTestFormatFlag_24BitSourceData;
+                break;
+            case 32:
+                theOutputFormat->mFormatFlags = kTestFormatFlag_32BitSourceData;
+                break;
+            default:
+                return -1;
+                break;
+        }
+        
+        theOutputFormat->mFramesPerPacket = kALACDefaultFramesPerPacket;
+        theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
+        // mBytesPerPacket == 0 because we are VBR
+        // mBytesPerFrame and mBitsPerChannel == 0 because there are no discernable bits assigned to a particular sample
+        // mReserved is always 0
+        theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel = theOutputFormat->mReserved = 0;
+    }
+    else
+    {
+        // decoding
+        theOutputFormat->mFormatID = kALACFormatLinearPCM;
+        theOutputFormat->mSampleRate =  theInputFormat.mSampleRate;
+        
+        switch(theInputFormat.mFormatFlags)
+        {
+            case kTestFormatFlag_16BitSourceData:
+                theOutputFormat->mBitsPerChannel = 16;
+                break;
+            case kTestFormatFlag_20BitSourceData:
+                theOutputFormat->mBitsPerChannel = 20;
+                break;
+            case kTestFormatFlag_24BitSourceData:
+                theOutputFormat->mBitsPerChannel = 24;
+                break;
+            case kTestFormatFlag_32BitSourceData:
+                theOutputFormat->mBitsPerChannel = 32;
+                break;
+            default:
+                return -1;
+                break;
+        }
+        
+        theOutputFormat->mFramesPerPacket = 1;
+        theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
+        theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel != 20 ? theInputFormat.mChannelsPerFrame * ((theOutputFormat->mBitsPerChannel) >> 3) : (int32_t)(theInputFormat.mChannelsPerFrame * 2.5 + .5);
+        theOutputFormat->mFormatFlags = kALACFormatFlagsNativeEndian;
+        theOutputFormat->mReserved = 0;
+    }
+    return 0;
+}
+
+int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize)
+{
+    // returns the absolute position within the file
+    int32_t currentPosition = ftell(inputFile); // record the current position
+    uint8_t theReadBuffer[12];
+    uint32_t chunkType = 0, fileSize = 0, chunkSize = 0;
+    bool done = false;
+    
+    switch (inputFileType)
+    {
+        case 'WAVE':
+            fseek(inputFile, 0, SEEK_SET); // start at 0
+            fread(theReadBuffer, 1, 8, inputFile);
+            fileSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
+            fseek(inputFile, 12, SEEK_SET); // start at 12!
+            while (!done && ((uint32_t)(ftell(inputFile)) < fileSize))
+            {
+                fread(theReadBuffer, 1, 8, inputFile);
+                chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
+                switch(chunkType)
+                {
+                    case 'data':
+                        *dataPos = ftell(inputFile);
+                        // little endian size
+                        *dataSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
+                        done = true;
+                        break;
+                    default:
+                        chunkSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
+                        fseek(inputFile, chunkSize, SEEK_CUR);
+                        break;
+                }
+            }
+            break;
+        case 'caff':
+            done = FindCAFFDataStart(inputFile, dataPos, dataSize);
+            break;
+    }
+    
+    fseek(inputFile, currentPosition, SEEK_SET); // start at 0
+
+    if (!done) return -1;
+
+    return 0;
+}
+
+int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize)
+{
+    int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theInputFormat.mBitsPerChannel >> 3) * theOutputFormat.mFramesPerPacket;
+    int32_t theOutputPacketBytes = theInputPacketBytes + kALACMaxEscapeHeaderBytes;
+    int32_t thePacketTableSize = 0, packetTablePos = 0, dataPos = 0, dataSizePos = 0, theBERSize = 0, packetTableSizePos;
+    uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
+    uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
+    int32_t numBytes = 0;
+    uint32_t packetTableBytesLeft = 0;
+    int64_t numDataBytes = 0;
+    port_CAFPacketTableHeader thePacketTableHeader;
+    int32_t inputDataBytesRemaining = inputDataSize;
+    uint8_t * theMagicCookie = NULL;
+    uint32_t theMagicCookieSize = 0;
+    
+    ALACEncoder * theEncoder = new ALACEncoder;
+    
+    theEncoder->SetFrameSize(theOutputFormat.mFramesPerPacket);
+    theEncoder->InitializeEncoder(theOutputFormat);
+    
+    // we only write out the caff header, the 'desc' chunk. the 'kuki' chunk, the 'pakt' chunk and the 'data' chunk
+    // write out the caff header
+    WriteCAFFcaffChunk(outputFile);
+    
+    // write out the desc chunk
+    WriteCAFFdescChunk(outputFile, theOutputFormat);
+
+    // get the magic cookie
+    theMagicCookieSize = theEncoder->GetMagicCookieSize(theOutputFormat.mChannelsPerFrame);
+    theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
+    theEncoder->GetMagicCookie(theMagicCookie, &theMagicCookieSize);
+    
+    // write out the kuki chunk
+    WriteCAFFkukiChunk(outputFile, theMagicCookie, theMagicCookieSize);
+    free(theMagicCookie);
+    
+    // We might be multi channel
+    if (theOutputFormat.mChannelsPerFrame > 2)
+    {
+        WriteCAFFchanChunk(outputFile, GetALACChannelLayoutTag(theOutputFormat.mChannelsPerFrame));
+    }
+    
+    // Figure out the maximum size and build the base pakt header
+    BuildBasePacketTable(theInputFormat, inputDataSize, &thePacketTableSize, &thePacketTableHeader);
+    packetTableBytesLeft = thePacketTableSize;
+    
+    // This could be substantially larger than either the read or write buffer, so allocate a block of memory here
+    // all we're going to do is copy it to the file
+    uint8_t * thePacketTableEntries = (uint8_t *)calloc (thePacketTableSize, 1);
+    
+    /* move */
+    thePacketTableSize += kMinCAFFPacketTableHeaderSize;
+    
+    WriteCAFFpaktChunkHeader(outputFile, &thePacketTableHeader, thePacketTableSize);
+    
+    packetTableSizePos = packetTablePos = ftell(outputFile);
+    packetTableSizePos -= (sizeof(int64_t) + kMinCAFFPacketTableHeaderSize);
+    
+    thePacketTableSize -= kMinCAFFPacketTableHeaderSize;    
+    fwrite (thePacketTableEntries, 1, thePacketTableSize, outputFile);
+    free(thePacketTableEntries);
+    
+    // We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
+    dataSizePos = ftell(outputFile) + sizeof(uint32_t);
+
+    // Finally, write out the data chunk
+    WriteCAFFdataChunk(outputFile);
+    
+    dataPos = ftell(outputFile);
+
+    while (theInputPacketBytes <= inputDataBytesRemaining)
+    {
+        numBytes = fread(theReadBuffer, 1, theInputPacketBytes, inputFile);
+#if VERBOSE
+        printf ("Read %i bytes\n", numBytes);
+#endif
+        inputDataBytesRemaining -= numBytes;
+		if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
+		{
+#if VERBOSE
+			printf ("Byte Swapping!\n");
+#endif
+			if (theInputFormat.mBitsPerChannel == 16)
+			{
+				uint16_t * theShort = (uint16_t *)theReadBuffer;
+				for (int32_t i = 0; i < (numBytes >> 1); ++i)
+				{
+					Swap16(&(theShort[i]));
+				}
+			}
+			else if (theInputFormat.mBitsPerChannel == 32)
+			{
+				uint32_t * theLong = (uint32_t *)theReadBuffer;
+				for (int32_t i = 0; i < (numBytes >> 2); ++i)
+				{
+					Swap32(&(theLong[i]));
+				}
+			}
+			else // covers both 20 and 24
+			{
+				for (int32_t i = 0; i < numBytes; i += 3)
+				{
+					Swap24(&(theReadBuffer[i]));
+				}
+			}
+ 		}
+        theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
+        
+        GetBERInteger(numBytes, theReadBuffer, &theBERSize);
+        fseek(outputFile, packetTablePos, SEEK_SET);
+        fwrite(theReadBuffer, 1, theBERSize, outputFile);       
+        packetTablePos += theBERSize;
+        packetTableBytesLeft -= theBERSize;
+        
+        fseek(outputFile, dataPos, SEEK_SET);
+        fwrite(theWriteBuffer, 1, numBytes, outputFile);
+        dataPos += numBytes;
+        numDataBytes += numBytes;
+#if VERBOSE
+        printf ("Writing %i bytes\n", numBytes);
+#endif
+    }
+    // encode the last partial packet
+    if (inputDataBytesRemaining)
+    {
+        numBytes = fread(theReadBuffer, 1, inputDataBytesRemaining, inputFile);
+#if VERBOSE
+        printf ("Last Packet! Read %i bytes\n", numBytes);
+#endif
+        inputDataBytesRemaining -= numBytes;
+		if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
+		{
+#if VERBOSE
+			printf ("Byte Swapping!\n");
+#endif
+			if (theInputFormat.mBitsPerChannel == 16)
+			{
+				uint16_t * theShort = (uint16_t *)theReadBuffer;
+				for (int32_t i = 0; i < (numBytes >> 1); ++i)
+				{
+					Swap16(&(theShort[i]));
+				}
+			}
+			else if (theInputFormat.mBitsPerChannel == 32)
+			{
+				uint32_t * theLong = (uint32_t *)theReadBuffer;
+				for (int32_t i = 0; i < (numBytes >> 2); ++i)
+				{
+					Swap32(&(theLong[i]));
+				}
+			}
+			else // covers both 20 and 24
+			{
+				for (int32_t i = 0; i < numBytes; i += 3)
+				{
+					Swap24(&(theReadBuffer[i]));
+				}
+			}
+ 		}
+        theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
+        
+        GetBERInteger(numBytes, theReadBuffer, &theBERSize);
+        fseek(outputFile, packetTablePos, SEEK_SET);
+        fwrite(theReadBuffer, 1, theBERSize, outputFile);       
+        packetTablePos += theBERSize;
+        packetTableBytesLeft -= theBERSize;
+        
+        fseek(outputFile, dataPos, SEEK_SET);
+        fwrite(theWriteBuffer, 1, numBytes, outputFile);
+        dataPos += numBytes;
+        numDataBytes += numBytes;
+#if VERBOSE
+        printf ("Writing %i bytes\n", numBytes);
+#endif
+    }
+
+    // cleanup -- if we have a lot of bytes left over in packet table, write a free chunk
+    if (packetTableBytesLeft > sizeof(port_CAFChunkHeader)) // min size required to write
+    {
+#if VERBOSE
+        printf ("Writing %i free bytes\n", packetTableBytesLeft);
+#endif
+        fseek(outputFile, packetTablePos, SEEK_SET);
+        WriteCAFFfreeChunk(outputFile, packetTableBytesLeft);
+        fseek(outputFile, packetTableSizePos, SEEK_SET);
+        WriteCAFFChunkSize(outputFile, thePacketTableSize - packetTableBytesLeft + kMinCAFFPacketTableHeaderSize);
+    }
+    // write out the data size
+    fseek(outputFile, dataSizePos, SEEK_SET);
+    numDataBytes += kCAFFdataChunkEditsSize;
+#if VERBOSE
+    printf ("numDataBytes == %i bytes\n", numDataBytes);
+#endif    
+    WriteCAFFChunkSize(outputFile, numDataBytes);
+
+    delete theEncoder;
+    
+    free(theReadBuffer);
+    free(theWriteBuffer);
+    
+    return 0;
+}
+
+// There's not a whole lot of difference between encode and decode on this level
+int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType)
+{
+    int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theOutputFormat.mBitsPerChannel >> 3) * theInputFormat.mFramesPerPacket + kALACMaxEscapeHeaderBytes;
+    int32_t theOutputPacketBytes = theInputPacketBytes - kALACMaxEscapeHeaderBytes;
+    int32_t thePacketTableSize = 0, packetTablePos = 0, outputDataSizePos = 0, inputDataPos = 0;
+    uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
+    uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
+    int32_t numBytes = 0;
+    int64_t numDataBytes = 0;
+    uint32_t numFrames = 0;
+    BitBuffer theInputBuffer;
+    uint8_t * theMagicCookie = NULL;
+    uint32_t theMagicCookieSize = 0;
+    
+    ALACDecoder * theDecoder = new ALACDecoder;
+    
+    // We need to get the cookie from the file
+    theMagicCookieSize = GetMagicCookieSizeFromCAFFkuki(inputFile);
+    theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
+    GetMagicCookieFromCAFFkuki(inputFile, theMagicCookie, &theMagicCookieSize);
+    
+    // While we don't have a use for this here, if you were using arbitrary channel layouts, you'd need to run the following check:
+    
+    theDecoder->Init(theMagicCookie, theMagicCookieSize);
+    free(theMagicCookie);
+    
+    BitBufferInit(&theInputBuffer, theReadBuffer, theInputPacketBytes);
+    inputDataPos = ftell(inputFile);
+    
+    if (outputFileType != 'WAVE')
+    {
+        // we only write out the caff header, the 'desc' chunk and the 'data' chunk
+        // write out the caff header
+        WriteCAFFcaffChunk(outputFile);
+        
+        // write out the desc chunk
+        WriteCAFFdescChunk(outputFile, theOutputFormat);
+        
+        // We might be multi channel
+        if (theOutputFormat.mChannelsPerFrame > 2)
+        {
+            // we are not rearranging the output data
+            WriteCAFFchanChunk(outputFile, CAFFChannelLayoutTags[theOutputFormat.mChannelsPerFrame - 1]);
+        }
+        
+        // We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
+        outputDataSizePos = ftell(outputFile) + sizeof(uint32_t);
+        
+        // Finally, write out the data chunk
+        WriteCAFFdataChunk(outputFile);
+    }
+    else
+    {
+        // We're writing a mono or stereo WAVE file
+        WriteWAVERIFFChunk(outputFile);
+        WriteWAVEfmtChunk(outputFile, theOutputFormat);
+        WriteWAVEdataChunk(outputFile);
+        outputDataSizePos = ftell(outputFile) - sizeof(uint32_t);
+    }
+
+    // We do have to get the packet size from the packet table
+    FindCAFFPacketTableStart(inputFile, &packetTablePos, &thePacketTableSize);
+    
+    fseek(inputFile, packetTablePos, SEEK_SET);
+    numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
+    
+    theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
+    packetTablePos += numBytes;
+    fseek(inputFile, inputDataPos, SEEK_SET);
+    inputDataPos += theInputPacketBytes;
+    
+    while ((theInputPacketBytes > 0) && ((size_t)theInputPacketBytes == fread(theReadBuffer, 1, theInputPacketBytes, inputFile)))
+    {
+#if VERBOSE
+        printf ("Read %i bytes\n", theInputPacketBytes);
+#endif
+        theDecoder->Decode(&theInputBuffer, theWriteBuffer, theInputFormat.mFramesPerPacket, theInputFormat.mChannelsPerFrame, &numFrames);
+        numBytes = numFrames * theOutputFormat.mBytesPerFrame;
+#if VERBOSE        
+        printf ("Writing %i bytes\n", numBytes);
+#endif
+        fwrite(theWriteBuffer, 1, numBytes, outputFile);
+        numDataBytes += numBytes;
+        fseek(inputFile, packetTablePos, SEEK_SET);
+        numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
+        
+        theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
+#if VERBOSE
+        printf ("theInputPacketBytes == %i bytes\n", theInputPacketBytes);
+#endif
+        packetTablePos += numBytes;
+        fseek(inputFile, inputDataPos, SEEK_SET);
+        inputDataPos += theInputPacketBytes;
+        BitBufferReset(&theInputBuffer);
+    }
+    if (outputFileType != 'WAVE')
+    {
+        // cleanup -- write out the data size
+        fseek(outputFile, outputDataSizePos, SEEK_SET);
+        numDataBytes += kCAFFdataChunkEditsSize; // add in the edit bytes
+#if VERBOSE
+        printf ("numDataBytes == %i bytes\n", numDataBytes);
+#endif
+        WriteCAFFChunkSize(outputFile, numDataBytes);
+    }
+    else
+    {
+        // cleanup -- write out the data size
+        fseek(outputFile, outputDataSizePos, SEEK_SET);
+        WriteWAVEChunkSize(outputFile, (uint32_t)numDataBytes);
+        // write out the file size
+        fseek(outputFile, 4, SEEK_SET);
+        WriteWAVEChunkSize(outputFile, numDataBytes + sizeof(outputFileType) + kWAVEdataChunkHeaderSize + kWAVEfmtChunkSize); // add in the size for 'WAVE', size of the data' chunk header and the 'fmt ' chunk
+    }
+
+    delete theDecoder;
+    
+    free(theReadBuffer);
+    free(theWriteBuffer);
+
+    return 0;
+}
+
+void GetOutputFileType(char * outputFileName, uint32_t * outputFileType)
+{
+    char * typeStr = strrchr(outputFileName, '.');
+    
+    *outputFileType = 'caff';
+
+    if (typeStr != NULL)
+    {
+        if (strlen(typeStr) == 4)
+        {
+            if (strcmp(typeStr, ".wav") == 0)
+            {
+                *outputFileType = 'WAVE';
+            }
+        }
+    }
+}
+
+ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame)
+{
+    return ALACChannelLayoutTags[inChannelsPerFrame - 1];
+}
+
+void WriteWAVERIFFChunk(FILE * outputFile)
+{
+    uint8_t theReadBuffer[kWAVERIFFChunkSize] = {'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'A', 'V', 'E'};
+    
+    fwrite(theReadBuffer, 1, kWAVERIFFChunkSize, outputFile);
+}
+
+void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
+{
+    // we use a standard 'fmt ' chunk for our pcm data where 16 is the chunk size and 1 is the compression code
+    uint8_t theBuffer[kWAVEfmtChunkSize] = {'f', 'm', 't', ' ', 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
+    uint32_t theSampleRate = theOutputFormat.mSampleRate;
+    uint32_t theAverageBytesPerSecond = theSampleRate * theOutputFormat.mBytesPerFrame;
+    
+    theBuffer[10] = theOutputFormat.mChannelsPerFrame;
+    
+    theBuffer[12] = theSampleRate & 0xff;
+    theBuffer[13] = (theSampleRate >> 8) & 0xff;
+    theBuffer[14] = (theSampleRate >> 16) & 0xff;
+    theBuffer[15] = theSampleRate >> 24;
+
+    theBuffer[16] = theAverageBytesPerSecond & 0xff;
+    theBuffer[17] = (theAverageBytesPerSecond >> 8) & 0xff;
+    theBuffer[18] = (theAverageBytesPerSecond >> 16) & 0xff;
+    theBuffer[19] = theAverageBytesPerSecond >> 24;
+
+    theBuffer[20] = theOutputFormat.mBytesPerFrame; 
+
+    theBuffer[22] = theOutputFormat.mBitsPerChannel; 
+
+    fwrite(theBuffer, 1, kWAVEfmtChunkSize, outputFile);    
+}
+
+void WriteWAVEdataChunk(FILE * outputFile)
+{
+    uint8_t theBuffer[kWAVEdataChunkHeaderSize] = {'d', 'a', 't', 'a', 0, 0, 0, 0};
+    
+    fwrite(theBuffer, 1, kWAVEdataChunkHeaderSize, outputFile);
+}
+
+void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes)
+{
+    uint8_t theBuffer[4];
+    
+    theBuffer[0] = numDataBytes & 0xff;
+    theBuffer[1] = (numDataBytes >> 8) & 0xff;
+    theBuffer[2] = (numDataBytes >> 16) & 0xff;
+    theBuffer[3] = (numDataBytes >> 24) & 0xff;
+    fwrite(theBuffer, 1, 4, outputFile);
+}

+ 202 - 0
components/spotify/cspot/bell/external/alac/targets/include/ALACAudioTypes.h

@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACAudioTypes.h
+*/
+
+#ifndef ALACAUDIOTYPES_H
+#define ALACAUDIOTYPES_H
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+    #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+    #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+    #pragma pack(2)
+#endif
+
+#include <stdint.h>
+
+#if defined(__ppc__)
+#define TARGET_RT_BIG_ENDIAN 1
+#elif defined(__ppc64__)
+#define TARGET_RT_BIG_ENDIAN 1
+#endif
+
+#define kChannelAtomSize 12
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmultichar"
+    
+enum 
+{
+    kALAC_UnimplementedError   = -4,
+    kALAC_FileNotFoundError    = -43,
+    kALAC_ParamError           = -50,
+    kALAC_MemFullError         = -108
+};
+
+enum
+{
+    kALACFormatAppleLossless = 'alac',
+    kALACFormatLinearPCM = 'lpcm'
+};
+
+enum
+{
+    kALACMaxChannels	= 8,
+    kALACMaxEscapeHeaderBytes = 8,
+    kALACMaxSearches	= 16,
+    kALACMaxCoefs		= 16,
+    kALACDefaultFramesPerPacket = 4096
+};
+
+typedef uint32_t ALACChannelLayoutTag;
+
+enum
+{
+    kALACFormatFlagIsFloat                     = (1 << 0),     // 0x1
+    kALACFormatFlagIsBigEndian                 = (1 << 1),     // 0x2
+    kALACFormatFlagIsSignedInteger             = (1 << 2),     // 0x4
+    kALACFormatFlagIsPacked                    = (1 << 3),     // 0x8
+    kALACFormatFlagIsAlignedHigh               = (1 << 4),     // 0x10
+};
+
+enum
+{
+#if TARGET_RT_BIG_ENDIAN
+    kALACFormatFlagsNativeEndian       = kALACFormatFlagIsBigEndian
+#else
+    kALACFormatFlagsNativeEndian       = 0
+#endif
+};
+
+// this is required to be an IEEE 64bit float
+typedef double alac_float64_t;
+
+// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
+enum
+{
+    kALACChannelLayoutTag_Mono          = (100<<16) | 1,    // C
+    kALACChannelLayoutTag_Stereo        = (101<<16) | 2,	// L R
+    kALACChannelLayoutTag_MPEG_3_0_B    = (113<<16) | 3,	// C L R
+    kALACChannelLayoutTag_MPEG_4_0_B    = (116<<16) | 4,	// C L R Cs
+    kALACChannelLayoutTag_MPEG_5_0_D    = (120<<16) | 5,    // C L R Ls Rs
+    kALACChannelLayoutTag_MPEG_5_1_D    = (124<<16) | 6,	// C L R Ls Rs LFE
+    kALACChannelLayoutTag_AAC_6_1       = (142<<16) | 7,	// C L R Ls Rs Cs LFE
+    kALACChannelLayoutTag_MPEG_7_1_B	= (127<<16) | 8     // C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
+// given number of channels and one of these layout tags
+static const ALACChannelLayoutTag	ALACChannelLayoutTags[kALACMaxChannels] =
+{
+    kALACChannelLayoutTag_Mono,         // C
+    kALACChannelLayoutTag_Stereo,		// L R
+    kALACChannelLayoutTag_MPEG_3_0_B,	// C L R
+    kALACChannelLayoutTag_MPEG_4_0_B,	// C L R Cs
+    kALACChannelLayoutTag_MPEG_5_0_D,	// C L R Ls Rs
+    kALACChannelLayoutTag_MPEG_5_1_D,	// C L R Ls Rs LFE
+    kALACChannelLayoutTag_AAC_6_1,		// C L R Ls Rs Cs LFE
+    kALACChannelLayoutTag_MPEG_7_1_B	// C Lc Rc L R Ls Rs LFE    (doc: IS-13818-7 MPEG2-AAC)
+};
+
+// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
+struct ALACAudioChannelLayout
+{
+    ALACChannelLayoutTag          mChannelLayoutTag;
+    uint32_t                      mChannelBitmap;
+    uint32_t                      mNumberChannelDescriptions;
+};
+typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
+
+struct AudioFormatDescription
+{
+    alac_float64_t mSampleRate;
+    uint32_t  mFormatID;
+    uint32_t  mFormatFlags;
+    uint32_t  mBytesPerPacket;
+    uint32_t  mFramesPerPacket;
+    uint32_t  mBytesPerFrame;
+    uint32_t  mChannelsPerFrame;
+    uint32_t  mBitsPerChannel;
+    uint32_t  mReserved;
+};
+typedef struct AudioFormatDescription  AudioFormatDescription;
+
+/* Lossless Definitions */
+
+enum
+{
+	kALACCodecFormat		= 'alac',
+	kALACVersion			= 0,
+	kALACCompatibleVersion	= kALACVersion,
+	kALACDefaultFrameSize	= 4096
+};
+
+// note: this struct is wrapped in an 'alac' atom in the sample description extension area
+// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
+typedef struct ALACSpecificConfig
+{
+	uint32_t				frameLength;
+	uint8_t					compatibleVersion;
+	uint8_t					bitDepth;							// max 32
+	uint8_t					pb;									// 0 <= pb <= 255
+	uint8_t					mb;
+	uint8_t					kb;
+	uint8_t					numChannels;
+	uint16_t				maxRun;
+	uint32_t				maxFrameBytes;
+	uint32_t				avgBitRate;
+	uint32_t				sampleRate;
+
+} ALACSpecificConfig;
+
+
+// The AudioChannelLayout atom type is not exposed yet so define it here
+enum
+{
+	AudioChannelLayoutAID = 'chan'
+};
+
+#pragma GCC diagnostic pop
+
+#if PRAGMA_STRUCT_ALIGN
+    #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+    #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+    #pragma pack()
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ALACAUDIOTYPES_H */

+ 65 - 0
components/spotify/cspot/bell/external/alac/targets/include/ALACDecoder.h

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACDecoder.h
+*/
+
+#ifndef _ALACDECODER_H
+#define _ALACDECODER_H
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#include <stdint.h>
+
+#include "ALACAudioTypes.h"
+
+struct BitBuffer;
+
+class ALACDecoder
+{
+	public:
+		ALACDecoder();
+		~ALACDecoder();
+
+		int32_t	Init( void * inMagicCookie, uint32_t inMagicCookieSize );
+		int32_t	Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
+
+	public:
+		// decoding parameters (public for use in the analyzer)
+		ALACSpecificConfig		mConfig;
+
+	protected:
+		int32_t	FillElement( struct BitBuffer * bits );
+		int32_t	DataStreamElement( struct BitBuffer * bits );
+
+		uint16_t					mActiveElements;
+
+		// decoding buffers
+		int32_t *				mMixBufferU;
+		int32_t *				mMixBufferV;
+		int32_t *				mPredictor;
+		uint16_t *				mShiftBuffer;	// note: this points to mPredictor's memory but different
+												//		 variable for clarity and type difference
+};
+
+#endif	/* _ALACDECODER_H */

+ 92 - 0
components/spotify/cspot/bell/external/alac/targets/include/ALACEncoder.h

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+	File:		ALACEncoder.h
+*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include "ALACAudioTypes.h"
+
+
+struct BitBuffer;
+
+class ALACEncoder
+{
+	public:
+		ALACEncoder();
+		virtual ~ALACEncoder();
+
+		virtual int32_t	Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
+                                   unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
+		virtual int32_t	Finish( );
+
+		void				SetFastMode( bool fast ) { mFastMode = fast; };
+
+		// this must be called *before* InitializeEncoder()
+		void				SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
+
+		void				GetConfig( ALACSpecificConfig & config );
+        uint32_t            GetMagicCookieSize(uint32_t inNumChannels);
+        void				GetMagicCookie( void * config, uint32_t * ioSize ); 
+
+        virtual int32_t	InitializeEncoder(AudioFormatDescription theOutputFormat);
+
+    protected:
+		virtual void		GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
+		
+		int32_t			EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+		int32_t			EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+		int32_t			EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
+		int32_t			EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
+
+
+		// ALAC encoder parameters
+		int16_t					mBitDepth;
+		bool					mFastMode;
+
+		// encoding state
+		int16_t					mLastMixRes[kALACMaxChannels];
+
+		// encoding buffers
+		int32_t *				mMixBufferU;
+		int32_t *				mMixBufferV;
+		int32_t *				mPredictorU;
+		int32_t *				mPredictorV;
+		uint16_t *				mShiftBufferUV;
+		
+		uint8_t *					mWorkBuffer;
+
+		// per-channel coefficients buffers
+		int16_t					mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
+		int16_t					mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
+
+		// encoding statistics
+		uint32_t					mTotalBytesGenerated;
+		uint32_t					mAvgBitRate;
+		uint32_t					mMaxFrameBytes;
+        uint32_t                  mFrameSize;
+        uint32_t                  mMaxOutputBytes;
+        uint32_t                  mNumChannels;
+        uint32_t                  mOutputSampleRate;		
+};

BIN
components/spotify/cspot/bell/external/alac/targets/win32/x64/alac.lib


BIN
components/spotify/cspot/bell/external/alac/targets/win32/x86/alac.lib


+ 0 - 0
components/spotify/cspot/bell/cJSON/.editorconfig → components/spotify/cspot/bell/external/cJSON/.editorconfig


+ 0 - 0
components/spotify/cspot/bell/cJSON/.gitattributes → components/spotify/cspot/bell/external/cJSON/.gitattributes


+ 0 - 0
components/spotify/cspot/bell/cJSON/.github/CONTRIBUTING.md → components/spotify/cspot/bell/external/cJSON/.github/CONTRIBUTING.md


+ 0 - 0
components/spotify/cspot/bell/cJSON/.github/workflows/CI.yml → components/spotify/cspot/bell/external/cJSON/.github/workflows/CI.yml


+ 0 - 0
components/spotify/cspot/bell/cJSON/.gitignore → components/spotify/cspot/bell/external/cJSON/.gitignore


+ 0 - 0
components/spotify/cspot/bell/cJSON/.travis.yml → components/spotify/cspot/bell/external/cJSON/.travis.yml


+ 0 - 0
components/spotify/cspot/bell/cJSON/CHANGELOG.md → components/spotify/cspot/bell/external/cJSON/CHANGELOG.md


+ 10 - 23
components/spotify/cspot/bell/cJSON/CMakeLists.txt → components/spotify/cspot/bell/external/cJSON/CMakeLists.txt

@@ -121,7 +121,6 @@ set(SOURCES cJSON.c)
 option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
 option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
 option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
-option(ENABLE_CJSON_VERSION_SO "Enables cJSON so version" ON)
 
 if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
     set(CJSON_LIBRARY_TYPE SHARED)
@@ -156,23 +155,17 @@ install(TARGETS "${CJSON_LIB}"
     INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
 )
 if (BUILD_SHARED_AND_STATIC_LIBS)
-    install(TARGETS "${CJSON_LIB}-static"
-    EXPORT "${CJSON_LIB}" 
-    ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
-    INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
-)
+    install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
 endif()
 if(ENABLE_TARGET_EXPORT)
     # export library information for CMake projects
     install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
 endif()
 
-if(ENABLE_CJSON_VERSION_SO)
-    set_target_properties("${CJSON_LIB}"
-        PROPERTIES
-            SOVERSION "${CJSON_VERSION_SO}"
-            VERSION "${PROJECT_VERSION}")
-endif()
+set_target_properties("${CJSON_LIB}"
+    PROPERTIES
+        SOVERSION "${CJSON_VERSION_SO}"
+        VERSION "${PROJECT_VERSION}")
 
 #cJSON_Utils
 option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
@@ -205,11 +198,7 @@ if(ENABLE_CJSON_UTILS)
         INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
     )
     if (BUILD_SHARED_AND_STATIC_LIBS)
-        install(TARGETS "${CJSON_UTILS_LIB}-static" 
-        EXPORT "${CJSON_UTILS_LIB}" 
-        ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
-        INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
-        )
+        install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
     endif()
     install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
     install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
@@ -218,12 +207,10 @@ if(ENABLE_CJSON_UTILS)
       install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
     endif()
 
-    if(ENABLE_CJSON_VERSION_SO)
-        set_target_properties("${CJSON_UTILS_LIB}"
-            PROPERTIES
-                SOVERSION "${CJSON_UTILS_VERSION_SO}"
-                VERSION "${PROJECT_VERSION}")
-    endif()
+    set_target_properties("${CJSON_UTILS_LIB}"
+        PROPERTIES
+            SOVERSION "${CJSON_UTILS_VERSION_SO}"
+            VERSION "${PROJECT_VERSION}")
 endif()
 
 # create the other package config files

+ 0 - 0
components/spotify/cspot/bell/cJSON/CONTRIBUTORS.md → components/spotify/cspot/bell/external/cJSON/CONTRIBUTORS.md


+ 0 - 0
components/spotify/cspot/bell/cJSON/LICENSE → components/spotify/cspot/bell/external/cJSON/LICENSE


+ 0 - 0
components/spotify/cspot/bell/cJSON/README.md → components/spotify/cspot/bell/external/cJSON/README.md


+ 0 - 0
components/spotify/cspot/bell/cJSON/appveyor.yml → components/spotify/cspot/bell/external/cJSON/appveyor.yml


+ 7 - 16
components/spotify/cspot/bell/cJSON/cJSON.c → components/spotify/cspot/bell/external/cJSON/cJSON.c

@@ -96,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
     return (const char*) (global_error.json + global_error.position);
 }
 
-CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) 
 {
-    if (!cJSON_IsString(item))
+    if (!cJSON_IsString(item)) 
     {
         return NULL;
     }
@@ -106,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
     return item->valuestring;
 }
 
-CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) 
 {
-    if (!cJSON_IsNumber(item))
+    if (!cJSON_IsNumber(item)) 
     {
         return (double) NAN;
     }
@@ -511,7 +511,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
 
             return NULL;
         }
-
+        
         memcpy(newbuffer, p->buffer, p->offset + 1);
         p->hooks.deallocate(p->buffer);
     }
@@ -562,10 +562,6 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
     {
         length = sprintf((char*)number_buffer, "null");
     }
-	else if(d == (double)item->valueint)
-	{
-		length = sprintf((char*)number_buffer, "%d", item->valueint);
-	}
     else
     {
         /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
@@ -1107,7 +1103,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
     }
 
     buffer.content = (const unsigned char*)value;
-    buffer.length = buffer_length;
+    buffer.length = buffer_length; 
     buffer.offset = 0;
     buffer.hooks = global_hooks;
 
@@ -2361,11 +2357,6 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
         cJSON_free(replacement->string);
     }
     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
-    if (replacement->string == NULL)
-    {
-        return false;
-    }
-
     replacement->type &= ~cJSON_StringIsConst;
 
     return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
@@ -2698,7 +2689,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co
     if (a && a->child) {
         a->child->prev = n;
     }
-
+    
     return a;
 }
 

+ 0 - 7
components/spotify/cspot/bell/cJSON/cJSON.h → components/spotify/cspot/bell/external/cJSON/cJSON.h

@@ -279,13 +279,6 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
 /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
 
-/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
-#define cJSON_SetBoolValue(object, boolValue) ( \
-    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
-    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
-    cJSON_Invalid\
-)
-
 /* Macro for iterating over an array or object */
 #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
 

+ 0 - 0
components/spotify/cspot/bell/cJSON/cJSON_Utils.c → components/spotify/cspot/bell/external/cJSON/cJSON_Utils.c


+ 0 - 0
components/spotify/cspot/bell/cJSON/cJSON_Utils.h → components/spotify/cspot/bell/external/cJSON/cJSON_Utils.h


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/.gitignore → components/spotify/cspot/bell/external/cJSON/fuzzing/.gitignore


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/CMakeLists.txt → components/spotify/cspot/bell/external/cJSON/fuzzing/CMakeLists.txt


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/afl-prepare-linux.sh → components/spotify/cspot/bell/external/cJSON/fuzzing/afl-prepare-linux.sh


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/afl.c → components/spotify/cspot/bell/external/cJSON/fuzzing/afl.c


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/afl.sh → components/spotify/cspot/bell/external/cJSON/fuzzing/afl.sh


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/cjson_read_fuzzer.c → components/spotify/cspot/bell/external/cJSON/fuzzing/cjson_read_fuzzer.c


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/fuzz_main.c → components/spotify/cspot/bell/external/cJSON/fuzzing/fuzz_main.c


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test1 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test1


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test10 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test10


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test11 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test11


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test2 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test2


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test3 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test3.bu → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.bu


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test3.uf → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.uf


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test3.uu → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test3.uu


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test4 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test4


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test5 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test5


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test6 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test6


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test7 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test7


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test8 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test8


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/inputs/test9 → components/spotify/cspot/bell/external/cJSON/fuzzing/inputs/test9


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/json.dict → components/spotify/cspot/bell/external/cJSON/fuzzing/json.dict


+ 0 - 0
components/spotify/cspot/bell/cJSON/fuzzing/ossfuzz.sh → components/spotify/cspot/bell/external/cJSON/fuzzing/ossfuzz.sh


+ 0 - 0
components/spotify/cspot/bell/cJSON/library_config/cJSONConfig.cmake.in → components/spotify/cspot/bell/external/cJSON/library_config/cJSONConfig.cmake.in


+ 0 - 0
components/spotify/cspot/bell/cJSON/library_config/cJSONConfigVersion.cmake.in → components/spotify/cspot/bell/external/cJSON/library_config/cJSONConfigVersion.cmake.in


Некоторые файлы не были показаны из-за большого количества измененных файлов