diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/In.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/In.cpp')
-rw-r--r-- | Src/Winamp/In.cpp | 1293 |
1 files changed, 1293 insertions, 0 deletions
diff --git a/Src/Winamp/In.cpp b/Src/Winamp/In.cpp new file mode 100644 index 00000000..ab83f820 --- /dev/null +++ b/Src/Winamp/In.cpp @@ -0,0 +1,1293 @@ +#include "Main.h" + +#include "resource.h" +#include <math.h> +#include "api.h" +//#define PROFILE_PLUGINS_LOAD_TIME +#include "timing.h" +#include "../nu/AutoWide.h" +#include "../nu/AutoChar.h" +#include "../nu/ns_wc.h" +#include "WinampAttributes.h" +#include "eq10dsp.h" +#include "../nsutil/pcm.h" + + +int filter_srate = 0, filter_enabled = 1, filter_top = 0, filter_top2 = 10; +static In_Module* dsp_init_mod = 0; +static int dsp_in_init = 0; +std::vector<In_Module*> in_modules; +In_Module* in_mod = 0; +float preamp_val = 1.0f; + +eq10_t* eq = 0; + +extern "C" volatile int sa_override; + +static void setinfo(int bitrate, int srate, int stereo, int synched); +static void vissa_init(int maxlatency_in_ms, int srate); +static void vissa_deinit(); +static int sa_getmode(); +static int eq_dosamples_4front(short* samples, int numsamples, int bps, int nch, int srate); +static int eq_dosamples(short* samples, int numsamples, int bps, int nch, int srate); +int benskiQ_eq_dosamples(short* samples, int numsamples, int bps, int nch, int srate); +static int eq_isactive(); + +static int myisourfile(const char* filename) // mjf bullshit +{ + return 0; +} + +typedef struct _PLUGINORDER +{ + LPCWSTR name; + bool found; +} PLUGINORDER; + +static PLUGINORDER preload[] = +{ + // the one plug-in to rule all + { L"in_mp3.dll", false }, + + // no extension configuration + { L"in_avi.dll", false }, + { L"in_cdda.dll", false }, + { L"in_linein.dll", false }, + { L"in_mkv.dll", false }, + { L"in_nsv.dll", false }, + { L"in_swf.dll", false }, + { L"in_vorbis.dll", false }, + + // extension configuration + { L"in_mp4.dll", false }, + { L"in_dshow.dll", false }, // load after in_avi and in_mkv as often those extensions are associated with this one as well + { L"in_flac.dll", false }, + { L"in_flv.dll", false }, + { L"in_wm.dll", false }, + + // tend to have a lot of extensions so do later + { L"in_wave.dll", false }, + { L"in_midi.dll", false }, + { L"in_mod.dll", false } +}; + +static void LoadInputPlugin(const wchar_t* filename) +{ + wchar_t file[MAX_PATH] = { 0 }; + PathCombineW(file, PLUGINDIR, filename); + + HINSTANCE hLib = LoadLibraryW(file); + if ( hLib == NULL ) + return; + + + In_Module* (*pr)(); + pr = (In_Module * (__cdecl*)(void)) GetProcAddress(hLib, "winampGetInModule2"); + if ( pr == NULL ) + return; + + + In_Module* mod = pr(); + if ( mod == NULL ) + { + FreeModule(hLib); + return; + } + + + int ver = ((mod->version & ~IN_UNICODE) & ~IN_INIT_RET); + if ( !(ver == IN_VER || ver == IN_VER_OLD) ) + { + FreeModule(hLib); + return; + } + + + if ( g_safeMode ) + { + char desc[128] = { 0 }; + lstrcpynA(desc, mod->description, sizeof(desc)); + if ( desc[0] && !memcmp(desc, "nullsoft(", 9) ) + { + char* p = strrchr(desc, ')'); + if ( p ) + { + *p = 0; + if ( _wcsicmp(filename, AutoWide(desc + 9)) ) + { + FreeModule(hLib); + return; + } + } + } + else + { + FreeModule(hLib); + return; + } + } + + mod->hDllInstance = hLib; + mod->dsp_dosamples = eq_dosamples; + mod->dsp_isactive = eq_isactive; + mod->SAGetMode = sa_getmode; + mod->SAAdd = (int(__cdecl*)(void*, int, int))sa_add; + mod->SAVSAInit = vissa_init; + mod->SAVSADeInit = vissa_deinit; + mod->VSASetInfo = vis_setinfo; + mod->VSAAdd = vsa_add; + mod->VSAGetMode = vsa_getmode; + mod->SAAddPCMData = sa_addpcmdata; + mod->VSAAddPCMData = vsa_addpcmdata; + mod->hMainWindow = hMainWindow; + mod->SetInfo = NULL; + mod->UsesOutputPlug &= ~(2 | 4 | 8 | 16); + + if ( !_wcsicmp(filename, L"in_mjf.dll") ) + { + mod->IsOurFile = myisourfile; + } + + // add 5.66+ to do better error handling on issues, etc + if ( mod->version & IN_INIT_RET ) + { + mod->service = WASABI_API_SVC; + } + int ret = mod->Init(); + if ( (mod->version & IN_INIT_RET) && (ret == IN_INIT_FAILURE) ) + { + FreeModule(hLib); + return; + } + + in_modules.push_back(mod); + + if ( mod->SetInfo ) + { + char* p = (char*)mod->SetInfo; + if ( p && *p ) + { + StringCchCatA(metric_plugin_list, 512, ":"); + StringCchCatA(metric_plugin_list, 512, p); + } + } + + mod->SetInfo = setinfo; + + if ( !g_has_video_plugin ) + { + int (*gefiW)(const wchar_t* fn, const char* data, wchar_t* dest, int destlen); + gefiW = (int(__cdecl*)(const wchar_t*, const char*, wchar_t*, int))GetProcAddress(hLib, "winampGetExtendedFileInfoW"); + if ( gefiW ) + { + wchar_t dest[16] = { 0 }; + gefiW(L"", "type", dest, 16); + if ( _wtoi(dest) == 1 ) g_has_video_plugin = 1; + } + + int (*gefi)(const char* fn, const char* data, char* dest, int destlen); + gefi = (int(__cdecl*)(const char*, const char*, char*, int))GetProcAddress(hLib, "winampGetExtendedFileInfo"); + if ( gefi ) + { + char dest[16] = { 0 }; + gefi("", "type", dest, 16); + if ( atoi(dest) == 1 ) g_has_video_plugin = 1; + } + } +} + +int in_init() +{ + // input plugins require the main window, at least for IPC calls + if ( !CreateMainWindow() ) + return FALSE; + + int i = 0, count = sizeof(preload) / sizeof(PLUGINORDER); + + for ( ; i < count; i++ ) + LoadInputPlugin(preload[i].name); + + WIN32_FIND_DATAW d = { 0 }; + wchar_t dirstr[MAX_PATH] = { 0 }; + + PathCombineW(dirstr, PLUGINDIR, L"IN_*.DLL"); + HANDLE h = FindFirstFileW(dirstr, &d); + if ( h != INVALID_HANDLE_VALUE ) + { + do + { + for ( i = 0; i < count && (preload[i].found || lstrcmpiW(preload[i].name, d.cFileName)); i++ ); + if ( i == count ) LoadInputPlugin(d.cFileName); + else preload[i].found = true; + } while ( FindNextFileW(h, &d) ); + FindClose(h); + } + + if ( (g_no_video_loaded = _r_i("no_video", 0)) ) g_has_video_plugin = 0; + + return TRUE; +} + +In_Module* g_in_infobox = 0; + +void in_deinit() +{ + size_t x = in_modules.size(); + while ( x-- ) + { + In_Module*& mod = in_modules[x]; + // make sure there's something valid due to the dynamic unload changes in 5.5+ + if ( mod != g_in_infobox && mod ) + { + //HINSTANCE hLib = mod->hDllInstance; + mod->Quit(); + + //FreeLibrary(hLib); // benski> we're just going to let it leak because it might be subclassing + mod = 0; + } + } + in_modules.clear(); +} + +In_Module* in_setmod_noplay(const wchar_t* filename, int* start_offs) +{ + size_t x; + char ext[128] = { 0 }; + extension_ex(AutoChar(filename), ext, sizeof(ext)); + for ( x = start_offs ? *start_offs : 0; x < in_modules.size(); x++ ) + { + if ( InW_IsOurFile(in_modules[x], filename) ) + { + if ( start_offs ) + *start_offs = (int)x; + + if ( !in_modules[x]->hMainWindow ) + in_modules[x]->hMainWindow = hMainWindow; + + return in_modules[x]; + } + } + for ( x = start_offs ? *start_offs : 0; x < in_modules.size(); x++ ) + { + if ( in_modules[x] ) + { + char* allExtension = in_modules[x]->FileExtensions; + while ( allExtension && *allExtension ) + { + char* splitterBuffer = allExtension; + char* extensionBuffer; + do + { + // string split on ';' + char currentExtension[20] = { 0 }; + lstrcpynA(currentExtension, splitterBuffer, 20); + if ( (extensionBuffer = strstr(splitterBuffer, ";")) ) + { + if ( (extensionBuffer - splitterBuffer) < 15 ) + currentExtension[extensionBuffer - splitterBuffer] = 0; + } + //else + //d[lstrlen(splitterBuffer)] = 0; + + if ( !lstrcmpiA(ext, currentExtension) ) + { + if ( start_offs ) + *start_offs = (int)x; + if ( !in_modules[x]->hMainWindow ) + in_modules[x]->hMainWindow = hMainWindow; + + return in_modules[x]; + } + splitterBuffer = extensionBuffer + 1; + } while ( extensionBuffer ); + + allExtension += lstrlenA(allExtension) + 1; + + if ( !*allExtension ) + break; + + allExtension += lstrlenA(allExtension) + 1; + } + } + } + + if ( start_offs ) + { + *start_offs = -1; + return 0; + } + + { + static int r; + const wchar_t* p; + + if ( PathFindExtensionW(filename)[0] && (p = wcsstr(filename, L"://")) && (p = wcsstr(p, L"?")) ) + { + wchar_t* d = _wcsdup(filename); + In_Module* v; + d[p - filename] = 0; + v = in_setmod_noplay(d, 0); + free(d); + return v; + } + + if ( !config_defext[0] || config_defext[0] == ' ' ) + StringCchCopyA(config_defext, 32, "mp3"); + + if ( !r ) + { + wchar_t a[128] = L"hi."; + In_Module* v; + MultiByteToWideCharSZ(CP_ACP, 0, config_defext, -1, a + 3, 120); + r = 1; + v = in_setmod_noplay(a, 0); + r = 0; + return v; + } + else + return 0; + } +} + +In_Module* in_setmod(const wchar_t* filename) +{ + In_Module* i = in_setmod_noplay(filename, 0); + if ( !i ) return 0; + if ( i->UsesOutputPlug & IN_MODULE_FLAG_USES_OUTPUT_PLUGIN ) + { + int t; + for ( t = 0; out_modules[t] && _stricmp(config_outname, (char*)out_modules[t]->id); t++ ); + if ( !out_modules[t] ) + { + for ( t = 0; out_modules[t]; t++ ) + { + if ( !_stricmp("out_ds.dll", (char*)out_modules[t]->id) ) + { + break; + } + else if ( !_stricmp("out_wave.dll", (char*)out_modules[t]->id) ) + { + break; + } + } + + if ( !out_modules[t] ) + { + LPMessageBox(DIALOG_PARENT(hMainWindow), IDS_NOOUTPUT, IDS_ERROR, MB_OK | MB_ICONERROR); + return (In_Module*)-31337; + } + } + + // TODO only call out_changed(..) if we are different from before + // though currently changing the output prefs and playing a + // new track will generate a change (which is expected but + // it might be assumed to be wrong so may need to document) + int changed = 0; + if ( !i->outMod || i->outMod && i->outMod->hDllInstance != out_modules[t]->hDllInstance ) + { + changed = 1; + if ( i->outMod ) out_changed(i->outMod->hDllInstance, OUT_UNSET | OUT_PLAYBACK); + } + i->outMod = out_modules[t]; + i->outMod->hMainWindow = hMainWindow; + if ( changed ) out_changed(i->outMod->hDllInstance, OUT_SET | OUT_PLAYBACK); + } + else + { + if ( i->outMod ) out_changed(i->outMod->hDllInstance, OUT_UNSET | OUT_PLAYBACK); + i->outMod = NULL; + } + return i; +} + +void in_flush(int ms) +{ + if ( in_mod && in_mod->outMod ) + { + in_mod->outMod->Flush(ms); + } +} + +int in_getouttime(void) +{ + if ( in_mod ) return in_mod->GetOutputTime(); + return 0; +} + +int in_getlength(void) +{ + if ( in_mod ) + { + int t = in_mod->GetLength() / 1000; + if ( t < 1 && t != -1 ) + t = 1; + + return t; + } + + return -1; +} + +void in_pause(int p) +{ + if ( in_mod ) + { + if ( p ) + in_mod->Pause(); + else + in_mod->UnPause(); + } +} + +void in_setvol(int v) +{ + if ( in_mod ) + in_mod->SetVolume(v); + + if ( config_eq_ws && config_eq_open ) + draw_eq_tbar(GetForegroundWindow() == hEQWindow ? 1 : (config_hilite ? 0 : 1)); + + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_VOLUME, IPC_CB_MISC); + + + //////CefRefPtr<wa_Cef_App> l_CefApp = wa_Cef_App::GetInstance(); + + //////if ( l_CefApp.get() != nullptr ) + //////{ + ////// l_CefApp.get()->setVolume( v ); + //////} + +} + +void in_setpan(int p) +{ + if ( in_mod ) + in_mod->SetPan(p); + + if ( config_eq_ws && config_eq_open ) + draw_eq_tbar(GetForegroundWindow() == hEQWindow ? 1 : (config_hilite ? 0 : 1)); + + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_VOLUME, IPC_CB_MISC); +} + +int in_seek(int time_in_ms) +{ + if ( in_mod ) + in_mod->SetOutputTime(time_in_ms); + + return 0; +} + +extern "C" int g_need_trusted_dsp = 0; + +int in_open(const wchar_t* fn) +{ + in_mod = in_setmod(fn); + if ( (int)in_mod <= 0 ) return (!in_mod ? 1 : *(int*)in_mod); + sa_setthread(config_sa); + in_setvol(config_volume); + in_setpan(config_pan); + + dsp_in_init = 0; + dsp_init_mod = in_mod; + filter_srate = 0; + + int r = InW_Play(in_mod, fn); + return r; +} + +void in_close(void) +{ + if ( in_mod ) + in_mod->Stop(); + + if ( NULL != eq ) + { + free(eq); + eq = NULL; + } + + timingPrint(); +} + +enum FileInfoMode +{ + FILEINFO_MODE_0, + FILEINFO_MODE_1, +}; + +int ModernInfoBox(In_Module* in, FileInfoMode mode, const wchar_t* filename, HWND parent); +typedef int(__cdecl* UseUnifiedFileInfoDlg)(const wchar_t* fn); + +int in_infobox(HWND hwnd, const wchar_t* fn) +{ + const wchar_t* p = wcsstr(fn, L"aol.com/uvox"); + if ( p ) return 0; + + if ( g_in_infobox ) return 0; + + In_Module* mod = in_setmod_noplay(fn, 0); + if ( !mod ) return 0; + + g_in_infobox = mod; + + UseUnifiedFileInfoDlg uufid = (UseUnifiedFileInfoDlg)GetProcAddress(mod->hDllInstance, "winampUseUnifiedFileInfoDlg"); + + // focus often gets reverted back to the main window after this dialog + // so we will remember what window used to have focus + HWND oldFocus = GetFocus(); + int a = 0; + + int ret = 0; + if ( uufid ) { + ret = uufid(fn); + if ( ret == 1 ) { + a = ModernInfoBox(mod, FILEINFO_MODE_0, fn, hwnd); + } + else if ( ret == 2 ) + a = ModernInfoBox(mod, FILEINFO_MODE_1, fn, hwnd); + } + + if ( ret == 0 ) { + // added 5.66 so plug-ins can get a hint that something may change... + SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)fn, IPC_FILE_TAG_MAY_UPDATEW); + a = InW_InfoBox(mod, fn, hwnd); + } + + SetFocus(oldFocus); + + if ( !a ) + { + SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)fn, IPC_FILE_TAG_MAY_HAVE_UPDATEDW); + } + + g_in_infobox = 0; + + return a; +} + +static void AddFilterString(char* p, size_t size, const char* a) +{ + while ( a && *a ) + { + char* t = 0; + StringCchCatExA(p, size, ";*.", &t, &size, 0); + t = p + lstrlenA(p); + while ( a && *a && *a != ';' ) *t++ = *a++; + *t = 0; + if ( a ) a++; + + if ( a && a[-1] ) continue; + if ( !*a ) break; + if ( a ) a += lstrlenA(a) + 1; + } +} + +char* in_getfltstr() +{ + int in_mod = -1; + int in_wave = -1; + size_t size = 256 * 1024; + char* buf = (char*)GlobalAlloc(GPTR, size); // this is gay, should have a growing buffer or somethin. + char* p = buf; + size_t x; + getString(IDS_ALLTYPES, p, size); + p = p + lstrlenA(p) + 1; + wchar_t playlistString[1024] = { 0 }; + playlistManager->GetFilterList(playlistString, 1024); + WideCharToMultiByteSZ(CP_ACP, 0, playlistString, -1, p, (int)size, 0, 0); + for ( x = 0; x < in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + if ( a && *a ) + { + /* we want to skip in_mod and in_wave because they have TOO MANY extensions and we are limited to MAX_PATH (260) + we'll tack them at the end just in case we have enough room for 'em */ + if ( in_mod < 0 && !strncmp(a, "mod;", 4) ) + in_mod = (int)x; + else if ( in_wave < 0 && strstr(a, "aiff") ) // detection for in_wave. not the best but should work + in_wave = (int)x; + else AddFilterString(p, size, a); + } + } + + /* add in_wave and in_mod last */ + if ( in_wave >= 0 ) + AddFilterString(p, size, in_modules[in_wave]->FileExtensions); + + if ( in_mod >= 0 ) // fuck you in_mod :) + AddFilterString(p, size, in_modules[in_mod]->FileExtensions); + + p = p + lstrlenA(p) + 1; + getString(IDS_PLAYLISTSTRING, p, size - (p - buf)); + p += lstrlenA(p) + 1; + playlistManager->GetFilterList(playlistString, 1024); + WideCharToMultiByteSZ(CP_ACP, 0, playlistString, -1, p, (int)size, 0, 0); + p += lstrlenA(p) + 1; + for ( x = 0; x < in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + while ( a && *a ) + { + char* b = a; + a += lstrlenA(a) + 1; + if ( !*a ) break; + StringCchCopyExA(p, size, a, &p, &size, 0); + p++; + { + do + { + char* c; + StringCchCopyA(p, size, "*."); + StringCchCatA(p, size, b); + if ( (b = strstr(b, ";")) ) b++; + if ( (c = strstr(p, ";")) ) c[1] = 0; + + p += lstrlenA(p); + } while ( b ); + p++; + a += lstrlenA(a) + 1; + } + } + } + StringCchCopyExA(p, size, getString(IDS_OFD_ALL_FILES, NULL, 0), &p, &size, 0); + p++; size--; + lstrcpynA(p, "*.*", (int)size); + p += 3; + *p = 0; + + { + char* newbuf; + size = p + 5 - buf; + newbuf = (char*)GlobalAlloc(GPTR, size); + memcpy(newbuf, buf, size); + GlobalFree(buf); + return newbuf; + } +} + +static void AddFilterStringW(wchar_t* p, size_t& size, const char* a, BOOL skip) +{ + while ( a && *a ) + { + wchar_t* t = 0; + StringCchCatExW(p, size, ((*p) ? L";*." : L"*."), &t, &size, 0); + size_t extsize = 0; + while ( a[extsize] && a[extsize] != ';' ) + extsize++; + + *(t += MultiByteToWideCharSZ(CP_ACP, 0, a, (int)extsize, t, (int)size) - 1); + a += extsize + 1; + + if ( a[-1] ) continue; + if ( !*a ) break; + a += lstrlenA(a) + 1; + + // limit the length of the filter to fit into MAX_PATH otherwise + // if things go past this then mainly for the all supported type + // it can sometimes act like *.* due to where the filter is cut + if ( !skip && lstrlenW(p) >= MAX_PATH ) + { + // if we end with a . then need to fake things to act like a new + // filter since windows will interpret the . as a *.* which is bad + if ( *(p + MAX_PATH) == L'.' ) + { + *(p + MAX_PATH - 1) = 0; + *(p + MAX_PATH) = 0; + } + } + } +} + +static wchar_t* inc(wchar_t* p, size_t& size, int extra = 0) +{ + int len = lstrlenW(p) + extra; + size -= len; + p += len; + return p; +} + +wchar_t* in_getfltstrW(BOOL skip) +{ + int in_mod = -1; + int in_wave = -1; + size_t size = 256 * 1024; + wchar_t* buf = (wchar_t*)GlobalAlloc(GPTR, size * sizeof(wchar_t)); // this is gay, should have a growing buffer or somethin. + wchar_t* p = buf, * ps; + *p = 0; + size_t x = 0; + + { + int cnt = lstrlenW(getStringW(IDS_ALLTYPES, buf, size)) + 1; + p += cnt; size -= cnt; + if ( playlistManager ) + { + playlistManager->GetExtensionList(p, size); + size -= lstrlenW(p); + } + } + ps = p; + + for ( x = 0; x < in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + if ( a && *a ) + { + /* we want to skip in_mod and in_wave because they have TOO MANY extensions and we are limited to MAX_PATH (260) + we'll tack them at the end just in case we have enough room for 'em */ + if ( in_mod < 0 && !strncmp(a, "mod;", 4) ) + in_mod = (int)x; + else if ( in_wave < 0 && strstr(a, "aiff") ) // detection for in_wave. not the best but should work + in_wave = (int)x; + else AddFilterStringW(p, size, a, skip); + } + } + + /* add in_wave and in_mod last */ + if ( in_wave >= 0 ) + AddFilterStringW(p, size, in_modules[in_wave]->FileExtensions, skip); + + if ( in_mod >= 0 ) // fuck you in_mod :) + AddFilterStringW(p, size, in_modules[in_mod]->FileExtensions, skip); + + if ( *p ) + p += lstrlenW(p) + 1; // don't decrement size here cause it was done already + + // uppercase the extensions so is consistent as can be + CharUpperBuffW(ps, 256 * 1024 - (p - ps)); + + if ( playlistManager ) + { + wchar_t ext[512] = { 0 }; + playlistManager->GetExtensionList(ext, 512); + StringCchPrintfW(p, size, getStringW(IDS_PLAYLISTSTRING_NEW, NULL, 0), ext); + int cnt = lstrlenW(p) + 1; + p += cnt; size -= cnt; + StringCchCatW(p, size, ext); + p = inc(p, size, 1); + } + + for ( x = 0; x < in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + while ( a && *a ) + { + char* b = a; + a += lstrlenA(a) + 1; + if ( !*a ) break; + // adjust down by 1 so that we have the actual string length exluding null termination + int cnt = MultiByteToWideCharSZ(CP_ACP, 0, a, -1, p, (int)size) - 1; + p += cnt; size -= cnt; + { + do + { + wchar_t* c = 0; + StringCchCopyW(p, size, L"*."); + StringCchCatW(p, size, AutoWide(b)); + if ( (b = strstr(b, ";")) ) b++; + if ( (c = wcsstr(p, L";")) ) c[1] = 0; + + p = inc(p, size); + } while ( b ); + p++; + size--; + a += lstrlenA(a) + 1; + } + } + } + StringCchCopyExW(p, size, getStringW(IDS_OFD_ALL_FILES, NULL, 0), &p, &size, 0); + p++; size--; + lstrcpynW(p, L"*.*", (int)size); + p += 3; + *p = 0; + + { + wchar_t* newbuf = 0; + size = p + 5 - buf; + newbuf = (wchar_t*)GlobalAlloc(GPTR, size * sizeof(wchar_t)); + memcpy(newbuf, buf, size * sizeof(wchar_t)); + GlobalFree(buf); + return newbuf; + } +} + +char* in_getextlist() +{ + size_t x; + char* mem = NULL, * p; + int size = 1024; + std::vector<LPSTR> exts; + + for ( x = 0; x != in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + while ( a && *a ) + { + char* b = a, * c = 0; + do + { + c = strstr(b, ";"); + if ( c ) + { + char temp[32] = { 0 }; + lstrcpynA(temp, b, c - b + 1); + int count = CharUpperBuffA(temp, ARRAYSIZE(temp)); + + bool skip = false; + for ( size_t i = 0; i < exts.size(); i++ ) + { + if ( !stricmp(exts[i], temp) ) + { + skip = true; + break; + } + } + if ( !skip ) + { + exts.push_back(_strdup(temp)); + size += count + 2; + } + } + else + { + char temp[32] = { 0 }; + lstrcpynA(temp, b, c - b + 1); + int count = CharUpperBuffA(temp, ARRAYSIZE(temp)); + + bool skip = false; + for ( size_t i = 0; i < exts.size(); i++ ) + { + if ( !stricmp(exts[i], temp) ) + { + skip = true; + break; + } + } + if ( !skip ) + { + exts.push_back(_strdup(temp)); + size += count + 2; + } + } + b = c + 1; + } while ( c && *c ); + + a += lstrlenA(a) + 1; + if ( !*a ) break; + a += lstrlenA(a) + 1; + } + } + + + if ( size > 0 ) + { + p = mem = (char*)GlobalAlloc(GPTR, size); + + for ( x = 0; x != exts.size(); x++ ) + { + char* e = exts[x]; + if ( e && *e ) + { + lstrcpynA(p, e, 32); + p += lstrlenA(p) + 1; + free(e); + } + } + + *p = 0; + } + + return mem; +} + +wchar_t* in_getextlistW() +{ + size_t x = 0; + wchar_t* mem = NULL, * p = 0; + int size = 0; + std::vector<LPWSTR> exts; + + for ( x = 0; x != in_modules.size(); x++ ) + { + char* a = in_modules[x]->FileExtensions; + while ( a && *a ) + { + char* b = a, * c; + do + { + wchar_t temp[32] = { 0 }; + c = strstr(b, ";"); + if ( c ) + { + int count = MultiByteToWideChar(CP_ACP, 0, b, c - b, 0, 0); + MultiByteToWideChar(CP_ACP, 0, b, c - b, temp, count); + CharUpperBuffW(temp, ARRAYSIZE(temp)); + + bool skip = false; + for ( size_t i = 0; i < exts.size(); i++ ) + { + if ( !wcsicmp(exts[i], temp) ) + { + skip = true; + break; + } + } + if ( !skip ) + { + exts.push_back(_wcsdup(temp)); + size += count + 2; + } + } + else + { + int count = MultiByteToWideChar(CP_ACP, 0, b, -1, 0, 0); + MultiByteToWideChar(CP_ACP, 0, b, -1, temp, count); + CharUpperBuffW(temp, ARRAYSIZE(temp)); + + bool skip = false; + for ( size_t i = 0; i < exts.size(); i++ ) + { + if ( !wcsicmp(exts[i], temp) ) + { + skip = true; + break; + } + } + if ( !skip ) + { + exts.push_back(_wcsdup(temp)); + size += count + 2; + } + } + b = c + 1; + } while ( c && *c ); + + a += lstrlenA(a) + 1; + if ( !*a ) break; + a += lstrlenA(a) + 1; + } + } + + if ( size > 0 ) + { + p = mem = (wchar_t*)GlobalAlloc(GPTR, size * sizeof(wchar_t)); + + for ( x = 0; x != exts.size(); x++ ) + { + wchar_t* e = exts[x]; + if ( e && *e ) + { + lstrcpynW(p, e, 32); + p += lstrlenW(p) + 1; + free(e); + } + } + *p = 0; + } + + return mem; +} + +static void vissa_init(int maxlatency_in_ms, int srate) +{ + g_srate_exact = srate; + int nf = MulDiv(maxlatency_in_ms * 4, srate, 450000); + //int nf = maxlatency_in_ms/5; + sa_init(nf); + vsa_init(nf); + vu_init(nf, srate); +} + +static void vissa_deinit() +{ + sa_deinit(); + vsa_deinit(); + vu_deinit(); +} + +static void setinfo(int bitrate, int srate, int stereo, int synched) +{ + int last_brate = g_brate, last_srate = g_srate, last_nch = g_nch; + + if ( stereo != -1 ) + { + g_nch = stereo; + // dynamic channels + if ( g_nch > 0 ) + { + if ( NULL != eq ) { free(eq); eq = NULL; } + eq = (eq10_t*)calloc(g_nch, sizeof(eq10_t)); + if ( NULL == eq ) + { + // bad. Need to handle this. + g_nch = 0; + } + eq_set(config_use_eq, (char*)eq_tab, config_preamp); + } + } + + if ( bitrate != -1 && srate != -1 ) + { + g_need_titleupd = 1; + } + + if ( bitrate != -1 ) + g_brate = bitrate; + if ( srate != -1 ) + { + g_srate = srate; + switch ( srate ) + { + case 11: + g_srate_exact = 11025; break; + case 22: + g_srate_exact = 22050; break; + case 44: + g_srate_exact = 44100; break; + case 88: + g_srate_exact = 88200; break; + default: + g_srate_exact = srate * 1000; break; + } + } + + if ( bitrate != -1 || srate != -1 || stereo != -1 ) + { + static unsigned int last_t; + unsigned int now = GetTickCount(); + + //detect wrap with the first one + if ( now < last_t || now > last_t + 500 || last_brate != g_brate || last_srate != g_srate || last_nch != g_nch ) + { + last_t = now; + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_INFO, IPC_CB_MISC); + } + } + + if ( synched != -1 || stereo != -1 ) + { + g_need_infoupd = synched | (stereo != -1 ? 8 : 4) | (g_need_infoupd & 8); + } +} + +static int sa_getmode() +{ + if ( sa_override ) return 3; + + if ( sa_curmode == 4 && !config_mw_open && config_pe_open ) + return 1; + return sa_curmode; +} + +static int eq_isactive() +{ + int r = dsp_isactive(); + if ( r ) return 1; + if ( in_mod && !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN) && config_replaygain.GetBool() && (config_replaygain_non_rg_gain.GetFloat() != 0) ) return 1; + if ( in_mod && !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN_PREAMP) && config_replaygain.GetBool() && (config_replaygain_preamp.GetFloat() != 0) ) return 1; + if ( filter_enabled ) return 2; + return 0; +} + +static float eq_lookup1[64] = { + 4.000000f, 3.610166f, 3.320019f, 3.088821f, 2.896617f, + 2.732131f, 2.588368f, 2.460685f, 2.345845f, 2.241498f, + 2.145887f, 2.057660f, 1.975760f, 1.899338f, 1.827707f, + 1.760303f, 1.696653f, 1.636363f, 1.579094f, 1.524558f, + 1.472507f, 1.422724f, 1.375019f, 1.329225f, 1.285197f, + 1.242801f, 1.201923f, 1.162456f, 1.124306f, 1.087389f, + 1.051628f, 1.000000f, 0.983296f, 0.950604f, 0.918821f, + 0.887898f, 0.857789f, 0.828454f, 0.799853f, 0.771950f, + 0.744712f, 0.718108f, 0.692110f, 0.666689f, 0.641822f, + 0.617485f, 0.593655f, 0.570311f, 0.547435f, 0.525008f, + 0.503013f, 0.481433f, 0.460253f, 0.439458f, 0.419035f, + 0.398970f, 0.379252f, 0.359868f, 0.340807f, 0.322060f, + 0.303614f, 0.285462f, 0.267593f, 0.250000f +}; + +///////////////// EQ CODE ///////////////////////// + +static int __inline float_to_int(double a) +{ + a += ((((65536.0 * 65536.0 * 16) + (65536.0 * 0.5)) * 65536.0)); + return ((*(int*)&a) - 0x80000000); +} + +float* splbuf = 0; +int splbuf_alloc = 0; +float eqt[10] = { 0 }; + +static void FillFloat(float* floatBuf, void* samples, size_t bps, size_t numSamples, size_t numChannels, float preamp) +{ + nsutil_pcm_IntToFloat_Interleaved_Gain(floatBuf, samples, (int)bps, numSamples * numChannels, preamp); +} + +static void FillSamples(void* samples, float* floatBuf, size_t bps, size_t numSamples, size_t numChannels) +{ + nsutil_pcm_FloatToInt_Interleaved(samples, floatBuf, (int)bps, numSamples * numChannels); +} + +static float NonReplayGainAdjust() +{ + if ( !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN) && config_replaygain.GetBool() ) + return pow(10.0f, (float)config_replaygain_non_rg_gain / 20.0f); + else + return 1.0f; +} + +static float ReplayGainPreamp() +{ + if ( !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN_PREAMP) && config_replaygain.GetBool() ) + return pow(10.0f, (float)config_replaygain_preamp / 20.0f); + else + return 1.0f; +} + +static int eq_dosamples_4front(short* samples, int numsamples, int bps, int nch, int srate) +{ + g_srate_exact = srate; + //char *csamples = (char *)samples; + short* oldsamples = samples; + + if ( filter_enabled && in_mod && !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_EQ) ) + { + if ( !eq || filter_srate != srate ) + { + if ( !eq ) eq = (eq10_t*)calloc(nch, sizeof(eq10_t)); + eq10_setup(eq, nch, (float)srate); // initialize + for ( int x = 0; x < 10; x++ ) + eq10_setgain(eq, nch, x, eqt[x]); + filter_srate = srate; + } + if ( splbuf_alloc < numsamples * nch ) + { + int new_splbuf_alloc = numsamples * nch; + float* new_splbuf = (float*)realloc(splbuf, 2 * sizeof(float) * new_splbuf_alloc); + if ( new_splbuf ) + { + splbuf_alloc = new_splbuf_alloc; + splbuf = new_splbuf; + } + } + if ( splbuf && eq ) + { + int y = nch * numsamples; + FillFloat(splbuf, samples, bps, numsamples, nch, preamp_val * NonReplayGainAdjust() * ReplayGainPreamp()); + for ( int x = 0; x < nch; x++ ) + { + eq10_processf(eq + x, splbuf, splbuf + y, numsamples, x, nch); + } + FillSamples(samples, splbuf + y, bps, numsamples, nch); + } + } + else if ( !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN) && config_replaygain.GetBool() && (config_replaygain_non_rg_gain.GetFloat() != 0) ) + { + if ( splbuf_alloc < numsamples * nch ) + { + int new_splbuf_alloc = numsamples * nch; + float* new_splbuf = (float*)realloc(splbuf, 2 * sizeof(float) * new_splbuf_alloc); + if ( new_splbuf ) + { + splbuf_alloc = new_splbuf_alloc; + splbuf = new_splbuf; + } + } + if ( splbuf ) + { + FillFloat(splbuf, samples, bps, numsamples, nch, NonReplayGainAdjust() * ReplayGainPreamp()); + FillSamples(samples, splbuf, bps, numsamples, nch); + } + } + else if ( !(in_mod->UsesOutputPlug & IN_MODULE_FLAG_REPLAYGAIN_PREAMP) && config_replaygain.GetBool() && (config_replaygain_preamp.GetFloat() != 0) ) + { + if ( splbuf_alloc < numsamples * nch ) + { + int new_splbuf_alloc = numsamples * nch; + float* new_splbuf = (float*)realloc(splbuf, 2 * sizeof(float) * new_splbuf_alloc); + if ( new_splbuf ) + { + splbuf_alloc = new_splbuf_alloc; + splbuf = new_splbuf; + } + } + if ( splbuf ) + { + FillFloat(splbuf, samples, bps, numsamples, nch, ReplayGainPreamp()); + FillSamples(samples, splbuf, bps, numsamples, nch); + } + } + else + filter_srate = 0; + return dsp_dosamples(oldsamples, numsamples, bps, nch, srate); +} + +static __inline double VALTODB(int v) +{ + v -= 31; + if ( v < -31 ) v = -31; + if ( v > 32 ) v = 32; + + if ( v > 0 ) return -12.0 * (v / 32.0); + else if ( v < 0 ) + { + return -12.0 * (v / 31.0); + } + return 0.0f; +} + +static void eq_set_4front(char data[10]) +{ + if ( !eq ) + return; + + for ( int x = 0; x < 10; x++ ) + { + eqt[x] = (float)VALTODB(data[x]); + if ( filter_srate ) eq10_setgain(eq, g_nch, x, eqt[x]); + } +} + +static bool eq_do_first = true; +static int startup_config_eq_type = EQ_TYPE_4FRONT; +void benskiQ_eq_set(char data[10]); +void eq_set(int on, char data[10], int preamp) +{ + if ( eq_do_first ) + { + startup_config_eq_type = config_eq_type; + eq_do_first = false; + } + + int x; + if ( in_mod && in_mod->EQSet ) in_mod->EQSet(on, data, preamp); + + for ( x = 9; x >= 0 && data[x] == 31; x++ ); + if ( x >= 0 ) + filter_top2 = x; + + for ( x = 0; x < 10 && data[x] == 31; x++ ); + if ( !on || (preamp == 31 && x == 10) ) + { + filter_enabled = 0; + } + else filter_enabled = 1; + preamp_val = (float)eq_lookup1[preamp]; + + if ( startup_config_eq_type == EQ_TYPE_4FRONT ) + eq_set_4front(data); + if ( startup_config_eq_type == EQ_TYPE_CONSTANT_Q ) + benskiQ_eq_set(data); +} + +static int eq_dosamples(short* samples, int numsamples, int bps, int nch, int srate) +{ + if ( eq_do_first ) + { + startup_config_eq_type = config_eq_type; + eq_do_first = false; + } + if ( startup_config_eq_type == EQ_TYPE_4FRONT ) + return eq_dosamples_4front(samples, numsamples, bps, nch, srate); + else + return benskiQ_eq_dosamples(samples, numsamples, bps, nch, srate); +}
\ No newline at end of file |