From 3043f5d4d554633b0b341303dee8a8f0e6acf16d Mon Sep 17 00:00:00 2001 From: Joshua Jones Date: Tue, 9 Feb 2010 05:58:27 +0000 Subject: [PATCH] Added plugin manager and plugin system to cAudio. Started work on an mp3 decoder plugin. Conflict fixes to earlier commit. --- Headers/cAudioPlugin.h | 56 + Headers/cMutex.h | 4 +- Headers/cPluginManager.h | 74 + Headers/cThread.h | 4 +- Headers/cUtils.h | 54 + Source/cAudioCapture.cpp | 13 + Source/cAudioManager.cpp | 15 +- Source/cAudioPlugin.cpp | 52 + Source/cAudioSleep.cpp | 6 +- Source/cMutex.cpp | 8 +- Source/cPluginManager.cpp | 162 ++ Source/cThread.cpp | 4 +- cAudio.sln | 6 + cAudio.vcproj | 28 + include/IAudioPlugin.h | 54 + include/IPluginManager.h | 26 + include/cAudioDefines.h | 32 +- include/cAudioPlatform.h | 22 + plugins/mp3Decoder/cMP3Decoder.cpp | 46 + plugins/mp3Decoder/cMP3Decoder.h | 36 + plugins/mp3Decoder/cMP3DecoderFactory.h | 23 + plugins/mp3Decoder/license.txt | 458 +++++ plugins/mp3Decoder/main.cpp | 45 + plugins/mp3Decoder/mp3Decoder.vcproj | 224 ++ plugins/mp3Decoder/mpaudec/bits.c | 273 +++ plugins/mp3Decoder/mpaudec/internal.h | 86 + plugins/mp3Decoder/mpaudec/mpaudec.c | 2477 +++++++++++++++++++++++ plugins/mp3Decoder/mpaudec/mpaudec.h | 34 + plugins/mp3Decoder/mpaudec/mpaudectab.h | 772 +++++++ plugins/mp3Decoder/mpaudec/mpegaudio.h | 17 + plugins/mp3Decoder/readme.txt | 5 + 31 files changed, 5073 insertions(+), 43 deletions(-) create mode 100644 Headers/cAudioPlugin.h create mode 100644 Headers/cPluginManager.h create mode 100644 Source/cAudioPlugin.cpp create mode 100644 Source/cPluginManager.cpp create mode 100644 include/IAudioPlugin.h create mode 100644 include/IPluginManager.h create mode 100644 include/cAudioPlatform.h create mode 100644 plugins/mp3Decoder/cMP3Decoder.cpp create mode 100644 plugins/mp3Decoder/cMP3Decoder.h create mode 100644 plugins/mp3Decoder/cMP3DecoderFactory.h create mode 100644 plugins/mp3Decoder/license.txt create mode 100644 plugins/mp3Decoder/main.cpp create mode 100644 plugins/mp3Decoder/mp3Decoder.vcproj create mode 100644 plugins/mp3Decoder/mpaudec/bits.c create mode 100644 plugins/mp3Decoder/mpaudec/internal.h create mode 100644 plugins/mp3Decoder/mpaudec/mpaudec.c create mode 100644 plugins/mp3Decoder/mpaudec/mpaudec.h create mode 100644 plugins/mp3Decoder/mpaudec/mpaudectab.h create mode 100644 plugins/mp3Decoder/mpaudec/mpegaudio.h create mode 100644 plugins/mp3Decoder/readme.txt diff --git a/Headers/cAudioPlugin.h b/Headers/cAudioPlugin.h new file mode 100644 index 0000000..1266107 --- /dev/null +++ b/Headers/cAudioPlugin.h @@ -0,0 +1,56 @@ +#ifndef CAUDIOPLUGIN_H_INCLUDED +#define CAUDIOPLUGIN_H_INCLUDED + +#include "../include/IAudioPlugin.h" + +namespace cAudio +{ + typedef bool (*pluginInstallFunc)(); + typedef const char* (*pluginNameFunc)(); + typedef void (*pluginUninstallFunc)(); + + typedef void (*pluginOnCreateAudioManager)(IAudioManager*); + typedef void (*pluginOnCreateAudioCapture)(IAudioCapture*); + + typedef void (*pluginOnDestroyAudioManager)(IAudioManager*); + typedef void (*pluginOnDestroyAudioCapture)(IAudioCapture*); + + //Simply acts as a shim between dll functions and IAudioPlugin + class cAudioPlugin : public IAudioPlugin + { + public: + cAudioPlugin() + { + initFunc = 0x0; + nameFunc = 0x0; + uninstalledFunc = 0x0; + createAudioManagerFunc = 0x0; + createAudioCaptureFunc = 0x0; + destroyAudioManagerFunc = 0x0; + destroyAudioCaptureFunc = 0x0; + } + ~cAudioPlugin() { } + + virtual bool installPlugin(); + virtual const char* getPluginName(); + virtual void uninstallPlugin(); + + virtual void onCreateAudioManager(IAudioManager* manager); + virtual void onCreateAudioCapture(IAudioCapture* capture); + + virtual void onDestroyAudioManager(IAudioManager* manager); + virtual void onDestoryAudioCapture(IAudioCapture* capture); + + pluginInstallFunc initFunc; + pluginNameFunc nameFunc; + pluginUninstallFunc uninstalledFunc; + + pluginOnCreateAudioManager createAudioManagerFunc; + pluginOnCreateAudioCapture createAudioCaptureFunc; + + pluginOnDestroyAudioManager destroyAudioManagerFunc; + pluginOnDestroyAudioCapture destroyAudioCaptureFunc; + }; +}; + +#endif //! CAUDIOPLUGIN_H_INCLUDED \ No newline at end of file diff --git a/Headers/cMutex.h b/Headers/cMutex.h index 262e731..4a5be6d 100644 --- a/Headers/cMutex.h +++ b/Headers/cMutex.h @@ -8,7 +8,7 @@ #include "../include/cAudioDefines.h" #ifdef CAUDIO_MAKE_THREAD_SAFE - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN #include //Basic windows include #else #include //Assumed linux system @@ -29,7 +29,7 @@ namespace cAudio void unlock(); private: void initialize(); - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN CRITICAL_SECTION criticalSection; #else pthread_mutex_t Mutex; diff --git a/Headers/cPluginManager.h b/Headers/cPluginManager.h new file mode 100644 index 0000000..4724329 --- /dev/null +++ b/Headers/cPluginManager.h @@ -0,0 +1,74 @@ +#ifndef CPLUGINMANAGER_H_INCLUDED +#define CPLUGINMANAGER_H_INCLUDED + +#include +#include +#include + +#include "../include/IPluginManager.h" +#include "../include/IAudioPlugin.h" +#include "../Headers/cMutex.h" + +#ifdef CAUDIO_PLATFORM_WIN +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#ifdef CAUDIO_PLATFORM_MAC +# include "macUtils.h" +# include +#endif + +#ifdef CAUDIO_PLATFORM_WIN +# define DYNLIB_HANDLE hInstance +# define DYNLIB_LOAD( a ) LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ) +# define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b ) +# define DYNLIB_UNLOAD( a ) !FreeLibrary( a ) +#endif + +struct HINSTANCE__; +typedef struct HINSTANCE__* hInstance; + +#ifdef CAUDIO_PLATFORM_LINUX +# define DYNLIB_HANDLE void* +# define DYNLIB_LOAD( a ) dlopen( a, RTLD_LAZY | RTLD_GLOBAL) +# define DYNLIB_GETSYM( a, b ) dlsym( a, b ) +# define DYNLIB_UNLOAD( a ) dlclose( a ) +#endif + +#ifdef CAUDIO_PLATFORM_MAC +# define DYNLIB_HANDLE void* +# define DYNLIB_LOAD( a ) mac_loadDylib( a ) +# define DYNLIB_GETSYM( a, b ) dlsym( a, b ) +# define DYNLIB_UNLOAD( a ) dlclose( a ) +#endif + +namespace cAudio +{ + class cPluginManager : public IPluginManager + { + public: + cPluginManager(); + ~cPluginManager(); + + virtual bool installPlugin(IAudioPlugin* plugin, const char* name); + virtual bool installPlugin(const char* filename, const char* name); + + virtual bool checkForPlugin(const char* name); + virtual IAudioPlugin* getPlugin(const char* name); + virtual unsigned int getPluginCount(); + std::vector getPluginList(); + + virtual void uninstallPlugin(IAudioPlugin* plugin); + virtual void uninstallPlugin(const char* name); + + void autoLoadPlugins(); + protected: + std::map RegisteredPlugins; + std::map DynamicallyLoadedPlugins; + }; + + static cPluginManager PluginManagerSingleton; +}; + +#endif //! CPLUGINMANAGER_H_INCLUDED \ No newline at end of file diff --git a/Headers/cThread.h b/Headers/cThread.h index 0d0b5a5..9db381a 100644 --- a/Headers/cThread.h +++ b/Headers/cThread.h @@ -8,7 +8,7 @@ #include "../include/cAudioDefines.h" //Helper defines in order to make sure the function is declared right for use as a thread -#ifdef _WIN32 +#ifdef CAUDIO_PLATFORM_WIN #define CAUDIO_DECLARE_THREAD_FUNCTION(functionName) unsigned __stdcall functionName( void* arguments ) #else #define CAUDIO_DECLARE_THREAD_FUNCTION(functionName) void* functionName( void* arguments ) @@ -23,7 +23,7 @@ namespace cAudio /** \param start_address The function you want to call // \param arg Any arguments to pass to the function // \return 0 if successful, otherwise an error */ -#ifdef _WIN32 +#ifdef CAUDIO_PLATFORM_WIN static int SpawnThread( unsigned __stdcall start_address( void* ), void *arg); #else static int SpawnThread( void* start_address( void* ), void *arg); diff --git a/Headers/cUtils.h b/Headers/cUtils.h index cf7ddfe..044cc84 100644 --- a/Headers/cUtils.h +++ b/Headers/cUtils.h @@ -4,7 +4,21 @@ #ifndef CUTILS_H_INCLUDED #define CUTILS_H_INCLUDED +#include "../include/cAudioPlatform.h" #include +#include + +#ifdef CAUDIO_PLATFORM_WIN +# define WIN32_LEAN_AND_MEAN +# include +# include +# include +#endif + +#ifdef CAUDIO_PLATFORM_LINUX +# include +# include +#endif //! Grabs the current extention of a given string. static std::string getExt(const std::string& filename) @@ -20,4 +34,44 @@ static std::string safeCStr(const char* str) else return std::string(""); } +static std::vector getFilesInDirectory(std::string path) +{ + std::vector FileList; +#ifdef CAUDIO_PLATFORM_WIN + std::string search = path + "\\" + std::string("*.*"); + WIN32_FIND_DATA info; + HANDLE h = FindFirstFile(search.c_str(), &info); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0)) + { + FileList.push_back(info.cFileName); + } + } while (FindNextFile(h, &info)); + FindClose(h); + } +#endif + +#ifdef CAUDIO_PLATFORM_LINUX + DIR *d; + struct dirent *dir; + d = opendir(path.c_str()); + if (d) + { + while ((dir = readdir(d)) != NULL) + { + if( strcmp( dir->d_name, "." ) == 0 || strcmp( dir->d_name, ".." ) == 0 ) { continue; } + if( dir->d_type == DT_DIR ) continue; + FileList.push_back(dir->d_name); + } + + closedir(d); + } +#endif + + return FileList; +} + #endif //! CUTILS_H_INCLUDED diff --git a/Source/cAudioCapture.cpp b/Source/cAudioCapture.cpp index 86591db..80ec3f7 100644 --- a/Source/cAudioCapture.cpp +++ b/Source/cAudioCapture.cpp @@ -7,6 +7,7 @@ #include "../Headers/cThread.h" #include "../include/cAudioSleep.h" #include "../Headers/cLogger.h" +#include "../Headers/cPluginManager.h" #include #include @@ -338,6 +339,12 @@ namespace cAudio if(initializeDefault) capture->initialize(); + std::vector plugins = PluginManagerSingleton.getPluginList(); + for(unsigned int i = 0; i < plugins.size(); ++i) + { + plugins[i]->onCreateAudioCapture(capture); + } + #ifdef CAUDIO_USE_INTERNAL_THREAD AudioCaptureObjectsMutex.lock(); AudioCaptureObjects.insert(capture); @@ -364,6 +371,12 @@ namespace cAudio RunAudioCaptureThread = false; AudioCaptureObjectsMutex.unlock(); #endif + std::vector plugins = PluginManagerSingleton.getPluginList(); + for(unsigned int i = 0; i < plugins.size(); ++i) + { + plugins[i]->onDestoryAudioCapture(capture); + } + delete capture; capture = NULL; } diff --git a/Source/cAudioManager.cpp b/Source/cAudioManager.cpp index a67d588..47628b8 100644 --- a/Source/cAudioManager.cpp +++ b/Source/cAudioManager.cpp @@ -12,7 +12,7 @@ #include "../Headers/cThread.h" #include "../include/cAudioSleep.h" #include "../Headers/cLogger.h" -#include "../include/CAudioDefines.h" +#include "../Headers/cPluginManager.h" #include #include @@ -608,6 +608,12 @@ namespace cAudio manager->getAvailableDevices(); + std::vector plugins = PluginManagerSingleton.getPluginList(); + for(unsigned int i = 0; i < plugins.size(); ++i) + { + plugins[i]->onCreateAudioManager(manager); + } + #ifdef CAUDIO_USE_INTERNAL_THREAD AudioManagerObjectsMutex.lock(); AudioManagerObjects.insert(manager); @@ -635,6 +641,13 @@ namespace cAudio AudioManagerObjectsMutex.unlock(); #endif manager->shutDown(); + + std::vector plugins = PluginManagerSingleton.getPluginList(); + for(unsigned int i = 0; i < plugins.size(); ++i) + { + plugins[i]->onDestroyAudioManager(manager); + } + delete manager; manager = NULL; } diff --git a/Source/cAudioPlugin.cpp b/Source/cAudioPlugin.cpp new file mode 100644 index 0000000..56f077d --- /dev/null +++ b/Source/cAudioPlugin.cpp @@ -0,0 +1,52 @@ +#include "../Headers/cAudioPlugin.h" + +namespace cAudio +{ + +bool cAudioPlugin::installPlugin() +{ + if(initFunc) + return initFunc(); + + return false; +} + +const char* cAudioPlugin::getPluginName() +{ + if(nameFunc) + return nameFunc(); + + return 0x0; +} + +void cAudioPlugin::uninstallPlugin() +{ + if(uninstalledFunc) + uninstalledFunc(); +} + +void cAudioPlugin::onCreateAudioManager(IAudioManager* manager) +{ + if(createAudioManagerFunc) + createAudioManagerFunc(manager); +} + +void cAudioPlugin::onCreateAudioCapture(IAudioCapture* capture) +{ + if(createAudioCaptureFunc) + createAudioCaptureFunc(capture); +} + +void cAudioPlugin::onDestroyAudioManager(IAudioManager* manager) +{ + if(destroyAudioManagerFunc) + destroyAudioManagerFunc(manager); +} + +void cAudioPlugin::onDestoryAudioCapture(IAudioCapture* capture) +{ + if(destroyAudioCaptureFunc) + destroyAudioCaptureFunc(capture); +} + +}; \ No newline at end of file diff --git a/Source/cAudioSleep.cpp b/Source/cAudioSleep.cpp index 50f2da7..1aa550d 100644 --- a/Source/cAudioSleep.cpp +++ b/Source/cAudioSleep.cpp @@ -2,7 +2,9 @@ // This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h -#ifdef _WIN32 +#include "../include/cAudioPlatform.h" + +#ifdef CAUDIO_PLATFORM_WIN #include //Basic windows include for Sleep(); #else #include //Assumed linux system, include for usleep() @@ -16,7 +18,7 @@ namespace cAudio void cAudioSleep(unsigned int ms) { -#ifdef _WIN32 +#ifdef CAUDIO_PLATFORM_WIN Sleep(ms); #else usleep(ms*1000); //convert from milliseconds to microseconds diff --git a/Source/cMutex.cpp b/Source/cMutex.cpp index 8744f0a..e0655a6 100644 --- a/Source/cMutex.cpp +++ b/Source/cMutex.cpp @@ -15,7 +15,7 @@ namespace cAudio { if(!Initialized) return; - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN DeleteCriticalSection(&criticalSection); #else pthread_mutex_destroy(&Mutex); @@ -27,7 +27,7 @@ namespace cAudio if(!Initialized) initialize(); - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN EnterCriticalSection(&criticalSection); #else int error = pthread_mutex_lock(&Mutex); @@ -38,7 +38,7 @@ namespace cAudio { if(!Initialized) return; - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN LeaveCriticalSection(&criticalSection); #else int error = pthread_mutex_unlock(&Mutex); @@ -47,7 +47,7 @@ namespace cAudio void cAudioMutex::initialize(void) { - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN InitializeCriticalSection(&criticalSection); #else pthread_mutexattr_t attr; diff --git a/Source/cPluginManager.cpp b/Source/cPluginManager.cpp new file mode 100644 index 0000000..f7fb0b5 --- /dev/null +++ b/Source/cPluginManager.cpp @@ -0,0 +1,162 @@ +#include "../Headers/cPluginManager.h" +#include "../Headers/cUtils.h" +#include "../include/cAudioPlatform.h" +#include "../Headers/cAudioPlugin.h" + +namespace cAudio +{ + +cPluginManager::cPluginManager() +{ + autoLoadPlugins(); +} + +cPluginManager::~cPluginManager() +{ + std::map::iterator it; + for(it = DynamicallyLoadedPlugins.begin(); it != DynamicallyLoadedPlugins.end(); it++) + { + //Found a plugin we loaded from the filesystem, unload it and delete the plugin + if(DYNLIB_UNLOAD(it->second)) + { + //Could be an error, not reporting it for now + } + delete it->first; + } +} + +bool cPluginManager::installPlugin(IAudioPlugin* plugin, const char* name) +{ + if(plugin) + { + std::string theName = safeCStr(name); + if(theName.empty()) + theName = plugin->getPluginName(); + + if(plugin->installPlugin()) + { + RegisteredPlugins[theName] = plugin; + return true; + } + } + return false; +} + +bool cPluginManager::installPlugin(const char* filename, const char* name) +{ + DYNLIB_HANDLE m_hInst = DYNLIB_LOAD(filename); + if(m_hInst) + { + cAudioPlugin* plugin = new cAudioPlugin(); + if(plugin) + { + plugin->initFunc = (pluginInstallFunc)DYNLIB_GETSYM(m_hInst, "InstallPlugin"); + plugin->nameFunc = (pluginNameFunc)DYNLIB_GETSYM(m_hInst, "GetPluginName"); + plugin->uninstalledFunc = (pluginUninstallFunc)DYNLIB_GETSYM(m_hInst, "UninstallPlugin"); + plugin->createAudioManagerFunc = (pluginOnCreateAudioManager)DYNLIB_GETSYM(m_hInst, "OnCreateAudioManager"); + plugin->createAudioCaptureFunc = (pluginOnCreateAudioCapture)DYNLIB_GETSYM(m_hInst, "OnCreateAudioCapture"); + plugin->destroyAudioManagerFunc = (pluginOnDestroyAudioManager)DYNLIB_GETSYM(m_hInst, "OnDestroyAudioManager"); + plugin->destroyAudioCaptureFunc = (pluginOnDestroyAudioCapture)DYNLIB_GETSYM(m_hInst, "OnDestroyAudioCapture"); + + if(plugin->initFunc && plugin->nameFunc && plugin->uninstalledFunc) + { + DynamicallyLoadedPlugins[plugin] = m_hInst; + + return installPlugin(plugin, name); + } + } + } + return false; +} + +bool cPluginManager::checkForPlugin(const char* name) +{ + return (RegisteredPlugins.find(name) != RegisteredPlugins.end()); +} + +IAudioPlugin* cPluginManager::getPlugin(const char* name) +{ + if(RegisteredPlugins.find(name) != RegisteredPlugins.end()) + { + return RegisteredPlugins[name]; + } + return NULL; +} + +unsigned int cPluginManager::getPluginCount() +{ + return RegisteredPlugins.size(); +} + +std::vector cPluginManager::getPluginList() +{ + std::vector list; + std::map::iterator it; + for(it = RegisteredPlugins.begin(); it != RegisteredPlugins.end(); it++) + { + list.push_back(it->second); + } + return list; +} + +void cPluginManager::uninstallPlugin(IAudioPlugin* plugin) +{ + if(plugin) + { + std::map::iterator it; + for(it = RegisteredPlugins.begin(); it != RegisteredPlugins.end(); it++) + { + if(it->second == plugin) + { + RegisteredPlugins.erase(it->first); + break; + } + } + + std::map::iterator it2 = DynamicallyLoadedPlugins.find(plugin); + if(it2 != DynamicallyLoadedPlugins.end()) + { + //Found a plugin we loaded from the filesystem, unload it and delete the plugin + if(DYNLIB_UNLOAD(it2->second)) + { + //Could be an error, not reporting it for now + } + DynamicallyLoadedPlugins.erase(it2->first); + delete plugin; + } + } +} + +void cPluginManager::uninstallPlugin(const char* name) +{ + if(RegisteredPlugins.find(name) != RegisteredPlugins.end()) + { + uninstallPlugin(RegisteredPlugins[name]); + } +} + +void cPluginManager::autoLoadPlugins() +{ + std::vector fileList = getFilesInDirectory("."); + for(int i=0; i //Basic windows includes #include #else @@ -13,7 +13,7 @@ namespace cAudio { - #ifdef _WIN32 + #ifdef CAUDIO_PLATFORM_WIN int cAudioThread::SpawnThread( unsigned __stdcall start_address( void* ), void *arg) { HANDLE threadHandle; diff --git a/cAudio.sln b/cAudio.sln index fb94a72..a5825c5 100644 --- a/cAudio.sln +++ b/cAudio.sln @@ -33,6 +33,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial5_AudioEffects", "E {ACD6C202-85D4-44F5-83BF-6577A074F655} = {ACD6C202-85D4-44F5-83BF-6577A074F655} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mp3Decoder", "plugins\mp3Decoder\mp3Decoder.vcproj", "{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -67,6 +69,10 @@ Global {EA03D1BB-6D71-4960-958A-670480A8259A}.Debug|Win32.Build.0 = Debug|Win32 {EA03D1BB-6D71-4960-958A-670480A8259A}.Release|Win32.ActiveCfg = Release|Win32 {EA03D1BB-6D71-4960-958A-670480A8259A}.Release|Win32.Build.0 = Release|Win32 + {F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Debug|Win32.ActiveCfg = Debug|Win32 + {F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Debug|Win32.Build.0 = Debug|Win32 + {F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Release|Win32.ActiveCfg = Release|Win32 + {F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/cAudio.vcproj b/cAudio.vcproj index a510bb3..379c0d4 100644 --- a/cAudio.vcproj +++ b/cAudio.vcproj @@ -191,6 +191,10 @@ RelativePath=".\Headers\cAudioManager.h" > + + @@ -239,6 +243,10 @@ RelativePath=".\Headers\cOggDecoder.h" > + + @@ -283,6 +291,10 @@ RelativePath=".\Source\cAudioManager.cpp" > + + @@ -331,6 +343,10 @@ RelativePath=".\Source\cOggDecoder.cpp" > + + @@ -359,6 +375,10 @@ RelativePath=".\include\cAudioDefines.h" > + + @@ -391,6 +411,10 @@ RelativePath=".\include\IAudioManager.h" > + + @@ -419,6 +443,10 @@ RelativePath=".\include\ILogReceiver.h" > + + diff --git a/include/IAudioPlugin.h b/include/IAudioPlugin.h new file mode 100644 index 0000000..97243c5 --- /dev/null +++ b/include/IAudioPlugin.h @@ -0,0 +1,54 @@ +#ifndef IAUDIOPLUGIN_H_INCLUDED +#define IAUDIOPLUGIN_H_INCLUDED + +class IAudioManager; +class IAudioCapture; + +namespace cAudio +{ + //Class that abstracts a particular plugin implementation + //Plugins must have the following functions: + /* + //Will be called on initial install of the plugin, use this for any first time initialization. + bool installPlugin(); + + //Must return a unique name that identifies this plugin. + const char* getPluginName(); + + //Will be called on when cAudio uninstalls this plugin, use this for any final cleanup. + void uninstallPlugin(); + + //Optional Functions, implement one if you want to support that feature of the library + + //Will be called when an Audio Manager is created. Use the passed in pointer to register any decoders or event handlers. + void onCreateAudioManager(IAudioManager* manager); + + //Will be called when an Audio Capture Device is created. Use the passed in pointer to register any event handlers. + void onCreateAudioCapture(IAudioCapture* capture); + + //Will be called when an Audio Manager is destroyed. Use the passed in pointer to remove any decoders or event handlers. + void onDestroyAudioManager(IAudioManager* manager); + + //Will be called when an Audio Capture Device is destroyed. Use the passed in pointer to remove any event handlers. + void onDestroyAudioCapture(IAudioCapture* capture); + + */ + class IAudioPlugin + { + public: + IAudioPlugin() { } + ~IAudioPlugin() { } + + virtual bool installPlugin() = 0; + virtual const char* getPluginName() = 0; + virtual void uninstallPlugin() = 0; + + virtual void onCreateAudioManager(IAudioManager* manager) = 0; + virtual void onCreateAudioCapture(IAudioCapture* capture) = 0; + + virtual void onDestroyAudioManager(IAudioManager* manager) = 0; + virtual void onDestoryAudioCapture(IAudioCapture* capture) = 0; + }; +}; + +#endif //! IAUDIOPLUGIN_H_INCLUDED \ No newline at end of file diff --git a/include/IPluginManager.h b/include/IPluginManager.h new file mode 100644 index 0000000..9e60e3c --- /dev/null +++ b/include/IPluginManager.h @@ -0,0 +1,26 @@ +#ifndef IPLUGINMANAGER_H_INCLUDED +#define IPLUGINMANAGER_H_INCLUDED + +#include "IAudioPlugin.h" + +namespace cAudio +{ + class IPluginManager + { + public: + IPluginManager() { } + ~IPluginManager() { } + + virtual bool installPlugin(IAudioPlugin* plugin, const char* name = NULL) = 0; + virtual bool installPlugin(const char* filename, const char* name = NULL) = 0; + + virtual bool checkForPlugin(const char* name) = 0; + virtual IAudioPlugin* getPlugin(const char* name) = 0; + virtual unsigned int getPluginCount() = 0; + + virtual void uninstallPlugin(IAudioPlugin* plugin) = 0; + virtual void uninstallPlugin(const char* name) = 0; + }; +}; + +#endif //! IPLUGINMANAGER_H_INCLUDED \ No newline at end of file diff --git a/include/cAudioDefines.h b/include/cAudioDefines.h index 31cf8c7..1c719b6 100644 --- a/include/cAudioDefines.h +++ b/include/cAudioDefines.h @@ -1,36 +1,8 @@ -// Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones -// This file is part of the "cAudio Engine" -// For conditions of distribution and use, see copyright notice in cAudio.h - #ifndef CAUDIODEFINES_H #define CAUDIODEFINES_H -//To use EFX in linux. -#ifndef ALC_EXT_EFX -#define AL_FILTER_TYPE 0x8001 -#define AL_EFFECT_TYPE 0x8001 -#define AL_FILTER_NULL 0x0000 -#define AL_FILTER_LOWPASS 0x0001 -#define AL_FILTER_HIGHPASS 0x0002 -#define AL_FILTER_BANDPASS 0x0003 -#define AL_EFFECT_NULL 0x0000 -#define AL_EFFECT_EAXREVERB 0x8000 -#define AL_EFFECT_REVERB 0x0001 -#define AL_EFFECT_CHORUS 0x0002 -#define AL_EFFECT_DISTORTION 0x0003 -#define AL_EFFECT_ECHO 0x0004 -#define AL_EFFECT_FLANGER 0x0005 -#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 -#define AL_EFFECT_VOCAL_MORPHER 0x0007 -#define AL_EFFECT_PITCH_SHIFTER 0x0008 -#define AL_EFFECT_RING_MODULATOR 0x0009 -#define AL_EFFECT_AUTOWAH 0x000A -#define AL_EFFECT_COMPRESSOR 0x000B -#define AL_EFFECT_EQUALIZER 0x000C -#define ALC_EFX_MAJOR_VERSION 0x20001 -#define ALC_EFX_MINOR_VERSION 0x20002 -#define ALC_MAX_AUXILIARY_SENDS 0x20003 -#endif +#include "cAudioPlatform.h" + //Global define for exporting the library #ifndef CAUDIO_STATIC_LIB diff --git a/include/cAudioPlatform.h b/include/cAudioPlatform.h new file mode 100644 index 0000000..6fff3d4 --- /dev/null +++ b/include/cAudioPlatform.h @@ -0,0 +1,22 @@ +#ifndef CAUDIOPLATFORM_H_INCLUDED +#define CAUDIOPLATFORM_H_INCLUDED + +#ifndef CAUDIO_PLATFORM_WIN +# if defined( WIN32 ) || defined( _WINDOWS ) || defined(_WIN32) +# define CAUDIO_PLATFORM_WIN +# endif +#endif + +#ifndef CAUDIO_PLATFORM_MAC +# if defined( __APPLE__ ) || defined( __APPLE_CC__ ) +# define CAUDIO_PLATFORM_MAC +# endif +#endif + +#ifndef CAUDIO_PLATFORM_LINUX +# if defined(_UNIX) || defined(__linux) +# define CAUDIO_PLATFORM_LINUX +# endif +#endif + +#endif //! CAUDIOPLATFORM_H_INCLUDED \ No newline at end of file diff --git a/plugins/mp3Decoder/cMP3Decoder.cpp b/plugins/mp3Decoder/cMP3Decoder.cpp new file mode 100644 index 0000000..13f8360 --- /dev/null +++ b/plugins/mp3Decoder/cMP3Decoder.cpp @@ -0,0 +1,46 @@ +#include "cMP3Decoder.h" + +cMP3Decoder::cMP3Decoder(IDataSource* stream) : IAudioDecoder(stream) +{ + +} + +cMP3Decoder::~cMP3Decoder() +{ + +} + +AudioFormats cMP3Decoder::getFormat() +{ + return EAF_16BIT_STEREO; +} + +int cMP3Decoder::getFrequency() +{ + return 0; +} + +bool cMP3Decoder::isSeekingSupported() +{ + return false; +} + +bool cMP3Decoder::isValid() +{ + return false; +} + +int cMP3Decoder::readAudioData(void* output, int amount) +{ + return 0; +} + +bool cMP3Decoder::setPosition(int position, bool relative) +{ + return false; +} + +bool cMP3Decoder::seek(float seconds, bool relative) +{ + return false; +} diff --git a/plugins/mp3Decoder/cMP3Decoder.h b/plugins/mp3Decoder/cMP3Decoder.h new file mode 100644 index 0000000..569efee --- /dev/null +++ b/plugins/mp3Decoder/cMP3Decoder.h @@ -0,0 +1,36 @@ +#ifndef CMP3DECODER_H +#define CMP3DECODER_H + +#include "IAudioDecoder.h" + +using namespace cAudio; + +class cMP3Decoder : public IAudioDecoder +{ + public: + cMP3Decoder(IDataSource* stream); + ~cMP3Decoder(); + + //!Returns the format of the audio data + virtual AudioFormats getFormat(); + + //!Returns the frequency of the audio data + virtual int getFrequency(); + + //!Returns whether seeking is supported + virtual bool isSeekingSupported(); + + //!Returns whether the stream is valid for this codec + virtual bool isValid(); + + //!Reads a section of data out of the audio stream + virtual int readAudioData(void* output, int amount); + + //!Sets the position to read data out of + virtual bool setPosition(int position, bool relative); + + //!If seeking is supported, will seek the stream to seconds + virtual bool seek(float seconds, bool relative); +}; + +#endif //! CMP3DECODER_H \ No newline at end of file diff --git a/plugins/mp3Decoder/cMP3DecoderFactory.h b/plugins/mp3Decoder/cMP3DecoderFactory.h new file mode 100644 index 0000000..8fc8a43 --- /dev/null +++ b/plugins/mp3Decoder/cMP3DecoderFactory.h @@ -0,0 +1,23 @@ +#ifndef CMP3DECODERFACTORY_H +#define CMP3DECODERFACTORY_H + +#include "IAudioDecoderFactory.h" +#include "cMP3Decoder.h" +#include "../Headers/cMutex.h" + +using namespace cAudio; + +class cMP3DecoderFactory : public IAudioDecoderFactory +{ + public: + cMP3DecoderFactory() { } + ~cMP3DecoderFactory() { } + + IAudioDecoder* CreateAudioDecoder(IDataSource* stream) + { + IAudioDecoder* decoder = new cMP3Decoder(stream); + return decoder; + } +}; + +#endif //! CMP3DECODERFACTORY_H \ No newline at end of file diff --git a/plugins/mp3Decoder/license.txt b/plugins/mp3Decoder/license.txt new file mode 100644 index 0000000..4b9ab31 --- /dev/null +++ b/plugins/mp3Decoder/license.txt @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/mp3Decoder/main.cpp b/plugins/mp3Decoder/main.cpp new file mode 100644 index 0000000..3660562 --- /dev/null +++ b/plugins/mp3Decoder/main.cpp @@ -0,0 +1,45 @@ +#include "cMP3DecoderFactory.h" +#include "IAudioPlugin.h" +#include "cAudioDefines.h" +#include "IAudioManager.h" + +//Will be called on initial install of the plugin, use this for any first time initialization. +CAUDIO_API bool InstallPlugin() +{ + //This plugin has no first time initialization to do, so this is an easy function + return true; +} + +//Must return a unique name that identifies this plugin. +CAUDIO_API const char* GetPluginName() +{ + return "MP3Decoder"; +} + +//Will be called on when cAudio uninstalls this plugin, use this for any final cleanup. +CAUDIO_API void UninstallPlugin() +{ + +} + +//Will be called when an Audio Manager is created. Use the passed in pointer to register any decoders or event handlers. +CAUDIO_API void OnCreateAudioManager(cAudio::IAudioManager* manager) +{ + cMP3DecoderFactory* factory = new cMP3DecoderFactory(); + + if(factory) + { + manager->registerAudioDecoder(factory, ".mp3"); + } +} + +CAUDIO_API void OnDestroyAudioManager(cAudio::IAudioManager* manager) +{ + cAudio::IAudioDecoderFactory* factory = manager->getAudioDecoderFactory(".mp3"); + manager->unRegisterAudioDecoder(".mp3"); + + if(factory) + { + delete factory; + } +} diff --git a/plugins/mp3Decoder/mp3Decoder.vcproj b/plugins/mp3Decoder/mp3Decoder.vcproj new file mode 100644 index 0000000..ac713d9 --- /dev/null +++ b/plugins/mp3Decoder/mp3Decoder.vcproj @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/mp3Decoder/mpaudec/bits.c b/plugins/mp3Decoder/mpaudec/bits.c new file mode 100644 index 0000000..d7657e4 --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/bits.c @@ -0,0 +1,273 @@ +/* + * Common bit i/o utils + * Copyright (c) 2000, 2001 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Modified by Matt Campbell for the stand-alone + * mpaudec library. Based on common.c from libavcodec. + */ + +#include "internal.h" + +/** + * init GetBitContext. + * @param buffer bitstream buffer + * @param bit_size the size of the buffer in bits + */ +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int bit_size) +{ + s->buffer= buffer; + s->size_in_bits= bit_size; + s->index=0; +} + +unsigned int show_bits(const GetBitContext *s, int n) +{ + int i; + unsigned int result = 0; + assert(s->size_in_bits - s->index >= n); + for (i = s->index; i < s->index + n; i++) { + int byte_index = i / 8; + unsigned int right_shift = 7 - (i % 8); + uint8_t byte = s->buffer[byte_index]; + uint8_t bit; + result <<= 1; + if (right_shift == 0) + bit = byte & 0x1; + else + bit = (byte >> right_shift) & 0x1; + result |= (unsigned int)bit; + } + return result; +} + +void skip_bits(GetBitContext *s, int n) +{ + s->index += n; +} + +unsigned int get_bits(GetBitContext *s, int n) +{ + unsigned int result = show_bits(s, n); + skip_bits(s, n); + return result; +} + +int get_bits_count(const GetBitContext *s) +{ + return s->index; +} + +/* VLC decoding */ + +/*#define DEBUG_VLC*/ + +#define GET_DATA(v, table, i, wrap, size) \ +{\ + const uint8_t *ptr = (const uint8_t *)table + i * wrap;\ + switch(size) {\ + case 1:\ + v = *(const uint8_t *)ptr;\ + break;\ + case 2:\ + v = *(const uint16_t *)ptr;\ + break;\ + default:\ + v = *(const uint32_t *)ptr;\ + break;\ + }\ +} + + +static int alloc_table(VLC *vlc, int size) +{ + int index; + index = vlc->table_size; + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + vlc->table_allocated += (1 << vlc->bits); + vlc->table = realloc(vlc->table, + sizeof(VLC_TYPE) * 2 * vlc->table_allocated); + if (!vlc->table) + return -1; + } + return index; +} + +static int build_table(VLC *vlc, int table_nb_bits, + int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + uint32_t code_prefix, int n_prefix) +{ + int i, j, k, n, table_size, table_index, nb, n1, index; + uint32_t code; + VLC_TYPE (*table)[2]; + + table_size = 1 << table_nb_bits; + table_index = alloc_table(vlc, table_size); +#ifdef DEBUG_VLC + printf("new table index=%d size=%d code_prefix=%x n=%d\n", + table_index, table_size, code_prefix, n_prefix); +#endif + if (table_index < 0) + return -1; + table = &vlc->table[table_index]; + + for(i=0;i 0 && (code >> n) == code_prefix) { + if (n <= table_nb_bits) { + /* no need to add another table */ + j = (code << (table_nb_bits - n)) & (table_size - 1); + nb = 1 << (table_nb_bits - n); + for(k=0;k> n) & ((1 << table_nb_bits) - 1); +#ifdef DEBUG_VLC + printf("%4x: n=%d (subtable)\n", + j, n); +#endif + /* compute table size */ + n1 = -table[j][1]; /*bits*/ + if (n > n1) + n1 = n; + table[j][1] = -n1; /*bits*/ + } + } + } + + /* second pass : fill auxillary tables recursively */ + for(i=0;i table_nb_bits) { + n = table_nb_bits; + table[i][1] = -n; /*bits*/ + } + index = build_table(vlc, n, nb_codes, + bits, bits_wrap, bits_size, + codes, codes_wrap, codes_size, + (code_prefix << table_nb_bits) | i, + n_prefix + table_nb_bits); + if (index < 0) + return -1; + /* note: realloc has been done, so reload tables */ + table = &vlc->table[table_index]; + table[i][0] = index; /*code*/ + } + } + return table_index; +} + + +/* Build VLC decoding tables suitable for use with get_vlc(). + + 'nb_bits' set thee decoding table size (2^nb_bits) entries. The + bigger it is, the faster is the decoding. But it should not be too + big to save memory and L1 cache. '9' is a good compromise. + + 'nb_codes' : number of vlcs codes + + 'bits' : table which gives the size (in bits) of each vlc code. + + 'codes' : table which gives the bit pattern of of each vlc code. + + 'xxx_wrap' : give the number of bytes between each entry of the + 'bits' or 'codes' tables. + + 'xxx_size' : gives the number of bytes of each entry of the 'bits' + or 'codes' tables. + + 'wrap' and 'size' allows to use any memory configuration and types + (byte/word/long) to store the 'bits' and 'codes' tables. +*/ +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size) +{ + vlc->bits = nb_bits; + vlc->table = NULL; + vlc->table_allocated = 0; + vlc->table_size = 0; +#ifdef DEBUG_VLC + printf("build table nb_codes=%d\n", nb_codes); +#endif + + if (build_table(vlc, nb_bits, nb_codes, + bits, bits_wrap, bits_size, + codes, codes_wrap, codes_size, + 0, 0) < 0) { + free(vlc->table); + return -1; + } + return 0; +} + + +void free_vlc(VLC *vlc) +{ + free(vlc->table); +} + +int get_vlc(GetBitContext *s, const VLC *vlc) +{ + int code = 0; + int depth = 0, max_depth = 3; + int n, index, bits = vlc->bits; + + do { + index = show_bits(s, bits) + code; + code = vlc->table[index][0]; + n = vlc->table[index][1]; + depth++; + + if (n < 0 && depth < max_depth) { + skip_bits(s, bits); + bits = -n; + } + } while (n < 0 && depth < max_depth); + + skip_bits(s, n); + return code; +} diff --git a/plugins/mp3Decoder/mpaudec/internal.h b/plugins/mp3Decoder/mpaudec/internal.h new file mode 100644 index 0000000..5588137 --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/internal.h @@ -0,0 +1,86 @@ +/* Based on common.h from libavcodec. Modified extensively by Matt Campbell + for the stand-alone mpaudec library. */ + +#ifndef INTERNAL_H +#define INTERNAL_H + +#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +# define CONFIG_WIN32 +#endif + +#include +#include +#include +#include +#include +#include +#include "mpaudec.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifdef CONFIG_WIN32 + +/* windows */ + +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +typedef signed char int8_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + +# ifdef _DEBUG +# define DEBUG +# endif + +/* CONFIG_WIN32 end */ +#else + +/* unix */ + +#include + +#endif /* !CONFIG_WIN32 */ + +/* debug stuff */ + +#if !defined(DEBUG) && !defined(NDEBUG) +# define NDEBUG +#endif +#include + +/* bit input */ + +typedef struct GetBitContext { + const uint8_t *buffer; + int index; + int size_in_bits; +} GetBitContext; + +int get_bits_count(const GetBitContext *s); + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; + int table_size, table_allocated; +} VLC; + +unsigned int get_bits(GetBitContext *s, int n); +unsigned int show_bits(const GetBitContext *s, int n); +void skip_bits(GetBitContext *s, int n); +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int buffer_size); + +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size); +void free_vlc(VLC *vlc); +int get_vlc(GetBitContext *s, const VLC *vlc); + +#endif /* INTERNAL_H */ diff --git a/plugins/mp3Decoder/mpaudec/mpaudec.c b/plugins/mp3Decoder/mpaudec/mpaudec.c new file mode 100644 index 0000000..a07289d --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/mpaudec.c @@ -0,0 +1,2477 @@ +/* + * MPEG Audio decoder + * Copyright (c) 2001, 2002 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Modified heavily by Matt Campbell for the + * stand-alone mpaudec library. Based on mpegaudiodec.c from libavcodec. + */ + +/*#define DEBUG*/ +#include "internal.h" +#include "mpegaudio.h" + +#ifdef _MSC_VER +#pragma warning(disable : 4244) +#endif + +/* + * TODO: + * - in low precision mode, use more 16 bit multiplies in synth filter + * - test lsf / mpeg25 extensively. + */ + +/* define USE_HIGHPRECISION to have a bit exact (but slower) mpeg + audio decoder */ +#define USE_HIGHPRECISION + +#ifdef USE_HIGHPRECISION +#define FRAC_BITS 23 /* fractional bits for sb_samples and dct */ +#define WFRAC_BITS 16 /* fractional bits for window */ +#else +#define FRAC_BITS 15 /* fractional bits for sb_samples and dct */ +#define WFRAC_BITS 14 /* fractional bits for window */ +#endif + +#define FRAC_ONE (1 << FRAC_BITS) + +#define MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS) +#define MUL64(a,b) ((int64_t)(a) * (int64_t)(b)) +#define FIX(a) ((int)((a) * FRAC_ONE)) +/* WARNING: only correct for posititive numbers */ +#define FIXR(a) ((int)((a) * FRAC_ONE + 0.5)) +#define FRAC_RND(a) (((a) + (FRAC_ONE/2)) >> FRAC_BITS) + +#if FRAC_BITS <= 15 +typedef int16_t MPA_INT; +#else +typedef int32_t MPA_INT; +#endif + +/****************/ + +#define HEADER_SIZE 4 +#define BACKSTEP_SIZE 512 + +typedef struct MPADecodeContext { + uint8_t inbuf1[2][MPA_MAX_CODED_FRAME_SIZE + BACKSTEP_SIZE]; /* input buffer */ + int inbuf_index; + uint8_t *inbuf_ptr, *inbuf; + int frame_size; + int free_format_frame_size; /* frame size in case of free format + (zero if currently unknown) */ + /* next header (used in free format parsing) */ + int error_protection; + int layer; + int sample_rate; + int sample_rate_index; /* between 0 and 8 */ + int bit_rate; + int old_frame_size; + GetBitContext gb; + int nb_channels; + int mode; + int mode_ext; + int lsf; + MPA_INT synth_buf[MPA_MAX_CHANNELS][512 * 2]; + int synth_buf_offset[MPA_MAX_CHANNELS]; + int32_t sb_samples[MPA_MAX_CHANNELS][36][SBLIMIT]; + int32_t mdct_buf[MPA_MAX_CHANNELS][SBLIMIT * 18]; /* previous samples, for layer 3 MDCT */ +#ifdef DEBUG + int frame_count; +#endif +} MPADecodeContext; + +/* layer 3 "granule" */ +typedef struct GranuleDef { + uint8_t scfsi; + int part2_3_length; + int big_values; + int global_gain; + int scalefac_compress; + uint8_t block_type; + uint8_t switch_point; + int table_select[3]; + int subblock_gain[3]; + uint8_t scalefac_scale; + uint8_t count1table_select; + int region_size[3]; /* number of huffman codes in each region */ + int preflag; + int short_start, long_end; /* long/short band indexes */ + uint8_t scale_factors[40]; + int32_t sb_hybrid[SBLIMIT * 18]; /* 576 samples */ +} GranuleDef; + +#define MODE_EXT_MS_STEREO 2 +#define MODE_EXT_I_STEREO 1 + +/* layer 3 huffman tables */ +typedef struct HuffTable { + int xsize; + const uint8_t *bits; + const uint16_t *codes; +} HuffTable; + +#include "mpaudectab.h" + +/* vlc structure for decoding layer 3 huffman tables */ +static VLC huff_vlc[16]; +static uint8_t *huff_code_table[16]; +static VLC huff_quad_vlc[2]; +/* computed from band_size_long */ +static uint16_t band_index_long[9][23]; +/* XXX: free when all decoders are closed */ +#define TABLE_4_3_SIZE (8191 + 16) +static int8_t table_4_3_exp[TABLE_4_3_SIZE]; +#if FRAC_BITS <= 15 +static uint16_t table_4_3_value[TABLE_4_3_SIZE]; +#else +static uint32_t table_4_3_value[TABLE_4_3_SIZE]; +#endif +/* intensity stereo coef table */ +static int32_t is_table[2][16]; +static int32_t is_table_lsf[2][2][16]; +static int32_t csa_table[8][2]; +static int32_t mdct_win[8][36]; + +/* lower 2 bits: modulo 3, higher bits: shift */ +static uint16_t scale_factor_modshift[64]; +/* [i][j]: 2^(-j/3) * FRAC_ONE * 2^(i+2) / (2^(i+2) - 1) */ +static int32_t scale_factor_mult[15][3]; +/* mult table for layer 2 group quantization */ + +#define SCALE_GEN(v) \ +{ FIXR(1.0 * (v)), FIXR(0.7937005259 * (v)), FIXR(0.6299605249 * (v)) } + +static int32_t scale_factor_mult2[3][3] = { + SCALE_GEN(4.0 / 3.0), /* 3 steps */ + SCALE_GEN(4.0 / 5.0), /* 5 steps */ + SCALE_GEN(4.0 / 9.0), /* 9 steps */ +}; + +/* 2^(n/4) */ +static uint32_t scale_factor_mult3[4] = { + FIXR(1.0), + FIXR(1.18920711500272106671), + FIXR(1.41421356237309504880), + FIXR(1.68179283050742908605), +}; + +static MPA_INT window[512]; + +/* layer 1 unscaling */ +/* n = number of bits of the mantissa minus 1 */ +static int l1_unscale(int n, int mant, int scale_factor) +{ + int shift, mod; + int64_t val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + val = MUL64(mant + (-1 << n) + 1, scale_factor_mult[n-1][mod]); + shift += n; + /* NOTE: at this point, 1 <= shift >= 21 + 15 */ + return (int)((val + ((int64_t)(1) << (shift - 1))) >> shift); +} + +static int l2_unscale_group(int steps, int mant, int scale_factor) +{ + int shift, mod, val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + + val = (mant - (steps >> 1)) * scale_factor_mult2[steps >> 2][mod]; + /* NOTE: at this point, 0 <= shift <= 21 */ + if (shift > 0) + val = (val + (1 << (shift - 1))) >> shift; + return val; +} + +/* compute value^(4/3) * 2^(exponent/4). It normalized to FRAC_BITS */ +static int l3_unscale(int value, int exponent) +{ +#if FRAC_BITS <= 15 + unsigned int m; +#else + uint64_t m; +#endif + int e; + + e = table_4_3_exp[value]; + e += (exponent >> 2); + e = FRAC_BITS - e; +#if FRAC_BITS <= 15 + if (e > 31) + e = 31; +#endif + m = table_4_3_value[value]; +#if FRAC_BITS <= 15 + m = (m * scale_factor_mult3[exponent & 3]); + m = (m + (1 << (e-1))) >> e; + return m; +#else + m = MUL64(m, scale_factor_mult3[exponent & 3]); + m = (m + ((uint64_t)(1) << (e-1))) >> e; + return (int)m; +#endif +} + +/* all integer n^(4/3) computation code */ +#define DEV_ORDER 13 + +#define POW_FRAC_BITS 24 +#define POW_FRAC_ONE (1 << POW_FRAC_BITS) +#define POW_FIX(a) ((int)((a) * POW_FRAC_ONE)) +#define POW_MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> POW_FRAC_BITS) + +static int dev_4_3_coefs[DEV_ORDER]; + +static int pow_mult3[3] = { + POW_FIX(1.0), + POW_FIX(1.25992104989487316476), + POW_FIX(1.58740105196819947474), +}; + +static void int_pow_init(void) +{ + int i, a; + + a = POW_FIX(1.0); + for(i=0;i= 0; j--) + a1 = POW_MULL(a, dev_4_3_coefs[j] + a1); + a = (1 << POW_FRAC_BITS) + a1; + /* exponent compute (exact) */ + e = e * 4; + er = e % 3; + eq = e / 3; + a = POW_MULL(a, pow_mult3[er]); + while (a >= 2 * POW_FRAC_ONE) { + a = a >> 1; + eq++; + } + /* convert to float */ + while (a < POW_FRAC_ONE) { + a = a << 1; + eq--; + } + /* now POW_FRAC_ONE <= a < 2 * POW_FRAC_ONE */ +#if POW_FRAC_BITS > FRAC_BITS + a = (a + (1 << (POW_FRAC_BITS - FRAC_BITS - 1))) >> (POW_FRAC_BITS - FRAC_BITS); + /* correct overflow */ + if (a >= 2 * (1 << FRAC_BITS)) { + a = a >> 1; + eq++; + } +#endif + *exp_ptr = eq; + return a; +} + +int mpaudec_init(MPAuDecContext * mpctx) +{ + MPADecodeContext *s; + static int init=0; + int i, j, k; + assert(mpctx != NULL); + memset(mpctx, 0, sizeof(MPAuDecContext)); + mpctx->priv_data = calloc(1, sizeof(MPADecodeContext)); + if (mpctx->priv_data == NULL) + return -1; + s = mpctx->priv_data; + + if (!init && !mpctx->parse_only) { + /* scale factors table for layer 1/2 */ + for(i=0;i<64;i++) { + int shift, mod; + /* 1.0 (i = 3) is normalized to 2 ^ FRAC_BITS */ + shift = (i / 3); + mod = i % 3; + scale_factor_modshift[i] = mod | (shift << 2); + } + + /* scale factor multiply for layer 1 */ + for(i=0;i<15;i++) { + int n, norm; + n = i + 2; + norm = (((int64_t)(1) << n) * FRAC_ONE) / ((1 << n) - 1); + scale_factor_mult[i][0] = MULL(FIXR(1.0 * 2.0), norm); + scale_factor_mult[i][1] = MULL(FIXR(0.7937005259 * 2.0), norm); + scale_factor_mult[i][2] = MULL(FIXR(0.6299605249 * 2.0), norm); +#ifdef DEBUG + printf("%d: norm=%x s=%x %x %x\n", + i, norm, + scale_factor_mult[i][0], + scale_factor_mult[i][1], + scale_factor_mult[i][2]); +#endif + } + + /* window */ + /* max = 18760, max sum over all 16 coefs : 44736 */ + for(i=0;i<257;i++) { + int v; + v = mpa_enwindow[i]; +#if WFRAC_BITS < 16 + v = (v + (1 << (16 - WFRAC_BITS - 1))) >> (16 - WFRAC_BITS); +#endif + window[i] = v; + if ((i & 63) != 0) + v = -v; + if (i != 0) + window[512 - i] = v; + } + + /* huffman decode tables */ + huff_code_table[0] = NULL; + for(i=1;i<16;i++) { + const HuffTable *h = &mpa_huff_tables[i]; + int xsize, x, y; + unsigned int n; + uint8_t *code_table; + + xsize = h->xsize; + n = xsize * xsize; + /* XXX: fail test */ + init_vlc(&huff_vlc[i], 8, n, + h->bits, 1, 1, h->codes, 2, 2); + + code_table = calloc(n, 1); + j = 0; + for(x=0;x> 1); + f = pow(2.0, e / 4.0); + k = i & 1; + is_table_lsf[j][k ^ 1][i] = FIXR(f); + is_table_lsf[j][k][i] = FIXR(1.0); +#ifdef DEBUG + printf("is_table_lsf %d %d: %x %x\n", + i, j, is_table_lsf[j][0][i], is_table_lsf[j][1][i]); +#endif + } + } + + for(i=0;i<8;i++) { + float ci, cs, ca; + ci = ci_table[i]; + cs = 1.0 / sqrt(1.0 + ci * ci); + ca = cs * ci; + csa_table[i][0] = FIX(cs); + csa_table[i][1] = FIX(ca); + } + + /* compute mdct windows */ + for(i=0;i<36;i++) { + int v; + v = FIXR(sin(M_PI * (i + 0.5) / 36.0)); + mdct_win[0][i] = v; + mdct_win[1][i] = v; + mdct_win[3][i] = v; + } + for(i=0;i<6;i++) { + mdct_win[1][18 + i] = FIXR(1.0); + mdct_win[1][24 + i] = FIXR(sin(M_PI * ((i + 6) + 0.5) / 12.0)); + mdct_win[1][30 + i] = FIXR(0.0); + + mdct_win[3][i] = FIXR(0.0); + mdct_win[3][6 + i] = FIXR(sin(M_PI * (i + 0.5) / 12.0)); + mdct_win[3][12 + i] = FIXR(1.0); + } + + for(i=0;i<12;i++) + mdct_win[2][i] = FIXR(sin(M_PI * (i + 0.5) / 12.0)); + + /* NOTE: we do frequency inversion adter the MDCT by changing + the sign of the right window coefs */ + for(j=0;j<4;j++) { + for(i=0;i<36;i+=2) { + mdct_win[j + 4][i] = mdct_win[j][i]; + mdct_win[j + 4][i + 1] = -mdct_win[j][i + 1]; + } + } + +#if defined(DEBUG) + for(j=0;j<8;j++) { + printf("win%d=\n", j); + for(i=0;i<36;i++) + printf("%f, ", (double)mdct_win[j][i] / FRAC_ONE); + printf("\n"); + } +#endif + init = 1; + } + + s->inbuf_index = 0; + s->inbuf = &s->inbuf1[s->inbuf_index][BACKSTEP_SIZE]; + s->inbuf_ptr = s->inbuf; +#ifdef DEBUG + s->frame_count = 0; +#endif + return 0; +} + +/* tab[i][j] = 1.0 / (2.0 * cos(pi*(2*k+1) / 2^(6 - j))) */ + +/* cos(i*pi/64) */ + +#define COS0_0 FIXR(0.50060299823519630134) +#define COS0_1 FIXR(0.50547095989754365998) +#define COS0_2 FIXR(0.51544730992262454697) +#define COS0_3 FIXR(0.53104259108978417447) +#define COS0_4 FIXR(0.55310389603444452782) +#define COS0_5 FIXR(0.58293496820613387367) +#define COS0_6 FIXR(0.62250412303566481615) +#define COS0_7 FIXR(0.67480834145500574602) +#define COS0_8 FIXR(0.74453627100229844977) +#define COS0_9 FIXR(0.83934964541552703873) +#define COS0_10 FIXR(0.97256823786196069369) +#define COS0_11 FIXR(1.16943993343288495515) +#define COS0_12 FIXR(1.48416461631416627724) +#define COS0_13 FIXR(2.05778100995341155085) +#define COS0_14 FIXR(3.40760841846871878570) +#define COS0_15 FIXR(10.19000812354805681150) + +#define COS1_0 FIXR(0.50241928618815570551) +#define COS1_1 FIXR(0.52249861493968888062) +#define COS1_2 FIXR(0.56694403481635770368) +#define COS1_3 FIXR(0.64682178335999012954) +#define COS1_4 FIXR(0.78815462345125022473) +#define COS1_5 FIXR(1.06067768599034747134) +#define COS1_6 FIXR(1.72244709823833392782) +#define COS1_7 FIXR(5.10114861868916385802) + +#define COS2_0 FIXR(0.50979557910415916894) +#define COS2_1 FIXR(0.60134488693504528054) +#define COS2_2 FIXR(0.89997622313641570463) +#define COS2_3 FIXR(2.56291544774150617881) + +#define COS3_0 FIXR(0.54119610014619698439) +#define COS3_1 FIXR(1.30656296487637652785) + +#define COS4_0 FIXR(0.70710678118654752439) + +/* butterfly operator */ +#define BF(a, b, c)\ +{\ + tmp0 = tab[a] + tab[b];\ + tmp1 = tab[a] - tab[b];\ + tab[a] = tmp0;\ + tab[b] = MULL(tmp1, c);\ +} + +#define BF1(a, b, c, d)\ +{\ + BF(a, b, COS4_0);\ + BF(c, d, -COS4_0);\ + tab[c] += tab[d];\ +} + +#define BF2(a, b, c, d)\ +{\ + BF(a, b, COS4_0);\ + BF(c, d, -COS4_0);\ + tab[c] += tab[d];\ + tab[a] += tab[c];\ + tab[c] += tab[b];\ + tab[b] += tab[d];\ +} + +#define ADD(a, b) tab[a] += tab[b] + +/* DCT32 without 1/sqrt(2) coef zero scaling. */ +static void dct32(int32_t *out, int32_t *tab) +{ + int tmp0, tmp1; + + /* pass 1 */ + BF(0, 31, COS0_0); + BF(1, 30, COS0_1); + BF(2, 29, COS0_2); + BF(3, 28, COS0_3); + BF(4, 27, COS0_4); + BF(5, 26, COS0_5); + BF(6, 25, COS0_6); + BF(7, 24, COS0_7); + BF(8, 23, COS0_8); + BF(9, 22, COS0_9); + BF(10, 21, COS0_10); + BF(11, 20, COS0_11); + BF(12, 19, COS0_12); + BF(13, 18, COS0_13); + BF(14, 17, COS0_14); + BF(15, 16, COS0_15); + + /* pass 2 */ + BF(0, 15, COS1_0); + BF(1, 14, COS1_1); + BF(2, 13, COS1_2); + BF(3, 12, COS1_3); + BF(4, 11, COS1_4); + BF(5, 10, COS1_5); + BF(6, 9, COS1_6); + BF(7, 8, COS1_7); + + BF(16, 31, -COS1_0); + BF(17, 30, -COS1_1); + BF(18, 29, -COS1_2); + BF(19, 28, -COS1_3); + BF(20, 27, -COS1_4); + BF(21, 26, -COS1_5); + BF(22, 25, -COS1_6); + BF(23, 24, -COS1_7); + + /* pass 3 */ + BF(0, 7, COS2_0); + BF(1, 6, COS2_1); + BF(2, 5, COS2_2); + BF(3, 4, COS2_3); + + BF(8, 15, -COS2_0); + BF(9, 14, -COS2_1); + BF(10, 13, -COS2_2); + BF(11, 12, -COS2_3); + + BF(16, 23, COS2_0); + BF(17, 22, COS2_1); + BF(18, 21, COS2_2); + BF(19, 20, COS2_3); + + BF(24, 31, -COS2_0); + BF(25, 30, -COS2_1); + BF(26, 29, -COS2_2); + BF(27, 28, -COS2_3); + + /* pass 4 */ + BF(0, 3, COS3_0); + BF(1, 2, COS3_1); + + BF(4, 7, -COS3_0); + BF(5, 6, -COS3_1); + + BF(8, 11, COS3_0); + BF(9, 10, COS3_1); + + BF(12, 15, -COS3_0); + BF(13, 14, -COS3_1); + + BF(16, 19, COS3_0); + BF(17, 18, COS3_1); + + BF(20, 23, -COS3_0); + BF(21, 22, -COS3_1); + + BF(24, 27, COS3_0); + BF(25, 26, COS3_1); + + BF(28, 31, -COS3_0); + BF(29, 30, -COS3_1); + + /* pass 5 */ + BF1(0, 1, 2, 3); + BF2(4, 5, 6, 7); + BF1(8, 9, 10, 11); + BF2(12, 13, 14, 15); + BF1(16, 17, 18, 19); + BF2(20, 21, 22, 23); + BF1(24, 25, 26, 27); + BF2(28, 29, 30, 31); + + /* pass 6 */ + + ADD( 8, 12); + ADD(12, 10); + ADD(10, 14); + ADD(14, 9); + ADD( 9, 13); + ADD(13, 11); + ADD(11, 15); + + out[ 0] = tab[0]; + out[16] = tab[1]; + out[ 8] = tab[2]; + out[24] = tab[3]; + out[ 4] = tab[4]; + out[20] = tab[5]; + out[12] = tab[6]; + out[28] = tab[7]; + out[ 2] = tab[8]; + out[18] = tab[9]; + out[10] = tab[10]; + out[26] = tab[11]; + out[ 6] = tab[12]; + out[22] = tab[13]; + out[14] = tab[14]; + out[30] = tab[15]; + + ADD(24, 28); + ADD(28, 26); + ADD(26, 30); + ADD(30, 25); + ADD(25, 29); + ADD(29, 27); + ADD(27, 31); + + out[ 1] = tab[16] + tab[24]; + out[17] = tab[17] + tab[25]; + out[ 9] = tab[18] + tab[26]; + out[25] = tab[19] + tab[27]; + out[ 5] = tab[20] + tab[28]; + out[21] = tab[21] + tab[29]; + out[13] = tab[22] + tab[30]; + out[29] = tab[23] + tab[31]; + out[ 3] = tab[24] + tab[20]; + out[19] = tab[25] + tab[21]; + out[11] = tab[26] + tab[22]; + out[27] = tab[27] + tab[23]; + out[ 7] = tab[28] + tab[18]; + out[23] = tab[29] + tab[19]; + out[15] = tab[30] + tab[17]; + out[31] = tab[31]; +} + +#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15) + +#if FRAC_BITS <= 15 + +static int round_sample(int sum) +{ + int sum1; + sum1 = (sum + (1 << (OUT_SHIFT - 1))) >> OUT_SHIFT; + if (sum1 < -32768) + sum1 = -32768; + else if (sum1 > 32767) + sum1 = 32767; + return sum1; +} + +/* signed 16x16 -> 32 multiply add accumulate */ +#define MACS(rt, ra, rb) rt += (ra) * (rb) + +/* signed 16x16 -> 32 multiply */ +#define MULS(ra, rb) ((ra) * (rb)) + +#else + +static int round_sample(int64_t sum) +{ + int sum1; + sum1 = (int)((sum + ((int64_t)(1) << (OUT_SHIFT - 1))) >> OUT_SHIFT); + if (sum1 < -32768) + sum1 = -32768; + else if (sum1 > 32767) + sum1 = 32767; + return sum1; +} + +#define MULS(ra, rb) MUL64(ra, rb) + +#endif + +#define SUM8(sum, op, w, p) \ +{ \ + sum op MULS((w)[0 * 64], p[0 * 64]);\ + sum op MULS((w)[1 * 64], p[1 * 64]);\ + sum op MULS((w)[2 * 64], p[2 * 64]);\ + sum op MULS((w)[3 * 64], p[3 * 64]);\ + sum op MULS((w)[4 * 64], p[4 * 64]);\ + sum op MULS((w)[5 * 64], p[5 * 64]);\ + sum op MULS((w)[6 * 64], p[6 * 64]);\ + sum op MULS((w)[7 * 64], p[7 * 64]);\ +} + +#define SUM8P2(sum1, op1, sum2, op2, w1, w2, p) \ +{ \ + int tmp;\ + tmp = p[0 * 64];\ + sum1 op1 MULS((w1)[0 * 64], tmp);\ + sum2 op2 MULS((w2)[0 * 64], tmp);\ + tmp = p[1 * 64];\ + sum1 op1 MULS((w1)[1 * 64], tmp);\ + sum2 op2 MULS((w2)[1 * 64], tmp);\ + tmp = p[2 * 64];\ + sum1 op1 MULS((w1)[2 * 64], tmp);\ + sum2 op2 MULS((w2)[2 * 64], tmp);\ + tmp = p[3 * 64];\ + sum1 op1 MULS((w1)[3 * 64], tmp);\ + sum2 op2 MULS((w2)[3 * 64], tmp);\ + tmp = p[4 * 64];\ + sum1 op1 MULS((w1)[4 * 64], tmp);\ + sum2 op2 MULS((w2)[4 * 64], tmp);\ + tmp = p[5 * 64];\ + sum1 op1 MULS((w1)[5 * 64], tmp);\ + sum2 op2 MULS((w2)[5 * 64], tmp);\ + tmp = p[6 * 64];\ + sum1 op1 MULS((w1)[6 * 64], tmp);\ + sum2 op2 MULS((w2)[6 * 64], tmp);\ + tmp = p[7 * 64];\ + sum1 op1 MULS((w1)[7 * 64], tmp);\ + sum2 op2 MULS((w2)[7 * 64], tmp);\ +} + + +/* 32 sub band synthesis filter. Input: 32 sub band samples, Output: + 32 samples. */ +/* XXX: optimize by avoiding ring buffer usage */ +static void synth_filter(MPADecodeContext *s1, + int ch, int16_t *samples, int incr, + int32_t sb_samples[SBLIMIT]) +{ + int32_t tmp[32]; + MPA_INT *synth_buf; + const MPA_INT *w, *w2, *p; + int j, offset, v; + int16_t *samples2; +#if FRAC_BITS <= 15 + int32_t sum, sum2; +#else + int64_t sum, sum2; +#endif + + dct32(tmp, sb_samples); + + offset = s1->synth_buf_offset[ch]; + synth_buf = s1->synth_buf[ch] + offset; + + for(j=0;j<32;j++) { + v = tmp[j]; +#if FRAC_BITS <= 15 + /* NOTE: can cause a loss in precision if very high amplitude + sound */ + if (v > 32767) + v = 32767; + else if (v < -32768) + v = -32768; +#endif + synth_buf[j] = v; + } + /* copy to avoid wrap */ + memcpy(synth_buf + 512, synth_buf, 32 * sizeof(MPA_INT)); + + samples2 = samples + 31 * incr; + w = window; + w2 = window + 31; + + sum = 0; + p = synth_buf + 16; + SUM8(sum, +=, w, p); + p = synth_buf + 48; + SUM8(sum, -=, w + 32, p); + *samples = round_sample(sum); + samples += incr; + w++; + + /* we calculate two samples at the same time to avoid one memory + access per two sample */ + for(j=1;j<16;j++) { + sum = 0; + sum2 = 0; + p = synth_buf + 16 + j; + SUM8P2(sum, +=, sum2, -=, w, w2, p); + p = synth_buf + 48 - j; + SUM8P2(sum, -=, sum2, -=, w + 32, w2 + 32, p); + + *samples = round_sample(sum); + samples += incr; + *samples2 = round_sample(sum2); + samples2 -= incr; + w++; + w2--; + } + + p = synth_buf + 32; + sum = 0; + SUM8(sum, -=, w + 32, p); + *samples = round_sample(sum); + + offset = (offset - 32) & 511; + s1->synth_buf_offset[ch] = offset; +} + +/* cos(pi*i/24) */ +#define C1 FIXR(0.99144486137381041114) +#define C3 FIXR(0.92387953251128675612) +#define C5 FIXR(0.79335334029123516458) +#define C7 FIXR(0.60876142900872063941) +#define C9 FIXR(0.38268343236508977173) +#define C11 FIXR(0.13052619222005159154) + +/* 12 points IMDCT. We compute it "by hand" by factorizing obvious + cases. */ +static void imdct12(int *out, int *in) +{ + int tmp; + int64_t in1_3, in1_9, in4_3, in4_9; + + in1_3 = MUL64(in[1], C3); + in1_9 = MUL64(in[1], C9); + in4_3 = MUL64(in[4], C3); + in4_9 = MUL64(in[4], C9); + + tmp = FRAC_RND(MUL64(in[0], C7) - in1_3 - MUL64(in[2], C11) + + MUL64(in[3], C1) - in4_9 - MUL64(in[5], C5)); + out[0] = tmp; + out[5] = -tmp; + tmp = FRAC_RND(MUL64(in[0] - in[3], C9) - in1_3 + + MUL64(in[2] + in[5], C3) - in4_9); + out[1] = tmp; + out[4] = -tmp; + tmp = FRAC_RND(MUL64(in[0], C11) - in1_9 + MUL64(in[2], C7) - + MUL64(in[3], C5) + in4_3 - MUL64(in[5], C1)); + out[2] = tmp; + out[3] = -tmp; + tmp = FRAC_RND(MUL64(-in[0], C5) + in1_9 + MUL64(in[2], C1) + + MUL64(in[3], C11) - in4_3 - MUL64(in[5], C7)); + out[6] = tmp; + out[11] = tmp; + tmp = FRAC_RND(MUL64(-in[0] + in[3], C3) - in1_9 + + MUL64(in[2] + in[5], C9) + in4_3); + out[7] = tmp; + out[10] = tmp; + tmp = FRAC_RND(-MUL64(in[0], C1) - in1_3 - MUL64(in[2], C5) - + MUL64(in[3], C7) - in4_9 - MUL64(in[5], C11)); + out[8] = tmp; + out[9] = tmp; +} + +#undef C1 +#undef C3 +#undef C5 +#undef C7 +#undef C9 +#undef C11 + +/* cos(pi*i/18) */ +#define C1 FIXR(0.98480775301220805936) +#define C2 FIXR(0.93969262078590838405) +#define C3 FIXR(0.86602540378443864676) +#define C4 FIXR(0.76604444311897803520) +#define C5 FIXR(0.64278760968653932632) +#define C6 FIXR(0.5) +#define C7 FIXR(0.34202014332566873304) +#define C8 FIXR(0.17364817766693034885) + +/* 0.5 / cos(pi*(2*i+1)/36) */ +static const int icos36[9] = { + FIXR(0.50190991877167369479), + FIXR(0.51763809020504152469), + FIXR(0.55168895948124587824), + FIXR(0.61038729438072803416), + FIXR(0.70710678118654752439), + FIXR(0.87172339781054900991), + FIXR(1.18310079157624925896), + FIXR(1.93185165257813657349), + FIXR(5.73685662283492756461), +}; + +static const int icos72[18] = { + /* 0.5 / cos(pi*(2*i+19)/72) */ + FIXR(0.74009361646113053152), + FIXR(0.82133981585229078570), + FIXR(0.93057949835178895673), + FIXR(1.08284028510010010928), + FIXR(1.30656296487637652785), + FIXR(1.66275476171152078719), + FIXR(2.31011315767264929558), + FIXR(3.83064878777019433457), + FIXR(11.46279281302667383546), + + /* 0.5 / cos(pi*(2*(i + 18) +19)/72) */ + FIXR(-0.67817085245462840086), + FIXR(-0.63023620700513223342), + FIXR(-0.59284452371708034528), + FIXR(-0.56369097343317117734), + FIXR(-0.54119610014619698439), + FIXR(-0.52426456257040533932), + FIXR(-0.51213975715725461845), + FIXR(-0.50431448029007636036), + FIXR(-0.50047634258165998492), +}; + +/* using Lee like decomposition followed by hand coded 9 points DCT */ +static void imdct36(int *out, int *in) +{ + int i, j, t0, t1, t2, t3, s0, s1, s2, s3; + int tmp[18], *tmp1, *in1; + int64_t in3_3, in6_6; + + for(i=17;i>=1;i--) + in[i] += in[i-1]; + for(i=17;i>=3;i-=2) + in[i] += in[i-2]; + + for(j=0;j<2;j++) { + tmp1 = tmp + j; + in1 = in + j; + + in3_3 = MUL64(in1[2*3], C3); + in6_6 = MUL64(in1[2*6], C6); + + tmp1[0] = FRAC_RND(MUL64(in1[2*1], C1) + in3_3 + + MUL64(in1[2*5], C5) + MUL64(in1[2*7], C7)); + tmp1[2] = in1[2*0] + FRAC_RND(MUL64(in1[2*2], C2) + + MUL64(in1[2*4], C4) + in6_6 + + MUL64(in1[2*8], C8)); + tmp1[4] = FRAC_RND(MUL64(in1[2*1] - in1[2*5] - in1[2*7], C3)); + tmp1[6] = FRAC_RND(MUL64(in1[2*2] - in1[2*4] - in1[2*8], C6)) - + in1[2*6] + in1[2*0]; + tmp1[8] = FRAC_RND(MUL64(in1[2*1], C5) - in3_3 - + MUL64(in1[2*5], C7) + MUL64(in1[2*7], C1)); + tmp1[10] = in1[2*0] + FRAC_RND(MUL64(-in1[2*2], C8) - + MUL64(in1[2*4], C2) + in6_6 + + MUL64(in1[2*8], C4)); + tmp1[12] = FRAC_RND(MUL64(in1[2*1], C7) - in3_3 + + MUL64(in1[2*5], C1) - + MUL64(in1[2*7], C5)); + tmp1[14] = in1[2*0] + FRAC_RND(MUL64(-in1[2*2], C4) + + MUL64(in1[2*4], C8) + in6_6 - + MUL64(in1[2*8], C2)); + tmp1[16] = in1[2*0] - in1[2*2] + in1[2*4] - in1[2*6] + in1[2*8]; + } + + i = 0; + for(j=0;j<4;j++) { + t0 = tmp[i]; + t1 = tmp[i + 2]; + s0 = t1 + t0; + s2 = t1 - t0; + + t2 = tmp[i + 1]; + t3 = tmp[i + 3]; + s1 = MULL(t3 + t2, icos36[j]); + s3 = MULL(t3 - t2, icos36[8 - j]); + + t0 = MULL(s0 + s1, icos72[9 + 8 - j]); + t1 = MULL(s0 - s1, icos72[8 - j]); + out[18 + 9 + j] = t0; + out[18 + 8 - j] = t0; + out[9 + j] = -t1; + out[8 - j] = t1; + + t0 = MULL(s2 + s3, icos72[9+j]); + t1 = MULL(s2 - s3, icos72[j]); + out[18 + 9 + (8 - j)] = t0; + out[18 + j] = t0; + out[9 + (8 - j)] = -t1; + out[j] = t1; + i += 4; + } + + s0 = tmp[16]; + s1 = MULL(tmp[17], icos36[4]); + t0 = MULL(s0 + s1, icos72[9 + 4]); + t1 = MULL(s0 - s1, icos72[4]); + out[18 + 9 + 4] = t0; + out[18 + 8 - 4] = t0; + out[9 + 4] = -t1; + out[8 - 4] = t1; +} + +/* fast header check for resync */ +static int check_header(uint32_t header) +{ + /* header */ + if ((header & 0xffe00000) != 0xffe00000) + return -1; + /* layer check */ + if (((header >> 17) & 3) == 0) + return -1; + /* bit rate */ + if (((header >> 12) & 0xf) == 0xf) + return -1; + /* frequency */ + if (((header >> 10) & 3) == 3) + return -1; + return 0; +} + +/* header + layer + bitrate + freq + lsf/mpeg25 */ +#define SAME_HEADER_MASK \ + (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19)) + +/* header decoding. MUST check the header before because no + consistency check is done there. Return 1 if free format found and + that the frame size must be computed externally */ +static int decode_header(MPADecodeContext *s, uint32_t header) +{ + int sample_rate, frame_size, mpeg25, padding; + int sample_rate_index, bitrate_index; + if (header & (1<<20)) { + s->lsf = (header & (1<<19)) ? 0 : 1; + mpeg25 = 0; + } else { + s->lsf = 1; + mpeg25 = 1; + } + + s->layer = 4 - ((header >> 17) & 3); + /* extract frequency */ + sample_rate_index = (header >> 10) & 3; + sample_rate = mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate_index += 3 * (s->lsf + mpeg25); + s->sample_rate_index = sample_rate_index; + s->error_protection = ((header >> 16) & 1) ^ 1; + s->sample_rate = sample_rate; + + bitrate_index = (header >> 12) & 0xf; + padding = (header >> 9) & 1; + s->mode = (header >> 6) & 3; + s->mode_ext = (header >> 4) & 3; + + if (s->mode == MPA_MONO) + s->nb_channels = 1; + else + s->nb_channels = 2; + + if (bitrate_index != 0) { + frame_size = mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + s->bit_rate = frame_size * 1000; + switch(s->layer) { + case 1: + frame_size = (frame_size * 12000) / sample_rate; + frame_size = (frame_size + padding) * 4; + break; + case 2: + frame_size = (frame_size * 144000) / sample_rate; + frame_size += padding; + break; + default: + case 3: + frame_size = (frame_size * 144000) / (sample_rate << s->lsf); + frame_size += padding; + break; + } + s->frame_size = frame_size; + } else { + /* if no frame size computed, signal it */ + if (!s->free_format_frame_size) + return 1; + /* free format: compute bitrate and real frame size from the + frame size we extracted by reading the bitstream */ + s->frame_size = s->free_format_frame_size; + switch(s->layer) { + case 1: + s->frame_size += padding * 4; + s->bit_rate = (s->frame_size * sample_rate) / 48000; + break; + case 2: + s->frame_size += padding; + s->bit_rate = (s->frame_size * sample_rate) / 144000; + break; + default: + case 3: + s->frame_size += padding; + s->bit_rate = (s->frame_size * (sample_rate << s->lsf)) / 144000; + break; + } + } + +#if defined(DEBUG) + printf("layer%d, %d Hz, %d kbits/s, ", + s->layer, s->sample_rate, s->bit_rate); + if (s->nb_channels == 2) { + if (s->layer == 3) { + if (s->mode_ext & MODE_EXT_MS_STEREO) + printf("ms-"); + if (s->mode_ext & MODE_EXT_I_STEREO) + printf("i-"); + } + printf("stereo"); + } else { + printf("mono"); + } + printf("\n"); +#endif + return 0; +} + +/* return the number of decoded frames */ +static int mp_decode_layer1(MPADecodeContext *s) +{ + int bound, i, v, n, ch, j, mant; + uint8_t allocation[MPA_MAX_CHANNELS][SBLIMIT]; + uint8_t scale_factors[MPA_MAX_CHANNELS][SBLIMIT]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = SBLIMIT; + + /* allocation bits */ + for(i=0;inb_channels;ch++) { + allocation[ch][i] = get_bits(&s->gb, 4); + } + } + for(i=bound;igb, 4); + } + + /* scale factors */ + for(i=0;inb_channels;ch++) { + if (allocation[ch][i]) + scale_factors[ch][i] = get_bits(&s->gb, 6); + } + } + for(i=bound;igb, 6); + scale_factors[1][i] = get_bits(&s->gb, 6); + } + } + + /* compute samples */ + for(j=0;j<12;j++) { + for(i=0;inb_channels;ch++) { + n = allocation[ch][i]; + if (n) { + mant = get_bits(&s->gb, n + 1); + v = l1_unscale(n, mant, scale_factors[ch][i]); + } else { + v = 0; + } + s->sb_samples[ch][j][i] = v; + } + } + for(i=bound;igb, n + 1); + v = l1_unscale(n, mant, scale_factors[0][i]); + s->sb_samples[0][j][i] = v; + v = l1_unscale(n, mant, scale_factors[1][i]); + s->sb_samples[1][j][i] = v; + } else { + s->sb_samples[0][j][i] = 0; + s->sb_samples[1][j][i] = 0; + } + } + } + return 12; +} + +/* bitrate is in kb/s */ +static int l2_select_table(int bitrate, int nb_channels, int freq, int lsf) +{ + int ch_bitrate, table; + + ch_bitrate = bitrate / nb_channels; + if (!lsf) { + if ((freq == 48000 && ch_bitrate >= 56) || + (ch_bitrate >= 56 && ch_bitrate <= 80)) + table = 0; + else if (freq != 48000 && ch_bitrate >= 96) + table = 1; + else if (freq != 32000 && ch_bitrate <= 48) + table = 2; + else + table = 3; + } else { + table = 4; + } + return table; +} + +static int mp_decode_layer2(MPADecodeContext *s) +{ + int sblimit; /* number of used subbands */ + const unsigned char *alloc_table; + int table, bit_alloc_bits, i, j, ch, bound, v; + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3], *sf; + int scale, qindex, bits, steps, k, l, m, b; + + /* select decoding table */ + table = l2_select_table(s->bit_rate / 1000, s->nb_channels, + s->sample_rate, s->lsf); + sblimit = sblimit_table[table]; + alloc_table = alloc_tables[table]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = sblimit; + +#ifdef DEBUG + printf("bound=%d sblimit=%d\n", bound, sblimit); +#endif + /* parse bit allocation */ + j = 0; + for(i=0;inb_channels;ch++) { + bit_alloc[ch][i] = get_bits(&s->gb, bit_alloc_bits); + } + j += 1 << bit_alloc_bits; + } + for(i=bound;igb, bit_alloc_bits); + bit_alloc[0][i] = v; + bit_alloc[1][i] = v; + j += 1 << bit_alloc_bits; + } + +#ifdef DEBUG + { + for(ch=0;chnb_channels;ch++) { + for(i=0;inb_channels;ch++) { + if (bit_alloc[ch][i]) + scale_code[ch][i] = get_bits(&s->gb, 2); + } + } + + /* scale factors */ + for(i=0;inb_channels;ch++) { + if (bit_alloc[ch][i]) { + sf = scale_factors[ch][i]; + switch(scale_code[ch][i]) { + default: + case 0: + sf[0] = get_bits(&s->gb, 6); + sf[1] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + break; + case 2: + sf[0] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + sf[2] = sf[0]; + break; + case 1: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + break; + case 3: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[2]; + break; + } + } + } + } + +#ifdef DEBUG + for(ch=0;chnb_channels;ch++) { + for(i=0;inb_channels;ch++) { + b = bit_alloc[ch][i]; + if (b) { + scale = scale_factors[ch][i][k]; + qindex = alloc_table[j+b]; + bits = quant_bits[qindex]; + if (bits < 0) { + /* 3 values at the same time */ + v = get_bits(&s->gb, -bits); + steps = quant_steps[qindex]; + s->sb_samples[ch][k * 12 + l + 0][i] = + l2_unscale_group(steps, v % steps, scale); + v = v / steps; + s->sb_samples[ch][k * 12 + l + 1][i] = + l2_unscale_group(steps, v % steps, scale); + v = v / steps; + s->sb_samples[ch][k * 12 + l + 2][i] = + l2_unscale_group(steps, v, scale); + } else { + for(m=0;m<3;m++) { + v = get_bits(&s->gb, bits); + v = l1_unscale(bits - 1, v, scale); + s->sb_samples[ch][k * 12 + l + m][i] = v; + } + } + } else { + s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch][k * 12 + l + 2][i] = 0; + } + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* XXX: find a way to avoid this duplication of code */ + for(i=bound;igb, -bits); + steps = quant_steps[qindex]; + mant = v % steps; + v = v / steps; + s->sb_samples[0][k * 12 + l + 0][i] = + l2_unscale_group(steps, mant, scale0); + s->sb_samples[1][k * 12 + l + 0][i] = + l2_unscale_group(steps, mant, scale1); + mant = v % steps; + v = v / steps; + s->sb_samples[0][k * 12 + l + 1][i] = + l2_unscale_group(steps, mant, scale0); + s->sb_samples[1][k * 12 + l + 1][i] = + l2_unscale_group(steps, mant, scale1); + s->sb_samples[0][k * 12 + l + 2][i] = + l2_unscale_group(steps, v, scale0); + s->sb_samples[1][k * 12 + l + 2][i] = + l2_unscale_group(steps, v, scale1); + } else { + for(m=0;m<3;m++) { + mant = get_bits(&s->gb, bits); + s->sb_samples[0][k * 12 + l + m][i] = + l1_unscale(bits - 1, mant, scale0); + s->sb_samples[1][k * 12 + l + m][i] = + l1_unscale(bits - 1, mant, scale1); + } + } + } else { + s->sb_samples[0][k * 12 + l + 0][i] = 0; + s->sb_samples[0][k * 12 + l + 1][i] = 0; + s->sb_samples[0][k * 12 + l + 2][i] = 0; + s->sb_samples[1][k * 12 + l + 0][i] = 0; + s->sb_samples[1][k * 12 + l + 1][i] = 0; + s->sb_samples[1][k * 12 + l + 2][i] = 0; + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* fill remaining samples to zero */ + for(i=sblimit;inb_channels;ch++) { + s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch][k * 12 + l + 2][i] = 0; + } + } + } + } + return 3 * 12; +} + +/* + * Seek back in the stream for backstep bytes (at most 511 bytes) + */ +static void seek_to_maindata(MPADecodeContext *s, unsigned int backstep) +{ + uint8_t *ptr; + + /* compute current position in stream */ + ptr = (uint8_t *)(s->gb.buffer + (get_bits_count(&s->gb)>>3)); + + /* copy old data before current one */ + ptr -= backstep; + memcpy(ptr, s->inbuf1[s->inbuf_index ^ 1] + + BACKSTEP_SIZE + s->old_frame_size - backstep, backstep); + /* init get bits again */ + init_get_bits(&s->gb, ptr, (s->frame_size + backstep)*8); + + /* prepare next buffer */ + s->inbuf_index ^= 1; + s->inbuf = &s->inbuf1[s->inbuf_index][BACKSTEP_SIZE]; + s->old_frame_size = s->frame_size; +} + +static void lsf_sf_expand(int *slen, + int sf, int n1, int n2, int n3) +{ + if (n3) { + slen[3] = sf % n3; + sf /= n3; + } else { + slen[3] = 0; + } + if (n2) { + slen[2] = sf % n2; + sf /= n2; + } else { + slen[2] = 0; + } + slen[1] = sf % n1; + sf /= n1; + slen[0] = sf; +} + +static void exponents_from_scale_factors(MPADecodeContext *s, + GranuleDef *g, + int16_t *exponents) +{ + const uint8_t *bstab, *pretab; + int len, i, j, k, l, v0, shift, gain, gains[3]; + int16_t *exp_ptr; + + exp_ptr = exponents; + gain = g->global_gain - 210; + shift = g->scalefac_scale + 1; + + bstab = band_size_long[s->sample_rate_index]; + pretab = mpa_pretab[g->preflag]; + for(i=0;ilong_end;i++) { + v0 = gain - ((g->scale_factors[i] + pretab[i]) << shift); + len = bstab[i]; + for(j=len;j>0;j--) + *exp_ptr++ = v0; + } + + if (g->short_start < 13) { + bstab = band_size_short[s->sample_rate_index]; + gains[0] = gain - (g->subblock_gain[0] << 3); + gains[1] = gain - (g->subblock_gain[1] << 3); + gains[2] = gain - (g->subblock_gain[2] << 3); + k = g->long_end; + for(i=g->short_start;i<13;i++) { + len = bstab[i]; + for(l=0;l<3;l++) { + v0 = gains[l] - (g->scale_factors[k++] << shift); + for(j=len;j>0;j--) + *exp_ptr++ = v0; + } + } + } +} + +/* handle n = 0 too */ +static int get_bitsz(GetBitContext *s, int n) +{ + if (n == 0) + return 0; + else + return get_bits(s, n); +} + +static int huffman_decode(MPADecodeContext *s, GranuleDef *g, + int16_t *exponents, int end_pos) +{ + int s_index; + int linbits, code, x, y, l, v, i, j, k, pos; + GetBitContext last_gb; + VLC *vlc; + uint8_t *code_table; + + /* low frequencies (called big values) */ + s_index = 0; + for(i=0;i<3;i++) { + j = g->region_size[i]; + if (j == 0) + continue; + /* select vlc table */ + k = g->table_select[i]; + l = mpa_huff_data[k][0]; + linbits = mpa_huff_data[k][1]; + vlc = &huff_vlc[l]; + code_table = huff_code_table[l]; + + /* read huffcode and compute each couple */ + for(;j>0;j--) { + if (get_bits_count(&s->gb) >= end_pos) + break; + if (code_table) { + code = get_vlc(&s->gb, vlc); + if (code < 0) + return -1; + y = code_table[code]; + x = y >> 4; + y = y & 0x0f; + } else { + x = 0; + y = 0; + } +#ifdef DEBUG + printf("region=%d n=%d x=%d y=%d exp=%d\n", + i, g->region_size[i] - j, x, y, exponents[s_index]); +#endif + if (x) { + if (x == 15) + x += get_bitsz(&s->gb, linbits); + v = l3_unscale(x, exponents[s_index]); + if (get_bits(&s->gb, 1)) + v = -v; + } else { + v = 0; + } + g->sb_hybrid[s_index++] = v; + if (y) { + if (y == 15) + y += get_bitsz(&s->gb, linbits); + v = l3_unscale(y, exponents[s_index]); + if (get_bits(&s->gb, 1)) + v = -v; + } else { + v = 0; + } + g->sb_hybrid[s_index++] = v; + } + } + + /* high frequencies */ + vlc = &huff_quad_vlc[g->count1table_select]; + last_gb.buffer = NULL; + while (s_index <= 572) { + pos = get_bits_count(&s->gb); + if (pos >= end_pos) { + if (pos > end_pos && last_gb.buffer != NULL) { + /* some encoders generate an incorrect size for this + part. We must go back into the data */ + s_index -= 4; + s->gb = last_gb; + } + break; + } + last_gb= s->gb; + + code = get_vlc(&s->gb, vlc); +#ifdef DEBUG + printf("t=%d code=%d\n", g->count1table_select, code); +#endif + if (code < 0) + return -1; + for(i=0;i<4;i++) { + if (code & (8 >> i)) { + /* non zero value. Could use a hand coded function for + 'one' value */ + v = l3_unscale(1, exponents[s_index]); + if(get_bits(&s->gb, 1)) + v = -v; + } else { + v = 0; + } + g->sb_hybrid[s_index++] = v; + } + } + while (s_index < 576) + g->sb_hybrid[s_index++] = 0; + return 0; +} + +/* Reorder short blocks from bitstream order to interleaved order. It + would be faster to do it in parsing, but the code would be far more + complicated */ +static void reorder_block(MPADecodeContext *s, GranuleDef *g) +{ + int i, j, k, len; + int32_t *ptr, *dst, *ptr1; + int32_t tmp[576]; + + if (g->block_type != 2) + return; + + if (g->switch_point) { + if (s->sample_rate_index != 8) { + ptr = g->sb_hybrid + 36; + } else { + ptr = g->sb_hybrid + 48; + } + } else { + ptr = g->sb_hybrid; + } + + for(i=g->short_start;i<13;i++) { + len = band_size_short[s->sample_rate_index][i]; + ptr1 = ptr; + for(k=0;k<3;k++) { + dst = tmp + k; + for(j=len;j>0;j--) { + *dst = *ptr++; + dst += 3; + } + } + memcpy(ptr1, tmp, len * 3 * sizeof(int32_t)); + } +} + +#define ISQRT2 FIXR(0.70710678118654752440) + +static void compute_stereo(MPADecodeContext *s, + GranuleDef *g0, GranuleDef *g1) +{ + int i, j, k, l; + int32_t v1, v2; + int sf_max, tmp0, tmp1, sf, len, non_zero_found; + int32_t (*is_tab)[16]; + int32_t *tab0, *tab1; + int non_zero_found_short[3]; + + /* intensity stereo */ + if (s->mode_ext & MODE_EXT_I_STEREO) { + if (!s->lsf) { + is_tab = is_table; + sf_max = 7; + } else { + is_tab = is_table_lsf[g1->scalefac_compress & 1]; + sf_max = 16; + } + + tab0 = g0->sb_hybrid + 576; + tab1 = g1->sb_hybrid + 576; + + non_zero_found_short[0] = 0; + non_zero_found_short[1] = 0; + non_zero_found_short[2] = 0; + k = (13 - g1->short_start) * 3 + g1->long_end - 3; + for(i = 12;i >= g1->short_start;i--) { + /* for last band, use previous scale factor */ + if (i != 11) + k -= 3; + len = band_size_short[s->sample_rate_index][i]; + for(l=2;l>=0;l--) { + tab0 -= len; + tab1 -= len; + if (!non_zero_found_short[l]) { + /* test if non zero band. if so, stop doing i-stereo */ + for(j=0;jscale_factors[k + l]; + if (sf >= sf_max) + goto found1; + + v1 = is_tab[0][sf]; + v2 = is_tab[1][sf]; + for(j=0;jmode_ext & MODE_EXT_MS_STEREO) { + /* lower part of the spectrum : do ms stereo + if enabled */ + for(j=0;jlong_end - 1;i >= 0;i--) { + len = band_size_long[s->sample_rate_index][i]; + tab0 -= len; + tab1 -= len; + /* test if non zero band. if so, stop doing i-stereo */ + if (!non_zero_found) { + for(j=0;jscale_factors[k]; + if (sf >= sf_max) + goto found2; + v1 = is_tab[0][sf]; + v2 = is_tab[1][sf]; + for(j=0;jmode_ext & MODE_EXT_MS_STEREO) { + /* lower part of the spectrum : do ms stereo + if enabled */ + for(j=0;jmode_ext & MODE_EXT_MS_STEREO) { + /* ms stereo ONLY */ + /* NOTE: the 1/sqrt(2) normalization factor is included in the + global gain */ + tab0 = g0->sb_hybrid; + tab1 = g1->sb_hybrid; + for(i=0;i<576;i++) { + tmp0 = tab0[i]; + tmp1 = tab1[i]; + tab0[i] = tmp0 + tmp1; + tab1[i] = tmp0 - tmp1; + } + } +} + +static void compute_antialias(MPADecodeContext *s, + GranuleDef *g) +{ + int32_t *ptr, *p0, *p1, *csa; + int n, tmp0, tmp1, i, j; + + /* we antialias only "long" bands */ + if (g->block_type == 2) { + if (!g->switch_point) + return; + /* XXX: check this for 8000Hz case */ + n = 1; + } else { + n = SBLIMIT - 1; + } + + ptr = g->sb_hybrid + 18; + for(i = n;i > 0;i--) { + p0 = ptr - 1; + p1 = ptr; + csa = &csa_table[0][0]; + for(j=0;j<8;j++) { + tmp0 = *p0; + tmp1 = *p1; + *p0 = FRAC_RND(MUL64(tmp0, csa[0]) - MUL64(tmp1, csa[1])); + *p1 = FRAC_RND(MUL64(tmp0, csa[1]) + MUL64(tmp1, csa[0])); + p0--; + p1++; + csa += 2; + } + ptr += 18; + } +} + +static void compute_imdct(MPADecodeContext *s, + GranuleDef *g, + int32_t *sb_samples, + int32_t *mdct_buf) +{ + int32_t *ptr, *win, *win1, *buf, *buf2, *out_ptr, *ptr1; + int32_t in[6]; + int32_t out[36]; + int32_t out2[12]; + int i, j, k, mdct_long_end, v, sblimit; + + /* find last non zero block */ + ptr = g->sb_hybrid + 576; + ptr1 = g->sb_hybrid + 2 * 18; + while (ptr >= ptr1) { + ptr -= 6; + v = ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5]; + if (v != 0) + break; + } + sblimit = ((ptr - g->sb_hybrid) / 18) + 1; + + if (g->block_type == 2) { + /* XXX: check for 8000 Hz */ + if (g->switch_point) + mdct_long_end = 2; + else + mdct_long_end = 0; + } else { + mdct_long_end = sblimit; + } + + buf = mdct_buf; + ptr = g->sb_hybrid; + for(j=0;jswitch_point && j < 2) + win1 = mdct_win[0]; + else + win1 = mdct_win[g->block_type]; + /* select frequency inversion */ + win = win1 + ((4 * 36) & -(j & 1)); + for(i=0;i<18;i++) { + *out_ptr = MULL(out[i], win[i]) + buf[i]; + buf[i] = MULL(out[i + 18], win[i + 18]); + out_ptr += SBLIMIT; + } + ptr += 18; + buf += 18; + } + for(j=mdct_long_end;jlsf) { + main_data_begin = get_bits(&s->gb, 8); + if (s->nb_channels == 2) + private_bits = get_bits(&s->gb, 2); + else + private_bits = get_bits(&s->gb, 1); + nb_granules = 1; + } else { + main_data_begin = get_bits(&s->gb, 9); + if (s->nb_channels == 2) + private_bits = get_bits(&s->gb, 3); + else + private_bits = get_bits(&s->gb, 5); + nb_granules = 2; + for(ch=0;chnb_channels;ch++) { + granules[ch][0].scfsi = 0; /* all scale factors are transmitted */ + granules[ch][1].scfsi = get_bits(&s->gb, 4); + } + } + + for(gr=0;grnb_channels;ch++) { +#ifdef DEBUG + printf("gr=%d ch=%d: side_info\n", gr, ch); +#endif + g = &granules[ch][gr]; + g->part2_3_length = get_bits(&s->gb, 12); + g->big_values = get_bits(&s->gb, 9); + g->global_gain = get_bits(&s->gb, 8); + /* if MS stereo only is selected, we precompute the + 1/sqrt(2) renormalization factor */ + if ((s->mode_ext & (MODE_EXT_MS_STEREO | MODE_EXT_I_STEREO)) == + MODE_EXT_MS_STEREO) + g->global_gain -= 2; + if (s->lsf) + g->scalefac_compress = get_bits(&s->gb, 9); + else + g->scalefac_compress = get_bits(&s->gb, 4); + blocksplit_flag = get_bits(&s->gb, 1); + if (blocksplit_flag) { + g->block_type = get_bits(&s->gb, 2); + if (g->block_type == 0) + return -1; + g->switch_point = get_bits(&s->gb, 1); + for(i=0;i<2;i++) + g->table_select[i] = get_bits(&s->gb, 5); + for(i=0;i<3;i++) + g->subblock_gain[i] = get_bits(&s->gb, 3); + /* compute huffman coded region sizes */ + if (g->block_type == 2) + g->region_size[0] = (36 / 2); + else { + if (s->sample_rate_index <= 2) + g->region_size[0] = (36 / 2); + else if (s->sample_rate_index != 8) + g->region_size[0] = (54 / 2); + else + g->region_size[0] = (108 / 2); + } + g->region_size[1] = (576 / 2); + } else { + int region_address1, region_address2, l; + g->block_type = 0; + g->switch_point = 0; + for(i=0;i<3;i++) + g->table_select[i] = get_bits(&s->gb, 5); + /* compute huffman coded region sizes */ + region_address1 = get_bits(&s->gb, 4); + region_address2 = get_bits(&s->gb, 3); +#ifdef DEBUG + printf("region1=%d region2=%d\n", + region_address1, region_address2); +#endif + g->region_size[0] = + band_index_long[s->sample_rate_index][region_address1 + 1] >> 1; + l = region_address1 + region_address2 + 2; + /* should not overflow */ + if (l > 22) + l = 22; + g->region_size[1] = + band_index_long[s->sample_rate_index][l] >> 1; + } + /* convert region offsets to region sizes and truncate + size to big_values */ + g->region_size[2] = (576 / 2); + j = 0; + for(i=0;i<3;i++) { + k = g->region_size[i]; + if (k > g->big_values) + k = g->big_values; + g->region_size[i] = k - j; + j = k; + } + + /* compute band indexes */ + if (g->block_type == 2) { + if (g->switch_point) { + /* if switched mode, we handle the 36 first samples as + long blocks. For 8000Hz, we handle the 48 first + exponents as long blocks (XXX: check this!) */ + if (s->sample_rate_index <= 2) + g->long_end = 8; + else if (s->sample_rate_index != 8) + g->long_end = 6; + else + g->long_end = 4; /* 8000 Hz */ + + if (s->sample_rate_index != 8) + g->short_start = 3; + else + g->short_start = 2; + } else { + g->long_end = 0; + g->short_start = 0; + } + } else { + g->short_start = 13; + g->long_end = 22; + } + + g->preflag = 0; + if (!s->lsf) + g->preflag = get_bits(&s->gb, 1); + g->scalefac_scale = get_bits(&s->gb, 1); + g->count1table_select = get_bits(&s->gb, 1); +#ifdef DEBUG + printf("block_type=%d switch_point=%d\n", + g->block_type, g->switch_point); +#endif + } + } + + /* now we get bits from the main_data_begin offset */ +#ifdef DEBUG + printf("seekback: %d\n", main_data_begin); +#endif + seek_to_maindata(s, main_data_begin); + + for(gr=0;grnb_channels;ch++) { + g = &granules[ch][gr]; + + bits_pos = get_bits_count(&s->gb); + + if (!s->lsf) { + uint8_t *sc; + int slen, slen1, slen2; + + /* MPEG1 scale factors */ + slen1 = slen_table[0][g->scalefac_compress]; + slen2 = slen_table[1][g->scalefac_compress]; +#ifdef DEBUG + printf("slen1=%d slen2=%d\n", slen1, slen2); +#endif + if (g->block_type == 2) { + n = g->switch_point ? 17 : 18; + j = 0; + for(i=0;iscale_factors[j++] = get_bitsz(&s->gb, slen1); + for(i=0;i<18;i++) + g->scale_factors[j++] = get_bitsz(&s->gb, slen2); + for(i=0;i<3;i++) + g->scale_factors[j++] = 0; + } else { + sc = granules[ch][0].scale_factors; + j = 0; + for(k=0;k<4;k++) { + n = (k == 0 ? 6 : 5); + if ((g->scfsi & (0x8 >> k)) == 0) { + slen = (k < 2) ? slen1 : slen2; + for(i=0;iscale_factors[j++] = get_bitsz(&s->gb, slen); + } else { + /* simply copy from last granule */ + for(i=0;iscale_factors[j] = sc[j]; + j++; + } + } + } + g->scale_factors[j++] = 0; + } +#if defined(DEBUG) + { + printf("scfsi=%x gr=%d ch=%d scale_factors:\n", + g->scfsi, gr, ch); + for(i=0;iscale_factors[i]); + printf("\n"); + } +#endif + } else { + int tindex, tindex2, slen[4], sl, sf; + + /* LSF scale factors */ + if (g->block_type == 2) { + tindex = g->switch_point ? 2 : 1; + } else { + tindex = 0; + } + sf = g->scalefac_compress; + if ((s->mode_ext & MODE_EXT_I_STEREO) && ch == 1) { + /* intensity stereo case */ + sf >>= 1; + if (sf < 180) { + lsf_sf_expand(slen, sf, 6, 6, 0); + tindex2 = 3; + } else if (sf < 244) { + lsf_sf_expand(slen, sf - 180, 4, 4, 0); + tindex2 = 4; + } else { + lsf_sf_expand(slen, sf - 244, 3, 0, 0); + tindex2 = 5; + } + } else { + /* normal case */ + if (sf < 400) { + lsf_sf_expand(slen, sf, 5, 4, 4); + tindex2 = 0; + } else if (sf < 500) { + lsf_sf_expand(slen, sf - 400, 5, 4, 0); + tindex2 = 1; + } else { + lsf_sf_expand(slen, sf - 500, 3, 0, 0); + tindex2 = 2; + g->preflag = 1; + } + } + + j = 0; + for(k=0;k<4;k++) { + n = lsf_nsf_table[tindex2][tindex][k]; + sl = slen[k]; + for(i=0;iscale_factors[j++] = get_bitsz(&s->gb, sl); + } + /* XXX: should compute exact size */ + for(;j<40;j++) + g->scale_factors[j] = 0; +#if defined(DEBUG) + { + printf("gr=%d ch=%d scale_factors:\n", + gr, ch); + for(i=0;i<40;i++) + printf(" %d", g->scale_factors[i]); + printf("\n"); + } +#endif + } + + exponents_from_scale_factors(s, g, exponents); + + /* read Huffman coded residue */ + if (huffman_decode(s, g, exponents, + bits_pos + g->part2_3_length) < 0) + return -1; + + /* skip extension bits */ + bits_left = g->part2_3_length - (get_bits_count(&s->gb) - bits_pos); + if (bits_left < 0) { +#ifdef DEBUG + printf("bits_left=%d\n", bits_left); +#endif + return -1; + } + while (bits_left >= 16) { + skip_bits(&s->gb, 16); + bits_left -= 16; + } + if (bits_left > 0) + skip_bits(&s->gb, bits_left); + } /* ch */ + + if (s->nb_channels == 2) + compute_stereo(s, &granules[0][gr], &granules[1][gr]); + + for(ch=0;chnb_channels;ch++) { + g = &granules[ch][gr]; + + reorder_block(s, g); + compute_antialias(s, g); + compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]); + } + } /* gr */ + return nb_granules * 18; +} + +static int mp_decode_frame(MPADecodeContext *s, + int16_t *samples) +{ + int i, nb_frames, ch; + int16_t *samples_ptr; + + init_get_bits(&s->gb, s->inbuf + HEADER_SIZE, + (s->inbuf_ptr - s->inbuf - HEADER_SIZE)*8); + + /* skip error protection field */ + if (s->error_protection) + get_bits(&s->gb, 16); + +#ifdef DEBUG + printf("frame %d:\n", s->frame_count); +#endif + switch(s->layer) { + case 1: + nb_frames = mp_decode_layer1(s); + break; + case 2: + nb_frames = mp_decode_layer2(s); + break; + case 3: + default: + nb_frames = mp_decode_layer3(s); + break; + } +#if defined(DEBUG) + for(i=0;inb_channels;ch++) { + int j; + printf("%d-%d:", i, ch); + for(j=0;jsb_samples[ch][i][j] / FRAC_ONE); + printf("\n"); + } + } +#endif + /* apply the synthesis filter */ + for(ch=0;chnb_channels;ch++) { + samples_ptr = samples + ch; + for(i=0;inb_channels, + s->sb_samples[ch][i]); + samples_ptr += 32 * s->nb_channels; + } + } +#ifdef DEBUG + s->frame_count++; +#endif + return nb_frames * 32 * sizeof(short) * s->nb_channels; +} + +int mpaudec_decode_frame(MPAuDecContext * mpctx, + void *data, int *data_size, + const uint8_t * buf, int buf_size) +{ + MPADecodeContext *s; + const uint8_t *buf_ptr = buf; + int out_size = 0; + int16_t *out_samples = data; + assert(mpctx != NULL); + assert(mpctx->priv_data != NULL); + s = mpctx->priv_data; + + while (buf_size > 0 && out_size == 0) { + uint32_t header; + uint32_t free_format_next_header = 0; + int len = s->inbuf_ptr - s->inbuf; + if (s->frame_size == 0) { + /* no header seen : find one. We need at least HEADER_SIZE + bytes to parse it */ + len = HEADER_SIZE - len; + if (len > buf_size) + len = buf_size; + if (len > 0) { + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + buf_size -= len; + s->inbuf_ptr += len; + } + if ((s->inbuf_ptr - s->inbuf) >= HEADER_SIZE) { + header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | + (s->inbuf[2] << 8) | s->inbuf[3]; + + if (check_header(header) < 0) { + /* no sync found : move by one byte (inefficient, but simple!) */ + memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); + s->inbuf_ptr--; +#ifdef DEBUG + printf("skip %x\n", header); +#endif + /* reset free format frame size to give a chance + to get a new bitrate */ + s->free_format_frame_size = 0; + } else { + if (decode_header(s, header) == 1) { + /* free format: prepare to compute frame size */ + s->frame_size = -1; + } + /* update codec info */ + mpctx->sample_rate = s->sample_rate; + mpctx->channels = s->nb_channels; + mpctx->bit_rate = s->bit_rate; + mpctx->layer = s->layer; + switch(s->layer) { + case 1: + mpctx->frame_size = 384; + break; + case 2: + mpctx->frame_size = 1152; + break; + case 3: + if (s->lsf) + mpctx->frame_size = 576; + else + mpctx->frame_size = 1152; + break; + } + } + } + } else if (s->frame_size == -1) { + /* free format : find next sync to compute frame size */ + len = MPA_MAX_CODED_FRAME_SIZE - len; + if (len > buf_size) + len = buf_size; + if (len == 0) { + /* frame too long: resync */ + s->frame_size = 0; + memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); + s->inbuf_ptr--; + } else { + uint8_t *p, *pend; + uint32_t header1; + int padding; + + memcpy(s->inbuf_ptr, buf_ptr, len); + /* check for header */ + p = s->inbuf_ptr - 3; + pend = s->inbuf_ptr + len - 4; + while (p <= pend && free_format_next_header == 0) { + header = (p[0] << 24) | (p[1] << 16) | + (p[2] << 8) | p[3]; + header1 = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | + (s->inbuf[2] << 8) | s->inbuf[3]; + /* check with high probability that we have a + valid header */ + if ((header & SAME_HEADER_MASK) == + (header1 & SAME_HEADER_MASK)) { + /* header found: update pointers */ + len = (p + 4) - s->inbuf_ptr; + buf_ptr += len; + buf_size -= len; + s->inbuf_ptr = p; + free_format_next_header = header; + /* compute frame size */ + s->free_format_frame_size = s->inbuf_ptr - s->inbuf; + padding = (header1 >> 9) & 1; + if (s->layer == 1) + s->free_format_frame_size -= padding * 4; + else + s->free_format_frame_size -= padding; +#ifdef DEBUG + printf("free frame size=%d padding=%d\n", + s->free_format_frame_size, padding); +#endif + decode_header(s, header1); + } else + p++; + } + if (free_format_next_header == 0) { + /* not found: simply increase pointers */ + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + } + } + } else if (len < s->frame_size) { + if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE) + s->frame_size = MPA_MAX_CODED_FRAME_SIZE; + len = s->frame_size - len; + if (len > buf_size) + len = buf_size; + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + } + if (s->frame_size > 0 && + (s->inbuf_ptr - s->inbuf) >= s->frame_size) { + mpctx->coded_frame_size = s->frame_size; + if (mpctx->parse_only) { + /* simply return the frame data */ + *(uint8_t **)data = s->inbuf; + out_size = s->inbuf_ptr - s->inbuf; + } else { + out_size = mp_decode_frame(s, out_samples); + } + if (free_format_next_header != 0) { + s->inbuf[0] = free_format_next_header >> 24; + s->inbuf[1] = free_format_next_header >> 16; + s->inbuf[2] = free_format_next_header >> 8; + s->inbuf[3] = free_format_next_header; + s->inbuf_ptr = s->inbuf + 4; + } else + s->inbuf_ptr = s->inbuf; + s->frame_size = 0; + } + } + *data_size = out_size; + return buf_ptr - buf; +} + +void mpaudec_clear(MPAuDecContext *mpctx) +{ + assert(mpctx != NULL); + free(mpctx->priv_data); + memset(mpctx, 0, sizeof(MPAuDecContext)); +} diff --git a/plugins/mp3Decoder/mpaudec/mpaudec.h b/plugins/mp3Decoder/mpaudec/mpaudec.h new file mode 100644 index 0000000..06205ba --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/mpaudec.h @@ -0,0 +1,34 @@ +/* Portions based on avcodec.h from libavcodec. */ + +#ifndef MPAUDEC_H +#define MPAUDEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* in bytes */ +#define MPAUDEC_MAX_AUDIO_FRAME_SIZE 4608 + +typedef struct MPAuDecContext { + int bit_rate; + int layer; + int sample_rate; + int channels; + int frame_size; + void *priv_data; + int parse_only; + int coded_frame_size; +} MPAuDecContext; + +int mpaudec_init(MPAuDecContext *mpctx); +int mpaudec_decode_frame(MPAuDecContext * mpctx, + void *data, int *data_size, + const unsigned char * buf, int buf_size); +void mpaudec_clear(MPAuDecContext *mpctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPAUDEC_H */ diff --git a/plugins/mp3Decoder/mpaudec/mpaudectab.h b/plugins/mp3Decoder/mpaudec/mpaudectab.h new file mode 100644 index 0000000..7db90e1 --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/mpaudectab.h @@ -0,0 +1,772 @@ +/* Modified slightly by Matt Campbell for the + stand-alone mpaudec library. Based on mpegaudiodectab.h from libavcodec. */ + +static const uint16_t mpa_bitrate_tab[2][3][15] = { + { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} + } +}; + +static const uint16_t mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +/*******************************************************/ +/* half mpeg encoding window (full precision) */ +static const int32_t mpa_enwindow[257] = { + 0, -1, -1, -1, -1, -1, -1, -2, + -2, -2, -2, -3, -3, -4, -4, -5, + -5, -6, -7, -7, -8, -9, -10, -11, + -13, -14, -16, -17, -19, -21, -24, -26, + -29, -31, -35, -38, -41, -45, -49, -53, + -58, -63, -68, -73, -79, -85, -91, -97, + -104, -111, -117, -125, -132, -139, -147, -154, + -161, -169, -176, -183, -190, -196, -202, -208, + 213, 218, 222, 225, 227, 228, 228, 227, + 224, 221, 215, 208, 200, 189, 177, 163, + 146, 127, 106, 83, 57, 29, -2, -36, + -72, -111, -153, -197, -244, -294, -347, -401, + -459, -519, -581, -645, -711, -779, -848, -919, + -991, -1064, -1137, -1210, -1283, -1356, -1428, -1498, + -1567, -1634, -1698, -1759, -1817, -1870, -1919, -1962, + -2001, -2032, -2057, -2075, -2085, -2087, -2080, -2063, + 2037, 2000, 1952, 1893, 1822, 1739, 1644, 1535, + 1414, 1280, 1131, 970, 794, 605, 402, 185, + -45, -288, -545, -814, -1095, -1388, -1692, -2006, + -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, + -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, + -7910, -8209, -8491, -8755, -8998, -9219, -9416, -9585, + -9727, -9838, -9916, -9959, -9966, -9935, -9863, -9750, + -9592, -9389, -9139, -8840, -8492, -8092, -7640, -7134, + 6574, 5959, 5288, 4561, 3776, 2935, 2037, 1082, + 70, -998, -2122, -3300, -4533, -5818, -7154, -8540, + -9975,-11455,-12980,-14548,-16155,-17799,-19478,-21189, +-22929,-24694,-26482,-28289,-30112,-31947,-33791,-35640, +-37489,-39336,-41176,-43006,-44821,-46617,-48390,-50137, +-51853,-53534,-55178,-56778,-58333,-59838,-61289,-62684, +-64019,-65290,-66494,-67629,-68692,-69679,-70590,-71420, +-72169,-72835,-73415,-73908,-74313,-74630,-74856,-74992, + 75038, +}; + +/*******************************************************/ +/* layer 2 tables */ + +static const int sblimit_table[5] = { 27 , 30 , 8, 12 , 30 }; + +static const int quant_steps[17] = { + 3, 5, 7, 9, 15, + 31, 63, 127, 255, 511, + 1023, 2047, 4095, 8191, 16383, + 32767, 65535 +}; + +/* we use a negative value if grouped */ +static const int quant_bits[17] = { + -5, -7, 3, -10, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, + 15, 16 +}; + +/* encoding tables which give the quantization index. Note how it is + possible to store them efficiently ! */ +static const unsigned char alloc_table_0[] = { + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, +}; + +static const unsigned char alloc_table_1[] = { + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, +}; + +static const unsigned char alloc_table_2[] = { + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, +}; + +static const unsigned char alloc_table_3[] = { + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, +}; + +static const unsigned char alloc_table_4[] = { + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, +}; + +static const unsigned char *alloc_tables[5] = +{ alloc_table_0, alloc_table_1, alloc_table_2, alloc_table_3, alloc_table_4, }; + +/*******************************************************/ +/* layer 3 tables */ + +/* layer3 scale factor size */ +static const uint8_t slen_table[2][16] = { + { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }, + { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }, +}; + +/* number of lsf scale factors for a given size */ +static const uint8_t lsf_nsf_table[6][3][4] = { + { { 6, 5, 5, 5 }, { 9, 9, 9, 9 }, { 6, 9, 9, 9 } }, + { { 6, 5, 7, 3 }, { 9, 9, 12, 6 }, { 6, 9, 12, 6 } }, + { { 11, 10, 0, 0 }, { 18, 18, 0, 0 }, { 15, 18, 0, 0 } }, + { { 7, 7, 7, 0 }, { 12, 12, 12, 0 }, { 6, 15, 12, 0 } }, + { { 6, 6, 6, 3 }, { 12, 9, 9, 6 }, { 6, 12, 9, 6 } }, + { { 8, 8, 5, 0 }, { 15, 12, 9, 0 }, { 6, 18, 9, 0 } }, +}; + +/* mpegaudio layer 3 huffman tables */ + +static const uint16_t mpa_huffcodes_1[4] = { + 0x0001, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_1[4] = { + 1, 3, 2, 3, +}; + +static const uint16_t mpa_huffcodes_2[9] = { + 0x0001, 0x0002, 0x0001, 0x0003, 0x0001, 0x0001, 0x0003, 0x0002, + 0x0000, +}; + +static const uint8_t mpa_huffbits_2[9] = { + 1, 3, 6, 3, 3, 5, 5, 5, + 6, +}; + +static const uint16_t mpa_huffcodes_3[9] = { + 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, + 0x0000, +}; + +static const uint8_t mpa_huffbits_3[9] = { + 2, 2, 6, 3, 2, 5, 5, 5, + 6, +}; + +static const uint16_t mpa_huffcodes_5[16] = { + 0x0001, 0x0002, 0x0006, 0x0005, 0x0003, 0x0001, 0x0004, 0x0004, + 0x0007, 0x0005, 0x0007, 0x0001, 0x0006, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_5[16] = { + 1, 3, 6, 7, 3, 3, 6, 7, + 6, 6, 7, 8, 7, 6, 7, 8, +}; + +static const uint16_t mpa_huffcodes_6[16] = { + 0x0007, 0x0003, 0x0005, 0x0001, 0x0006, 0x0002, 0x0003, 0x0002, + 0x0005, 0x0004, 0x0004, 0x0001, 0x0003, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_6[16] = { + 3, 3, 5, 7, 3, 2, 4, 5, + 4, 4, 5, 6, 6, 5, 6, 7, +}; + +static const uint16_t mpa_huffcodes_7[36] = { + 0x0001, 0x0002, 0x000a, 0x0013, 0x0010, 0x000a, 0x0003, 0x0003, + 0x0007, 0x000a, 0x0005, 0x0003, 0x000b, 0x0004, 0x000d, 0x0011, + 0x0008, 0x0004, 0x000c, 0x000b, 0x0012, 0x000f, 0x000b, 0x0002, + 0x0007, 0x0006, 0x0009, 0x000e, 0x0003, 0x0001, 0x0006, 0x0004, + 0x0005, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_7[36] = { + 1, 3, 6, 8, 8, 9, 3, 4, + 6, 7, 7, 8, 6, 5, 7, 8, + 8, 9, 7, 7, 8, 9, 9, 9, + 7, 7, 8, 9, 9, 10, 8, 8, + 9, 10, 10, 10, +}; + +static const uint16_t mpa_huffcodes_8[36] = { + 0x0003, 0x0004, 0x0006, 0x0012, 0x000c, 0x0005, 0x0005, 0x0001, + 0x0002, 0x0010, 0x0009, 0x0003, 0x0007, 0x0003, 0x0005, 0x000e, + 0x0007, 0x0003, 0x0013, 0x0011, 0x000f, 0x000d, 0x000a, 0x0004, + 0x000d, 0x0005, 0x0008, 0x000b, 0x0005, 0x0001, 0x000c, 0x0004, + 0x0004, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_8[36] = { + 2, 3, 6, 8, 8, 9, 3, 2, + 4, 8, 8, 8, 6, 4, 6, 8, + 8, 9, 8, 8, 8, 9, 9, 10, + 8, 7, 8, 9, 10, 10, 9, 8, + 9, 9, 11, 11, +}; + +static const uint16_t mpa_huffcodes_9[36] = { + 0x0007, 0x0005, 0x0009, 0x000e, 0x000f, 0x0007, 0x0006, 0x0004, + 0x0005, 0x0005, 0x0006, 0x0007, 0x0007, 0x0006, 0x0008, 0x0008, + 0x0008, 0x0005, 0x000f, 0x0006, 0x0009, 0x000a, 0x0005, 0x0001, + 0x000b, 0x0007, 0x0009, 0x0006, 0x0004, 0x0001, 0x000e, 0x0004, + 0x0006, 0x0002, 0x0006, 0x0000, +}; + +static const uint8_t mpa_huffbits_9[36] = { + 3, 3, 5, 6, 8, 9, 3, 3, + 4, 5, 6, 8, 4, 4, 5, 6, + 7, 8, 6, 5, 6, 7, 7, 8, + 7, 6, 7, 7, 8, 9, 8, 7, + 8, 8, 9, 9, +}; + +static const uint16_t mpa_huffcodes_10[64] = { + 0x0001, 0x0002, 0x000a, 0x0017, 0x0023, 0x001e, 0x000c, 0x0011, + 0x0003, 0x0003, 0x0008, 0x000c, 0x0012, 0x0015, 0x000c, 0x0007, + 0x000b, 0x0009, 0x000f, 0x0015, 0x0020, 0x0028, 0x0013, 0x0006, + 0x000e, 0x000d, 0x0016, 0x0022, 0x002e, 0x0017, 0x0012, 0x0007, + 0x0014, 0x0013, 0x0021, 0x002f, 0x001b, 0x0016, 0x0009, 0x0003, + 0x001f, 0x0016, 0x0029, 0x001a, 0x0015, 0x0014, 0x0005, 0x0003, + 0x000e, 0x000d, 0x000a, 0x000b, 0x0010, 0x0006, 0x0005, 0x0001, + 0x0009, 0x0008, 0x0007, 0x0008, 0x0004, 0x0004, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_10[64] = { + 1, 3, 6, 8, 9, 9, 9, 10, + 3, 4, 6, 7, 8, 9, 8, 8, + 6, 6, 7, 8, 9, 10, 9, 9, + 7, 7, 8, 9, 10, 10, 9, 10, + 8, 8, 9, 10, 10, 10, 10, 10, + 9, 9, 10, 10, 11, 11, 10, 11, + 8, 8, 9, 10, 10, 10, 11, 11, + 9, 8, 9, 10, 10, 11, 11, 11, +}; + +static const uint16_t mpa_huffcodes_11[64] = { + 0x0003, 0x0004, 0x000a, 0x0018, 0x0022, 0x0021, 0x0015, 0x000f, + 0x0005, 0x0003, 0x0004, 0x000a, 0x0020, 0x0011, 0x000b, 0x000a, + 0x000b, 0x0007, 0x000d, 0x0012, 0x001e, 0x001f, 0x0014, 0x0005, + 0x0019, 0x000b, 0x0013, 0x003b, 0x001b, 0x0012, 0x000c, 0x0005, + 0x0023, 0x0021, 0x001f, 0x003a, 0x001e, 0x0010, 0x0007, 0x0005, + 0x001c, 0x001a, 0x0020, 0x0013, 0x0011, 0x000f, 0x0008, 0x000e, + 0x000e, 0x000c, 0x0009, 0x000d, 0x000e, 0x0009, 0x0004, 0x0001, + 0x000b, 0x0004, 0x0006, 0x0006, 0x0006, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_11[64] = { + 2, 3, 5, 7, 8, 9, 8, 9, + 3, 3, 4, 6, 8, 8, 7, 8, + 5, 5, 6, 7, 8, 9, 8, 8, + 7, 6, 7, 9, 8, 10, 8, 9, + 8, 8, 8, 9, 9, 10, 9, 10, + 8, 8, 9, 10, 10, 11, 10, 11, + 8, 7, 7, 8, 9, 10, 10, 10, + 8, 7, 8, 9, 10, 10, 10, 10, +}; + +static const uint16_t mpa_huffcodes_12[64] = { + 0x0009, 0x0006, 0x0010, 0x0021, 0x0029, 0x0027, 0x0026, 0x001a, + 0x0007, 0x0005, 0x0006, 0x0009, 0x0017, 0x0010, 0x001a, 0x000b, + 0x0011, 0x0007, 0x000b, 0x000e, 0x0015, 0x001e, 0x000a, 0x0007, + 0x0011, 0x000a, 0x000f, 0x000c, 0x0012, 0x001c, 0x000e, 0x0005, + 0x0020, 0x000d, 0x0016, 0x0013, 0x0012, 0x0010, 0x0009, 0x0005, + 0x0028, 0x0011, 0x001f, 0x001d, 0x0011, 0x000d, 0x0004, 0x0002, + 0x001b, 0x000c, 0x000b, 0x000f, 0x000a, 0x0007, 0x0004, 0x0001, + 0x001b, 0x000c, 0x0008, 0x000c, 0x0006, 0x0003, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_12[64] = { + 4, 3, 5, 7, 8, 9, 9, 9, + 3, 3, 4, 5, 7, 7, 8, 8, + 5, 4, 5, 6, 7, 8, 7, 8, + 6, 5, 6, 6, 7, 8, 8, 8, + 7, 6, 7, 7, 8, 8, 8, 9, + 8, 7, 8, 8, 8, 9, 8, 9, + 8, 7, 7, 8, 8, 9, 9, 10, + 9, 8, 8, 9, 9, 9, 9, 10, +}; + +static const uint16_t mpa_huffcodes_13[256] = { + 0x0001, 0x0005, 0x000e, 0x0015, 0x0022, 0x0033, 0x002e, 0x0047, + 0x002a, 0x0034, 0x0044, 0x0034, 0x0043, 0x002c, 0x002b, 0x0013, + 0x0003, 0x0004, 0x000c, 0x0013, 0x001f, 0x001a, 0x002c, 0x0021, + 0x001f, 0x0018, 0x0020, 0x0018, 0x001f, 0x0023, 0x0016, 0x000e, + 0x000f, 0x000d, 0x0017, 0x0024, 0x003b, 0x0031, 0x004d, 0x0041, + 0x001d, 0x0028, 0x001e, 0x0028, 0x001b, 0x0021, 0x002a, 0x0010, + 0x0016, 0x0014, 0x0025, 0x003d, 0x0038, 0x004f, 0x0049, 0x0040, + 0x002b, 0x004c, 0x0038, 0x0025, 0x001a, 0x001f, 0x0019, 0x000e, + 0x0023, 0x0010, 0x003c, 0x0039, 0x0061, 0x004b, 0x0072, 0x005b, + 0x0036, 0x0049, 0x0037, 0x0029, 0x0030, 0x0035, 0x0017, 0x0018, + 0x003a, 0x001b, 0x0032, 0x0060, 0x004c, 0x0046, 0x005d, 0x0054, + 0x004d, 0x003a, 0x004f, 0x001d, 0x004a, 0x0031, 0x0029, 0x0011, + 0x002f, 0x002d, 0x004e, 0x004a, 0x0073, 0x005e, 0x005a, 0x004f, + 0x0045, 0x0053, 0x0047, 0x0032, 0x003b, 0x0026, 0x0024, 0x000f, + 0x0048, 0x0022, 0x0038, 0x005f, 0x005c, 0x0055, 0x005b, 0x005a, + 0x0056, 0x0049, 0x004d, 0x0041, 0x0033, 0x002c, 0x002b, 0x002a, + 0x002b, 0x0014, 0x001e, 0x002c, 0x0037, 0x004e, 0x0048, 0x0057, + 0x004e, 0x003d, 0x002e, 0x0036, 0x0025, 0x001e, 0x0014, 0x0010, + 0x0035, 0x0019, 0x0029, 0x0025, 0x002c, 0x003b, 0x0036, 0x0051, + 0x0042, 0x004c, 0x0039, 0x0036, 0x0025, 0x0012, 0x0027, 0x000b, + 0x0023, 0x0021, 0x001f, 0x0039, 0x002a, 0x0052, 0x0048, 0x0050, + 0x002f, 0x003a, 0x0037, 0x0015, 0x0016, 0x001a, 0x0026, 0x0016, + 0x0035, 0x0019, 0x0017, 0x0026, 0x0046, 0x003c, 0x0033, 0x0024, + 0x0037, 0x001a, 0x0022, 0x0017, 0x001b, 0x000e, 0x0009, 0x0007, + 0x0022, 0x0020, 0x001c, 0x0027, 0x0031, 0x004b, 0x001e, 0x0034, + 0x0030, 0x0028, 0x0034, 0x001c, 0x0012, 0x0011, 0x0009, 0x0005, + 0x002d, 0x0015, 0x0022, 0x0040, 0x0038, 0x0032, 0x0031, 0x002d, + 0x001f, 0x0013, 0x000c, 0x000f, 0x000a, 0x0007, 0x0006, 0x0003, + 0x0030, 0x0017, 0x0014, 0x0027, 0x0024, 0x0023, 0x0035, 0x0015, + 0x0010, 0x0017, 0x000d, 0x000a, 0x0006, 0x0001, 0x0004, 0x0002, + 0x0010, 0x000f, 0x0011, 0x001b, 0x0019, 0x0014, 0x001d, 0x000b, + 0x0011, 0x000c, 0x0010, 0x0008, 0x0001, 0x0001, 0x0000, 0x0001, +}; + +static const uint8_t mpa_huffbits_13[256] = { + 1, 4, 6, 7, 8, 9, 9, 10, + 9, 10, 11, 11, 12, 12, 13, 13, + 3, 4, 6, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 12, 12, 12, + 6, 6, 7, 8, 9, 9, 10, 10, + 9, 10, 10, 11, 11, 12, 13, 13, + 7, 7, 8, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 11, 12, 13, 13, + 8, 7, 9, 9, 10, 10, 11, 11, + 10, 11, 11, 12, 12, 13, 13, 14, + 9, 8, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 11, 13, 13, 14, 14, + 9, 9, 10, 10, 11, 11, 11, 11, + 11, 12, 12, 12, 13, 13, 14, 14, + 10, 9, 10, 11, 11, 11, 12, 12, + 12, 12, 13, 13, 13, 14, 16, 16, + 9, 8, 9, 10, 10, 11, 11, 12, + 12, 12, 12, 13, 13, 14, 15, 15, + 10, 9, 10, 10, 11, 11, 11, 13, + 12, 13, 13, 14, 14, 14, 16, 15, + 10, 10, 10, 11, 11, 12, 12, 13, + 12, 13, 14, 13, 14, 15, 16, 17, + 11, 10, 10, 11, 12, 12, 12, 12, + 13, 13, 13, 14, 15, 15, 15, 16, + 11, 11, 11, 12, 12, 13, 12, 13, + 14, 14, 15, 15, 15, 16, 16, 16, + 12, 11, 12, 13, 13, 13, 14, 14, + 14, 14, 14, 15, 16, 15, 16, 16, + 13, 12, 12, 13, 13, 13, 15, 14, + 14, 17, 15, 15, 15, 17, 16, 16, + 12, 12, 13, 14, 14, 14, 15, 14, + 15, 15, 16, 16, 19, 18, 19, 16, +}; + +static const uint16_t mpa_huffcodes_15[256] = { + 0x0007, 0x000c, 0x0012, 0x0035, 0x002f, 0x004c, 0x007c, 0x006c, + 0x0059, 0x007b, 0x006c, 0x0077, 0x006b, 0x0051, 0x007a, 0x003f, + 0x000d, 0x0005, 0x0010, 0x001b, 0x002e, 0x0024, 0x003d, 0x0033, + 0x002a, 0x0046, 0x0034, 0x0053, 0x0041, 0x0029, 0x003b, 0x0024, + 0x0013, 0x0011, 0x000f, 0x0018, 0x0029, 0x0022, 0x003b, 0x0030, + 0x0028, 0x0040, 0x0032, 0x004e, 0x003e, 0x0050, 0x0038, 0x0021, + 0x001d, 0x001c, 0x0019, 0x002b, 0x0027, 0x003f, 0x0037, 0x005d, + 0x004c, 0x003b, 0x005d, 0x0048, 0x0036, 0x004b, 0x0032, 0x001d, + 0x0034, 0x0016, 0x002a, 0x0028, 0x0043, 0x0039, 0x005f, 0x004f, + 0x0048, 0x0039, 0x0059, 0x0045, 0x0031, 0x0042, 0x002e, 0x001b, + 0x004d, 0x0025, 0x0023, 0x0042, 0x003a, 0x0034, 0x005b, 0x004a, + 0x003e, 0x0030, 0x004f, 0x003f, 0x005a, 0x003e, 0x0028, 0x0026, + 0x007d, 0x0020, 0x003c, 0x0038, 0x0032, 0x005c, 0x004e, 0x0041, + 0x0037, 0x0057, 0x0047, 0x0033, 0x0049, 0x0033, 0x0046, 0x001e, + 0x006d, 0x0035, 0x0031, 0x005e, 0x0058, 0x004b, 0x0042, 0x007a, + 0x005b, 0x0049, 0x0038, 0x002a, 0x0040, 0x002c, 0x0015, 0x0019, + 0x005a, 0x002b, 0x0029, 0x004d, 0x0049, 0x003f, 0x0038, 0x005c, + 0x004d, 0x0042, 0x002f, 0x0043, 0x0030, 0x0035, 0x0024, 0x0014, + 0x0047, 0x0022, 0x0043, 0x003c, 0x003a, 0x0031, 0x0058, 0x004c, + 0x0043, 0x006a, 0x0047, 0x0036, 0x0026, 0x0027, 0x0017, 0x000f, + 0x006d, 0x0035, 0x0033, 0x002f, 0x005a, 0x0052, 0x003a, 0x0039, + 0x0030, 0x0048, 0x0039, 0x0029, 0x0017, 0x001b, 0x003e, 0x0009, + 0x0056, 0x002a, 0x0028, 0x0025, 0x0046, 0x0040, 0x0034, 0x002b, + 0x0046, 0x0037, 0x002a, 0x0019, 0x001d, 0x0012, 0x000b, 0x000b, + 0x0076, 0x0044, 0x001e, 0x0037, 0x0032, 0x002e, 0x004a, 0x0041, + 0x0031, 0x0027, 0x0018, 0x0010, 0x0016, 0x000d, 0x000e, 0x0007, + 0x005b, 0x002c, 0x0027, 0x0026, 0x0022, 0x003f, 0x0034, 0x002d, + 0x001f, 0x0034, 0x001c, 0x0013, 0x000e, 0x0008, 0x0009, 0x0003, + 0x007b, 0x003c, 0x003a, 0x0035, 0x002f, 0x002b, 0x0020, 0x0016, + 0x0025, 0x0018, 0x0011, 0x000c, 0x000f, 0x000a, 0x0002, 0x0001, + 0x0047, 0x0025, 0x0022, 0x001e, 0x001c, 0x0014, 0x0011, 0x001a, + 0x0015, 0x0010, 0x000a, 0x0006, 0x0008, 0x0006, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_15[256] = { + 3, 4, 5, 7, 7, 8, 9, 9, + 9, 10, 10, 11, 11, 11, 12, 13, + 4, 3, 5, 6, 7, 7, 8, 8, + 8, 9, 9, 10, 10, 10, 11, 11, + 5, 5, 5, 6, 7, 7, 8, 8, + 8, 9, 9, 10, 10, 11, 11, 11, + 6, 6, 6, 7, 7, 8, 8, 9, + 9, 9, 10, 10, 10, 11, 11, 11, + 7, 6, 7, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 11, + 8, 7, 7, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 11, 11, 12, + 9, 7, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 11, 11, 12, 12, + 9, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 11, 11, 11, 12, + 9, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 11, 11, 12, 12, 12, + 9, 8, 9, 9, 9, 9, 10, 10, + 10, 11, 11, 11, 11, 12, 12, 12, + 10, 9, 9, 9, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 12, 13, 12, + 10, 9, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 12, 12, 12, 13, + 11, 10, 9, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 12, 12, 13, 13, + 11, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 13, 13, + 12, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 12, 13, + 12, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 13, 13, 13, +}; + +static const uint16_t mpa_huffcodes_16[256] = { + 0x0001, 0x0005, 0x000e, 0x002c, 0x004a, 0x003f, 0x006e, 0x005d, + 0x00ac, 0x0095, 0x008a, 0x00f2, 0x00e1, 0x00c3, 0x0178, 0x0011, + 0x0003, 0x0004, 0x000c, 0x0014, 0x0023, 0x003e, 0x0035, 0x002f, + 0x0053, 0x004b, 0x0044, 0x0077, 0x00c9, 0x006b, 0x00cf, 0x0009, + 0x000f, 0x000d, 0x0017, 0x0026, 0x0043, 0x003a, 0x0067, 0x005a, + 0x00a1, 0x0048, 0x007f, 0x0075, 0x006e, 0x00d1, 0x00ce, 0x0010, + 0x002d, 0x0015, 0x0027, 0x0045, 0x0040, 0x0072, 0x0063, 0x0057, + 0x009e, 0x008c, 0x00fc, 0x00d4, 0x00c7, 0x0183, 0x016d, 0x001a, + 0x004b, 0x0024, 0x0044, 0x0041, 0x0073, 0x0065, 0x00b3, 0x00a4, + 0x009b, 0x0108, 0x00f6, 0x00e2, 0x018b, 0x017e, 0x016a, 0x0009, + 0x0042, 0x001e, 0x003b, 0x0038, 0x0066, 0x00b9, 0x00ad, 0x0109, + 0x008e, 0x00fd, 0x00e8, 0x0190, 0x0184, 0x017a, 0x01bd, 0x0010, + 0x006f, 0x0036, 0x0034, 0x0064, 0x00b8, 0x00b2, 0x00a0, 0x0085, + 0x0101, 0x00f4, 0x00e4, 0x00d9, 0x0181, 0x016e, 0x02cb, 0x000a, + 0x0062, 0x0030, 0x005b, 0x0058, 0x00a5, 0x009d, 0x0094, 0x0105, + 0x00f8, 0x0197, 0x018d, 0x0174, 0x017c, 0x0379, 0x0374, 0x0008, + 0x0055, 0x0054, 0x0051, 0x009f, 0x009c, 0x008f, 0x0104, 0x00f9, + 0x01ab, 0x0191, 0x0188, 0x017f, 0x02d7, 0x02c9, 0x02c4, 0x0007, + 0x009a, 0x004c, 0x0049, 0x008d, 0x0083, 0x0100, 0x00f5, 0x01aa, + 0x0196, 0x018a, 0x0180, 0x02df, 0x0167, 0x02c6, 0x0160, 0x000b, + 0x008b, 0x0081, 0x0043, 0x007d, 0x00f7, 0x00e9, 0x00e5, 0x00db, + 0x0189, 0x02e7, 0x02e1, 0x02d0, 0x0375, 0x0372, 0x01b7, 0x0004, + 0x00f3, 0x0078, 0x0076, 0x0073, 0x00e3, 0x00df, 0x018c, 0x02ea, + 0x02e6, 0x02e0, 0x02d1, 0x02c8, 0x02c2, 0x00df, 0x01b4, 0x0006, + 0x00ca, 0x00e0, 0x00de, 0x00da, 0x00d8, 0x0185, 0x0182, 0x017d, + 0x016c, 0x0378, 0x01bb, 0x02c3, 0x01b8, 0x01b5, 0x06c0, 0x0004, + 0x02eb, 0x00d3, 0x00d2, 0x00d0, 0x0172, 0x017b, 0x02de, 0x02d3, + 0x02ca, 0x06c7, 0x0373, 0x036d, 0x036c, 0x0d83, 0x0361, 0x0002, + 0x0179, 0x0171, 0x0066, 0x00bb, 0x02d6, 0x02d2, 0x0166, 0x02c7, + 0x02c5, 0x0362, 0x06c6, 0x0367, 0x0d82, 0x0366, 0x01b2, 0x0000, + 0x000c, 0x000a, 0x0007, 0x000b, 0x000a, 0x0011, 0x000b, 0x0009, + 0x000d, 0x000c, 0x000a, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, +}; + +static const uint8_t mpa_huffbits_16[256] = { + 1, 4, 6, 8, 9, 9, 10, 10, + 11, 11, 11, 12, 12, 12, 13, 9, + 3, 4, 6, 7, 8, 9, 9, 9, + 10, 10, 10, 11, 12, 11, 12, 8, + 6, 6, 7, 8, 9, 9, 10, 10, + 11, 10, 11, 11, 11, 12, 12, 9, + 8, 7, 8, 9, 9, 10, 10, 10, + 11, 11, 12, 12, 12, 13, 13, 10, + 9, 8, 9, 9, 10, 10, 11, 11, + 11, 12, 12, 12, 13, 13, 13, 9, + 9, 8, 9, 9, 10, 11, 11, 12, + 11, 12, 12, 13, 13, 13, 14, 10, + 10, 9, 9, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 14, 10, + 10, 9, 10, 10, 11, 11, 11, 12, + 12, 13, 13, 13, 13, 15, 15, 10, + 10, 10, 10, 11, 11, 11, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 10, + 11, 10, 10, 11, 11, 12, 12, 13, + 13, 13, 13, 14, 13, 14, 13, 11, + 11, 11, 10, 11, 12, 12, 12, 12, + 13, 14, 14, 14, 15, 15, 14, 10, + 12, 11, 11, 11, 12, 12, 13, 14, + 14, 14, 14, 14, 14, 13, 14, 11, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 15, 14, 14, 14, 14, 16, 11, + 14, 12, 12, 12, 13, 13, 14, 14, + 14, 16, 15, 15, 15, 17, 15, 11, + 13, 13, 11, 12, 14, 14, 13, 14, + 14, 15, 16, 15, 17, 15, 14, 11, + 9, 8, 8, 9, 9, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 8, +}; + +static const uint16_t mpa_huffcodes_24[256] = { + 0x000f, 0x000d, 0x002e, 0x0050, 0x0092, 0x0106, 0x00f8, 0x01b2, + 0x01aa, 0x029d, 0x028d, 0x0289, 0x026d, 0x0205, 0x0408, 0x0058, + 0x000e, 0x000c, 0x0015, 0x0026, 0x0047, 0x0082, 0x007a, 0x00d8, + 0x00d1, 0x00c6, 0x0147, 0x0159, 0x013f, 0x0129, 0x0117, 0x002a, + 0x002f, 0x0016, 0x0029, 0x004a, 0x0044, 0x0080, 0x0078, 0x00dd, + 0x00cf, 0x00c2, 0x00b6, 0x0154, 0x013b, 0x0127, 0x021d, 0x0012, + 0x0051, 0x0027, 0x004b, 0x0046, 0x0086, 0x007d, 0x0074, 0x00dc, + 0x00cc, 0x00be, 0x00b2, 0x0145, 0x0137, 0x0125, 0x010f, 0x0010, + 0x0093, 0x0048, 0x0045, 0x0087, 0x007f, 0x0076, 0x0070, 0x00d2, + 0x00c8, 0x00bc, 0x0160, 0x0143, 0x0132, 0x011d, 0x021c, 0x000e, + 0x0107, 0x0042, 0x0081, 0x007e, 0x0077, 0x0072, 0x00d6, 0x00ca, + 0x00c0, 0x00b4, 0x0155, 0x013d, 0x012d, 0x0119, 0x0106, 0x000c, + 0x00f9, 0x007b, 0x0079, 0x0075, 0x0071, 0x00d7, 0x00ce, 0x00c3, + 0x00b9, 0x015b, 0x014a, 0x0134, 0x0123, 0x0110, 0x0208, 0x000a, + 0x01b3, 0x0073, 0x006f, 0x006d, 0x00d3, 0x00cb, 0x00c4, 0x00bb, + 0x0161, 0x014c, 0x0139, 0x012a, 0x011b, 0x0213, 0x017d, 0x0011, + 0x01ab, 0x00d4, 0x00d0, 0x00cd, 0x00c9, 0x00c1, 0x00ba, 0x00b1, + 0x00a9, 0x0140, 0x012f, 0x011e, 0x010c, 0x0202, 0x0179, 0x0010, + 0x014f, 0x00c7, 0x00c5, 0x00bf, 0x00bd, 0x00b5, 0x00ae, 0x014d, + 0x0141, 0x0131, 0x0121, 0x0113, 0x0209, 0x017b, 0x0173, 0x000b, + 0x029c, 0x00b8, 0x00b7, 0x00b3, 0x00af, 0x0158, 0x014b, 0x013a, + 0x0130, 0x0122, 0x0115, 0x0212, 0x017f, 0x0175, 0x016e, 0x000a, + 0x028c, 0x015a, 0x00ab, 0x00a8, 0x00a4, 0x013e, 0x0135, 0x012b, + 0x011f, 0x0114, 0x0107, 0x0201, 0x0177, 0x0170, 0x016a, 0x0006, + 0x0288, 0x0142, 0x013c, 0x0138, 0x0133, 0x012e, 0x0124, 0x011c, + 0x010d, 0x0105, 0x0200, 0x0178, 0x0172, 0x016c, 0x0167, 0x0004, + 0x026c, 0x012c, 0x0128, 0x0126, 0x0120, 0x011a, 0x0111, 0x010a, + 0x0203, 0x017c, 0x0176, 0x0171, 0x016d, 0x0169, 0x0165, 0x0002, + 0x0409, 0x0118, 0x0116, 0x0112, 0x010b, 0x0108, 0x0103, 0x017e, + 0x017a, 0x0174, 0x016f, 0x016b, 0x0168, 0x0166, 0x0164, 0x0000, + 0x002b, 0x0014, 0x0013, 0x0011, 0x000f, 0x000d, 0x000b, 0x0009, + 0x0007, 0x0006, 0x0004, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, +}; + +static const uint8_t mpa_huffbits_24[256] = { + 4, 4, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 11, 11, 11, 12, 9, + 4, 4, 5, 6, 7, 8, 8, 9, + 9, 9, 10, 10, 10, 10, 10, 8, + 6, 5, 6, 7, 7, 8, 8, 9, + 9, 9, 9, 10, 10, 10, 11, 7, + 7, 6, 7, 7, 8, 8, 8, 9, + 9, 9, 9, 10, 10, 10, 10, 7, + 8, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 10, 10, 10, 10, 11, 7, + 9, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 7, + 9, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 11, 7, + 10, 8, 8, 8, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 11, 11, 11, 8, + 11, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 8, + 12, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 8, + 8, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 4, +}; + +static const HuffTable mpa_huff_tables[16] = { +{ 1, NULL, NULL }, +{ 2, mpa_huffbits_1, mpa_huffcodes_1 }, +{ 3, mpa_huffbits_2, mpa_huffcodes_2 }, +{ 3, mpa_huffbits_3, mpa_huffcodes_3 }, +{ 4, mpa_huffbits_5, mpa_huffcodes_5 }, +{ 4, mpa_huffbits_6, mpa_huffcodes_6 }, +{ 6, mpa_huffbits_7, mpa_huffcodes_7 }, +{ 6, mpa_huffbits_8, mpa_huffcodes_8 }, +{ 6, mpa_huffbits_9, mpa_huffcodes_9 }, +{ 8, mpa_huffbits_10, mpa_huffcodes_10 }, +{ 8, mpa_huffbits_11, mpa_huffcodes_11 }, +{ 8, mpa_huffbits_12, mpa_huffcodes_12 }, +{ 16, mpa_huffbits_13, mpa_huffcodes_13 }, +{ 16, mpa_huffbits_15, mpa_huffcodes_15 }, +{ 16, mpa_huffbits_16, mpa_huffcodes_16 }, +{ 16, mpa_huffbits_24, mpa_huffcodes_24 }, +}; + +static const uint8_t mpa_huff_data[32][2] = { +{ 0, 0 }, +{ 1, 0 }, +{ 2, 0 }, +{ 3, 0 }, +{ 0, 0 }, +{ 4, 0 }, +{ 5, 0 }, +{ 6, 0 }, +{ 7, 0 }, +{ 8, 0 }, +{ 9, 0 }, +{ 10, 0 }, +{ 11, 0 }, +{ 12, 0 }, +{ 0, 0 }, +{ 13, 0 }, +{ 14, 1 }, +{ 14, 2 }, +{ 14, 3 }, +{ 14, 4 }, +{ 14, 6 }, +{ 14, 8 }, +{ 14, 10 }, +{ 14, 13 }, +{ 15, 4 }, +{ 15, 5 }, +{ 15, 6 }, +{ 15, 7 }, +{ 15, 8 }, +{ 15, 9 }, +{ 15, 11 }, +{ 15, 13 }, +}; + + +/* huffman tables for quadrules */ +static uint8_t mpa_quad_codes[2][16] = { + { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1, }, + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, +}; + +static uint8_t mpa_quad_bits[2][16] = { + { 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6, }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }, +}; + +/* band size tables */ +static const uint8_t band_size_long[9][22] = { +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, + 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158, }, /* 44100 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, + 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192, }, /* 48000 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, + 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26, }, /* 32000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 22050 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 18, 22, 26, 32, 38, 46, 52, 64, 70, 76, 36, }, /* 24000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 16000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 11025 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 12000 */ +{ 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, + 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2, }, /* 8000 */ +}; + +static const uint8_t band_size_short[9][13] = { +{ 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56, }, /* 44100 */ +{ 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66, }, /* 48000 */ +{ 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12, }, /* 32000 */ +{ 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18, }, /* 22050 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12, }, /* 24000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 16000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 11025 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 12000 */ +{ 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26, }, /* 8000 */ +}; + +static const uint8_t mpa_pretab[2][22] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 }, +}; + +/* table for alias reduction (XXX: store it as integer !) */ +static const float ci_table[8] = { + -0.6f, -0.535f, -0.33f, -0.185f, -0.095f, -0.041f, -0.0142f, -0.0037f, +}; diff --git a/plugins/mp3Decoder/mpaudec/mpegaudio.h b/plugins/mp3Decoder/mpaudec/mpegaudio.h new file mode 100644 index 0000000..51f0291 --- /dev/null +++ b/plugins/mp3Decoder/mpaudec/mpegaudio.h @@ -0,0 +1,17 @@ +/* Modified slightly by Matt Campbell for the + stand-alone mpaudec library. Based on mpegaudio.h from libavcodec. */ + +/* max frame size, in samples */ +#define MPA_FRAME_SIZE 1152 + +/* max compressed frame size */ +#define MPA_MAX_CODED_FRAME_SIZE 1792 + +#define MPA_MAX_CHANNELS 2 + +#define SBLIMIT 32 /* number of subbands */ + +#define MPA_STEREO 0 +#define MPA_JSTEREO 1 +#define MPA_DUAL 2 +#define MPA_MONO 3 diff --git a/plugins/mp3Decoder/readme.txt b/plugins/mp3Decoder/readme.txt new file mode 100644 index 0000000..4f544b3 --- /dev/null +++ b/plugins/mp3Decoder/readme.txt @@ -0,0 +1,5 @@ +Note: This plugin uses code from "MP3 input for Audiere" by Matt Campbell , which is based on libavcodec from ffmpeg (http://ffmpeg.sourceforge.net/). + +As a result, this plugin falls under his license and is not statically linked to the main library. + +See license.txt for license details of this plugin. \ No newline at end of file