Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
839
Src/Winamp/VIS.cpp
Normal file
839
Src/Winamp/VIS.cpp
Normal file
|
@ -0,0 +1,839 @@
|
|||
#include <windowsx.h>
|
||||
|
||||
#include "Main.h"
|
||||
#include "vis.h"
|
||||
#include "fft.h"
|
||||
#include <bfc/platform/types.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "./api.h"
|
||||
#include "../nsutil/window.h"
|
||||
#include "../nu/threadname.h"
|
||||
|
||||
static winampVisModule *vis_mod;
|
||||
static DWORD WINAPI vis_thread(void *tmp);
|
||||
static HANDLE hThread;
|
||||
static DWORD visThreadId=0;
|
||||
static volatile int killThread;
|
||||
static int _nch = 2, _numframes=1;
|
||||
int _srate = 44100;
|
||||
static wchar_t _visplugin_name[512];
|
||||
static int _visplugin_num;
|
||||
static char *vsa_data;
|
||||
static int vsa_position, vsa_entrysize=577*4;
|
||||
static int vsa_length,size=576*4;
|
||||
static int vis_stopping;
|
||||
static CRITICAL_SECTION cs;
|
||||
static HWND external_window = NULL;
|
||||
static HWND external_window_host = NULL;
|
||||
|
||||
#ifdef _M_IX86
|
||||
__inline static int lrint(float flt)
|
||||
{
|
||||
int intgr;
|
||||
|
||||
_asm
|
||||
{
|
||||
fld flt
|
||||
fistp intgr
|
||||
}
|
||||
|
||||
return intgr;
|
||||
}
|
||||
#else
|
||||
__inline static int lrint(float flt)
|
||||
{
|
||||
return (int)flt;
|
||||
}
|
||||
#endif
|
||||
|
||||
// quantizes to 23 bits - use appropriately
|
||||
#define FASTMIN(x,b) { x = b - x; x += (float)fabs(x); x *= 0.5f; x = b - x; }
|
||||
|
||||
static size_t vis_refCount=0;
|
||||
static winampVisModule *GetVis()
|
||||
{
|
||||
winampVisModule *ret = 0;
|
||||
EnterCriticalSection(&cs);
|
||||
if (vis_stopping)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
if (vis_mod)
|
||||
{
|
||||
ret = vis_mod;
|
||||
vis_refCount++;
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void DestroyVis()
|
||||
{
|
||||
killThread=1;
|
||||
vis_stopping=1;
|
||||
|
||||
if (GetCurrentThreadId() != visThreadId)
|
||||
{
|
||||
HANDLE thisThread = hThread;
|
||||
LeaveCriticalSection(&cs);
|
||||
|
||||
// run message pump. this shouldn't last long.
|
||||
int x=200;
|
||||
while (WaitForSingleObject(thisThread,10) == WAIT_TIMEOUT && x-- > 0)
|
||||
{
|
||||
WASABI_API_APP->app_messageLoopStep();
|
||||
}
|
||||
WaitForSingleObject(thisThread,INFINITE);
|
||||
EnterCriticalSection(&cs);
|
||||
}
|
||||
|
||||
CloseHandle(hThread);
|
||||
if (vis_mod)
|
||||
FreeLibrary(vis_mod->hDllInstance);
|
||||
vis_stopping=0;
|
||||
vis_mod=0;
|
||||
|
||||
hThread=0;
|
||||
killThread=0;
|
||||
}
|
||||
|
||||
static void ReleaseVis(winampVisModule *vis)
|
||||
{
|
||||
if (vis)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
vis_refCount--;
|
||||
if (vis_refCount == 0)
|
||||
{
|
||||
DestroyVis();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
}
|
||||
|
||||
void vis_init(void)
|
||||
{
|
||||
InitializeCriticalSectionAndSpinCount(&cs, 4000);
|
||||
}
|
||||
|
||||
static char *vsa_get(int timestamp);
|
||||
static void vsa_setdatasize();
|
||||
|
||||
int vis_running()
|
||||
{
|
||||
int running=0;
|
||||
winampVisModule *vis = GetVis();
|
||||
if (vis)
|
||||
{
|
||||
running = !vis_stopping;
|
||||
ReleaseVis(vis);
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
static int priorities[5] =
|
||||
{
|
||||
THREAD_PRIORITY_LOWEST,
|
||||
THREAD_PRIORITY_BELOW_NORMAL,
|
||||
THREAD_PRIORITY_NORMAL,
|
||||
THREAD_PRIORITY_ABOVE_NORMAL,
|
||||
THREAD_PRIORITY_HIGHEST
|
||||
};
|
||||
|
||||
void vis_start(HWND hwnd, wchar_t *fn)
|
||||
{
|
||||
if (vis_stopping || g_safeMode) return;
|
||||
vis_stop();
|
||||
vsa_deinit();
|
||||
if (!config_visplugin_name[0]) return;
|
||||
|
||||
killThread=0;
|
||||
if (!fn || !*fn)
|
||||
{
|
||||
PathCombineW(_visplugin_name, VISDIR, config_visplugin_name);
|
||||
_visplugin_num=config_visplugin_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t buf[MAX_PATH] = {0};
|
||||
wchar_t *p;
|
||||
StringCchCopyW(buf,MAX_PATH,fn);
|
||||
p=wcsstr(buf,L",");
|
||||
if (p)
|
||||
{
|
||||
*p++=0;
|
||||
_visplugin_num=_wtoi(p);
|
||||
}
|
||||
else _visplugin_num=0;
|
||||
if (PathIsFileSpecW(buf) || PathIsRelativeW(buf))
|
||||
PathCombineW(_visplugin_name, VISDIR, buf);
|
||||
else
|
||||
StringCchCopyW(_visplugin_name,512,buf);
|
||||
}
|
||||
hThread = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) vis_thread,NULL,0,&visThreadId);
|
||||
SetThreadPriority(hThread,priorities[config_visplugin_priority]);
|
||||
}
|
||||
|
||||
void vis_setprio()
|
||||
{
|
||||
if (vis_stopping) return;
|
||||
if (hThread) SetThreadPriority(hThread,priorities[config_visplugin_priority]);
|
||||
}
|
||||
|
||||
void vis_stop()
|
||||
{
|
||||
if (vis_stopping||!hThread) return;
|
||||
EnterCriticalSection(&cs); // go into critical section so vis_mod doesn't suddenly appear out of nowhere
|
||||
winampVisModule *thisVis = vis_mod;
|
||||
LeaveCriticalSection(&cs);
|
||||
ReleaseVis(thisVis);
|
||||
}
|
||||
|
||||
void vis_setinfo(int srate, int nch)
|
||||
{
|
||||
if (srate > 0) _srate = srate;
|
||||
if (nch > 0) _nch = nch;
|
||||
if (!vis_running()) return;
|
||||
EnterCriticalSection(&cs);
|
||||
winampVisModule *vis = GetVis();
|
||||
if (vis)
|
||||
{
|
||||
vis->sRate = _srate;
|
||||
vis->nCh = _nch;
|
||||
ReleaseVis(vis);
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
void vis_setextwindow(HWND hwnd)
|
||||
{
|
||||
HWND test_window;
|
||||
unsigned int test_window_style_ex;
|
||||
unsigned long window_thread_id;
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
external_window = hwnd;
|
||||
external_window_host = external_window;
|
||||
|
||||
window_thread_id = GetWindowThreadProcessId(external_window, NULL);
|
||||
while(NULL != external_window_host)
|
||||
{
|
||||
test_window = GetAncestor(external_window_host, GA_PARENT);
|
||||
if (NULL != test_window &&
|
||||
window_thread_id == GetWindowThreadProcessId(test_window, NULL))
|
||||
{
|
||||
test_window_style_ex = (unsigned int)GetWindowLongPtrW(test_window, GWL_STYLE);
|
||||
if (0 != (WS_EX_CONTROLPARENT & test_window_style_ex))
|
||||
{
|
||||
external_window_host = test_window;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
static winampVisModule *CreateVis(HINSTANCE visLib)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
winampVisModule *ret = 0;
|
||||
ret = GetVis();
|
||||
if (ret)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
winampVisGetHeaderType pr;
|
||||
pr = (winampVisGetHeaderType) GetProcAddress(visLib,"winampVisGetHeader");
|
||||
if (!pr)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
winampVisHeader* pv = pr(hMainWindow);
|
||||
if (!pv)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vis_mod = pv->getModule(_visplugin_num);
|
||||
if (!vis_mod)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vis_mod->sRate = _srate;
|
||||
vis_mod->nCh = _nch;
|
||||
vis_mod->hwndParent = hMainWindow;
|
||||
vis_mod->hDllInstance = visLib;
|
||||
|
||||
vis_refCount++;
|
||||
LeaveCriticalSection(&cs);
|
||||
return vis_mod;
|
||||
}
|
||||
|
||||
static BOOL vis_process_message(MSG *msg)
|
||||
{
|
||||
if (msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST &&
|
||||
msg->hwnd == external_window &&
|
||||
NULL != external_window)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (WM_MOUSEWHEEL == msg->message &&
|
||||
NULL != external_window_host)
|
||||
{
|
||||
POINT cursor;
|
||||
HWND target_window;
|
||||
|
||||
POINTSTOPOINT(cursor, msg->lParam);
|
||||
target_window = WindowFromPoint(cursor);
|
||||
|
||||
if (NULL != target_window &&
|
||||
FALSE == IsChild(external_window_host, target_window ) &&
|
||||
GetWindowThreadProcessId(target_window, NULL) != GetWindowThreadProcessId(external_window_host, NULL))
|
||||
{
|
||||
PostMessageW(hMainWindow, msg->message, msg->wParam, msg->lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (NULL != external_window_host)
|
||||
return IsDialogMessageW(external_window_host, msg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static DWORD WINAPI vis_thread(void *tmp)
|
||||
{
|
||||
winampVisModule *vis = 0;
|
||||
MSG Msg;
|
||||
HINSTANCE hLib=0;
|
||||
int t=0;
|
||||
SetThreadName((DWORD)-1, "Vis (plugin) thread");
|
||||
hLib = LoadLibrary(_visplugin_name);
|
||||
if (!hLib)
|
||||
{
|
||||
t=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vis = CreateVis(hLib);
|
||||
if (!vis)
|
||||
{
|
||||
FreeLibrary(hLib);
|
||||
hLib = 0;
|
||||
t=1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!t)
|
||||
{
|
||||
if (!(config_no_visseh&1))
|
||||
{
|
||||
__try
|
||||
{
|
||||
t = (vis ? vis->Init(vis) : 1);
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
t=1;
|
||||
char errstr[512] = {0};
|
||||
char caption[512] = {0};
|
||||
getString(IDS_PLUGINERROR,errstr,512);
|
||||
StringCchCatA(errstr, 512, " (1)");
|
||||
MessageBoxA(NULL,errstr,getString(IDS_ERROR,caption,512),MB_OK|MB_ICONEXCLAMATION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t = vis->Init(vis);
|
||||
}
|
||||
}
|
||||
|
||||
if (!t)
|
||||
{
|
||||
if (config_disvis) sa_setthread(0);
|
||||
vsa_setdatasize();
|
||||
|
||||
while (!killThread)
|
||||
{
|
||||
if (PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
|
||||
{
|
||||
if (Msg.message == WM_QUIT)
|
||||
break;
|
||||
|
||||
if (FALSE == vis_process_message(&Msg))
|
||||
{
|
||||
TranslateMessage(&Msg);
|
||||
DispatchMessage(&Msg);
|
||||
}
|
||||
}
|
||||
else if (!paused)
|
||||
{
|
||||
static int upd;
|
||||
int p=playing;
|
||||
char *data=0;
|
||||
if (in_mod && p) data = vsa_get(in_mod->GetOutputTime()+vis->latencyMs);
|
||||
if (data)
|
||||
{
|
||||
int l=vis->spectrumNch;
|
||||
for (int n = 0; n < l; n ++)
|
||||
{
|
||||
memcpy(vis->spectrumData[n],data,576);
|
||||
data += 576;
|
||||
}
|
||||
l=vis->waveformNch;
|
||||
for (int n = 0; n < l; n ++)
|
||||
{
|
||||
memcpy(vis->waveformData[n],data,576);
|
||||
data += 576;
|
||||
}
|
||||
}
|
||||
if (!data)
|
||||
{
|
||||
memset(vis->spectrumData,0,576*2);
|
||||
memset(vis->waveformData,0,576*2);
|
||||
}
|
||||
if (p) upd=1;
|
||||
if (upd)
|
||||
if (!(config_no_visseh&1))
|
||||
{
|
||||
__try
|
||||
{
|
||||
if (vis->Render(vis))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
char errstr[512] = {0};
|
||||
char caption[512] = {0};
|
||||
getString(IDS_PLUGINERROR,errstr,512);
|
||||
StringCchCatA(errstr, 512, " (2)");
|
||||
MessageBoxA(NULL,errstr,getString(IDS_ERROR,caption,512),MB_OK|MB_ICONEXCLAMATION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vis->Render(vis))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p) upd=0;
|
||||
Sleep(vis->delayMs);
|
||||
}
|
||||
else Sleep(min(1,vis->delayMs));
|
||||
}
|
||||
vsa_deinit();
|
||||
sa_setthread(config_sa);
|
||||
if (!(config_no_visseh&1))
|
||||
{
|
||||
__try
|
||||
{
|
||||
vis->Quit(vis);
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
wchar_t errstr[512] = {0};
|
||||
wchar_t caption[512] = {0};
|
||||
getStringW(IDS_PLUGINERROR,errstr,512);
|
||||
StringCchCatW(errstr, 512, L" (3)");
|
||||
MessageBoxW(NULL,errstr,getStringW(IDS_ERROR,caption,512),MB_OK|MB_ICONEXCLAMATION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vis->Quit(vis);
|
||||
}
|
||||
EnterCriticalSection(&cs);
|
||||
if (killThread)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseVis(vis);
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseVis(vis);
|
||||
if (hLib)
|
||||
FreeLibrary(hLib);
|
||||
hLib = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int last_pos;
|
||||
|
||||
static void _vsa_init()
|
||||
{
|
||||
vsa_deinit();
|
||||
if (_numframes < 1) _numframes=1;
|
||||
vsa_entrysize = 4+size;
|
||||
vsa_data = (char *) GlobalAlloc(GPTR,vsa_entrysize * _numframes);
|
||||
vsa_position=0;
|
||||
vsa_length = _numframes;
|
||||
}
|
||||
|
||||
void vsa_init(int numframes)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
if (vis_running())
|
||||
{
|
||||
last_pos=0;
|
||||
_numframes=numframes;
|
||||
_vsa_init();
|
||||
}
|
||||
else
|
||||
{
|
||||
last_pos=0;
|
||||
_numframes=numframes;
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
static void vsa_setdatasize()
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
winampVisModule *vis = GetVis();
|
||||
if (vis)
|
||||
{
|
||||
size=576*(vis->waveformNch+vis->spectrumNch);
|
||||
_vsa_init();
|
||||
ReleaseVis(vis);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
int vsa_add(void *data, int timestamp)
|
||||
{
|
||||
if (!vsa_data) return 1;
|
||||
EnterCriticalSection(&cs);
|
||||
if (vsa_data) // check again, it might have gone away while we were waiting on the CS
|
||||
{
|
||||
if (vsa_length < 2)
|
||||
{
|
||||
vsa_position = 0;
|
||||
}
|
||||
char *c = vsa_data + vsa_position*vsa_entrysize;
|
||||
*(int32_t *)c=timestamp;
|
||||
|
||||
memcpy(c+4,data,vsa_entrysize-4);
|
||||
if (++vsa_position >= vsa_length) vsa_position -= vsa_length;
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void vsa_deinit(void)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
if (vsa_data)
|
||||
{
|
||||
GlobalFree(vsa_data);
|
||||
vsa_data=0;
|
||||
vsa_length=0;
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
static char *vsa_get(int timestamp)
|
||||
{
|
||||
int i,x, closest=1000000, closest_v = -1;
|
||||
if (!vsa_data) return NULL;
|
||||
if (vsa_length<2)
|
||||
{
|
||||
return vsa_data+4;
|
||||
}
|
||||
EnterCriticalSection(&cs);
|
||||
x=last_pos;
|
||||
if (x >= vsa_length) x=0;
|
||||
for (i = 0; i < vsa_length; i ++)
|
||||
{
|
||||
int *q = (int *)(vsa_data+x*vsa_entrysize);
|
||||
int d = timestamp-*q;
|
||||
if (++x == vsa_length) x=0;
|
||||
if (d < 0) d = -d;
|
||||
if (d < closest)
|
||||
{
|
||||
closest = d;
|
||||
closest_v = x;
|
||||
}
|
||||
else if (closest<200) break;
|
||||
}
|
||||
if (closest_v >= 0)
|
||||
{
|
||||
static char data[576*4];
|
||||
last_pos=closest_v;
|
||||
memcpy(data,vsa_data+vsa_entrysize*closest_v+4,vsa_entrysize-4);
|
||||
LeaveCriticalSection(&cs);
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int vsa_getmode(int *sp, int *wa)
|
||||
{
|
||||
int rv=0;
|
||||
winampVisModule *vis = GetVis();
|
||||
if (vis)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
*sp=vis->spectrumNch;
|
||||
*wa=vis->waveformNch;
|
||||
rv=1;
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
ReleaseVis(vis);
|
||||
}
|
||||
else *sp=*wa=0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void FillRealSamples_8Bit(unsigned char *data, const int stride, const int channels, float *samples, const float divider)
|
||||
{
|
||||
int frame,c;
|
||||
const float p = (float)channels*divider;
|
||||
|
||||
for (frame = 0; frame <512; frame ++)
|
||||
{
|
||||
//done by memset - samples[x*2]=0;
|
||||
for (c=0;c<channels;c++)
|
||||
{
|
||||
samples[frame] += (float)(*data - 128);
|
||||
data+=stride; // jump to the next sample (channels are interleaved)
|
||||
}
|
||||
|
||||
samples[frame] /= p;
|
||||
//done by memset - wavetrum[x*2+1] = 0.0f;
|
||||
}
|
||||
nsutil_window_Hann_F32_IP(samples, 512);
|
||||
}
|
||||
|
||||
#define SA_DC_FILTER
|
||||
void FillRealSamples(char *ptr, const int stride, const int channels, float *samples, const float divider)
|
||||
{
|
||||
#ifdef SA_DC_FILTER
|
||||
float x1=0, y1=0;
|
||||
#endif
|
||||
int frame, c;
|
||||
const float p=(float)channels * divider;
|
||||
|
||||
// we're calculating using only the most significant byte,
|
||||
// because we only end up with 6 bit data anyway
|
||||
// if you want full resolution, check out CVS tag BETA_2005_1122_182830, file: vis.c
|
||||
|
||||
for (frame = 0;frame <512;frame++)
|
||||
{
|
||||
//done by memset - wavetrum[x*2]=0;
|
||||
float x=0;
|
||||
for (c=0;c<channels;c++)
|
||||
{
|
||||
x += (float)(*ptr);
|
||||
ptr+=stride; // jump to the next sample (channels are interleaved)
|
||||
}
|
||||
#ifdef SA_DC_FILTER
|
||||
float y = x - x1 + 0.99f * y1;
|
||||
y1=y;
|
||||
x1=x;
|
||||
#else
|
||||
float y=x;
|
||||
#endif
|
||||
y/=p;
|
||||
|
||||
samples[frame]=y;
|
||||
//done by memset - wavetrum[x*2+1] = 0.0f;
|
||||
}
|
||||
nsutil_window_Hann_F32_IP(samples, 512);
|
||||
}
|
||||
|
||||
void vsa_addpcmdata(void *_data_buf, int numChannels, int numBits, int ts)
|
||||
{
|
||||
char *data_buf = reinterpret_cast<char *>(_data_buf);
|
||||
// begin vis plugin stuff
|
||||
winampVisModule *vis = GetVis();
|
||||
if (vis)
|
||||
{
|
||||
__declspec(align(32)) float wavetrum[512];
|
||||
extern int vsa_add(void *data, int timestamp);
|
||||
char data[576*4*2] = {0};
|
||||
int data_offs=0;
|
||||
int y,x,spectrumChannels, waveformChannels, stride;
|
||||
|
||||
spectrumChannels=min(numChannels,vis->spectrumNch);
|
||||
stride=numBits/8;
|
||||
|
||||
for (y = 0; y < spectrumChannels; y ++)
|
||||
{
|
||||
if (spectrumChannels == 1) // downmix to mono, if necessary
|
||||
{
|
||||
if (numBits == 8)
|
||||
FillRealSamples_8Bit((unsigned char*)data_buf, 1, numChannels, wavetrum, 1.f);
|
||||
else
|
||||
{
|
||||
const int stride=numBits/8; // number of bytes between samples
|
||||
char *ptr = data_buf+y*stride+stride-1; // offset for little endian
|
||||
FillRealSamples(ptr, stride, numChannels, wavetrum, 1.f);
|
||||
}
|
||||
}
|
||||
else // TODO: deal with 'downmixing' to stereo if channels>2
|
||||
{
|
||||
if (numBits == 8)
|
||||
FillRealSamples_8Bit((unsigned char*)data_buf, numChannels, 1, wavetrum, 1.f);
|
||||
else
|
||||
{
|
||||
const int stride=numBits/8; // number of bytes between samples
|
||||
char *ptr = data_buf+y*stride+stride-1; // offset for little endian
|
||||
FillRealSamples(ptr, stride*numChannels, 1, wavetrum, 1.f);
|
||||
}
|
||||
}
|
||||
fft_9(wavetrum);
|
||||
{
|
||||
float la=0;
|
||||
int thisBand=0;
|
||||
|
||||
for (x = 0; x < 256; x ++)
|
||||
{
|
||||
float sinT = wavetrum[x*2];
|
||||
float cosT = wavetrum[x*2+1];
|
||||
|
||||
float thisValue=(float)sqrt(sinT*sinT+cosT*cosT)/16.0f;
|
||||
thisBand++;
|
||||
|
||||
FASTMIN(thisValue, 255.f);
|
||||
data[data_offs++] = lrint((thisValue + la)/2.f);
|
||||
//data[data_offs++] = lrint((thisValue + thisValue + la)/3.f);
|
||||
data[data_offs++] = lrint(thisValue);
|
||||
la=thisValue;
|
||||
}
|
||||
while ((data_offs % 576)!=0)
|
||||
{
|
||||
la/=2;
|
||||
data[data_offs++]=lrint(la);
|
||||
}
|
||||
|
||||
assert((data_offs % 576)==0);
|
||||
}
|
||||
}
|
||||
|
||||
if (numChannels == 1 && vis->spectrumNch == 2) // upmix, if necessary
|
||||
{
|
||||
memcpy(data+data_offs,data+data_offs-576,576);
|
||||
data_offs+=576;
|
||||
}
|
||||
|
||||
waveformChannels=min(numChannels,vis->waveformNch);
|
||||
if (waveformChannels == 1) // downmix to mono, if necessary
|
||||
{
|
||||
char *ptr = data_buf+stride-1; // offset for little endian
|
||||
for (x=0;x<576;x++)
|
||||
{
|
||||
__int32 mix=0;
|
||||
for (int channel=0;channel<numChannels;channel++)
|
||||
{
|
||||
mix += (*ptr);
|
||||
ptr+=stride; // jump to the next sample (channels are interleaved)
|
||||
}
|
||||
data[data_offs++] = (char)(mix / numChannels);
|
||||
}
|
||||
}
|
||||
else // TODO: deal with 'downmixing' to stereo if numChannels>2
|
||||
{
|
||||
for (y = 0; y < waveformChannels; y++)
|
||||
{
|
||||
char *ptr = data_buf+y*stride+stride-1; // offset for little endian
|
||||
for (x=0;x<576;x++)
|
||||
{
|
||||
data[data_offs++] = *ptr;
|
||||
ptr+=stride*numChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numChannels == 1 && vis->waveformNch == 2)
|
||||
{
|
||||
memcpy(data+data_offs,data+data_offs-576,576);
|
||||
//data_offs+=576;
|
||||
}
|
||||
vsa_add(data,ts);
|
||||
ReleaseVis(vis);
|
||||
}
|
||||
}
|
||||
|
||||
HWND hVisWindow, hPLVisWindow;
|
||||
|
||||
LRESULT CALLBACK VIS_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
RECT r1, r2;
|
||||
int xPos = GET_X_LPARAM(lParam); // horizontal position of cursor
|
||||
int yPos = GET_Y_LPARAM(lParam);
|
||||
if (hwnd == hVisWindow)
|
||||
{
|
||||
GetWindowRect(hMainWindow,&r1);
|
||||
}
|
||||
else GetWindowRect(hPLWindow,&r1);
|
||||
GetWindowRect(hwnd,&r2);
|
||||
xPos += r2.left-r1.left;
|
||||
yPos += r2.top-r1.top;
|
||||
lParam = MAKELPARAM(xPos,yPos);
|
||||
SendMessageW(hwnd == hVisWindow?hMainWindow:hPLWindow,message,wParam,lParam);
|
||||
return 0;
|
||||
}
|
||||
case WM_USER+0xebe:
|
||||
case WM_DROPFILES:
|
||||
return SendMessageW(GetParent(hwnd),message,wParam,lParam);
|
||||
case WM_CREATE:
|
||||
if (NULL != WASABI_API_APP)
|
||||
WASABI_API_APP->app_registerGlobalWindow(hwnd);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
if (NULL != WASABI_API_APP)
|
||||
WASABI_API_APP->app_unregisterGlobalWindow(hwnd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (FALSE != IsDirectMouseWheelMessage(message))
|
||||
{
|
||||
SendMessageW(hwnd, WM_MOUSEWHEEL, wParam, lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return DefWindowProcW(hwnd,message,wParam,lParam);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue