JACKY_ZZ[猫猫爱吃鱼]

春风拂面两颊红,秋叶洒地一片金。 夏荷摇曳一身轻,冬雪覆盖大地银。
posts - 30, comments - 123, trackbacks - 0, articles - 0

[C/C++] bass

Posted on 2010-11-19 16:53 jacky_zz 阅读(933) 评论(0)  编辑 收藏 引用
  1#define MAX_LOADSTRING 100
  2#define WM_BASSPLAY    (WM_USER + 100)
  3#define WM_BASSQUIT (WM_USER + 101)
  4
  5HINSTANCE hInst;
  6HWND hMainWindow;
  7TCHAR szTitle[MAX_LOADSTRING];
  8TCHAR szWindowClass[MAX_LOADSTRING];
  9HSTREAM hStream = NULL;
 10HANDLE hFile = NULL;
 11#define BLOCK_SIZE 17640
 12
 13In_Module* in_module;
 14Out_Module out_module;
 15
 16HMODULE hInputModule = NULL;
 17
 18ATOM                MyRegisterClass(HINSTANCE hInstance);
 19BOOL                InitInstance(HINSTANCE, int);
 20LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 21INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 22BOOL                Play();
 23BOOL                LoadWinampInputPlugin();
 24BOOL                UnloadWinampInputPlugin();
 25BOOL                LoadWinampOutputPlugin();
 26BOOL                UnloadWinampOutputPlugin();
 27
 28int APIENTRY _tWinMain(HINSTANCE hInstance,
 29                     HINSTANCE hPrevInstance,
 30                     LPTSTR    lpCmdLine,
 31                     int       nCmdShow)
 32{
 33    UNREFERENCED_PARAMETER(hPrevInstance);
 34    UNREFERENCED_PARAMETER(lpCmdLine);
 35
 36    MSG msg;
 37    HACCEL hAccelTable;
 38
 39    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 40    LoadString(hInstance, IDC_MINIBASSPLAYER, szWindowClass, MAX_LOADSTRING);
 41    MyRegisterClass(hInstance);
 42
 43    if (!InitInstance (hInstance, nCmdShow))
 44    {
 45        return FALSE;
 46    }

 47
 48    if(!BASS_Init(1441000, hMainWindow, NULL))
 49    {
 50        MessageBox(hMainWindow, "Could not initialize Bass library.""Error", MB_OK);
 51        return 0;
 52    }

 53
 54    BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, 10000);
 55
 56    if(!LoadWinampOutputPlugin())
 57    {
 58        BASS_Free();
 59        return FALSE;
 60    }

 61
 62    if(!LoadWinampInputPlugin())
 63    {
 64        UnloadWinampOutputPlugin();
 65        BASS_Free();
 66        return FALSE;
 67    }

 68
 69    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MINIBASSPLAYER));
 70
 71    while (GetMessage(&msg, NULL, 00))
 72    {
 73        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
 74        {
 75            TranslateMessage(&msg);
 76            DispatchMessage(&msg);
 77        }

 78    }

 79
 80    UnloadWinampOutputPlugin();
 81    UnloadWinampInputPlugin();
 82    BASS_Free();
 83    return (int) msg.wParam;
 84}

 85
 86ATOM MyRegisterClass(HINSTANCE hInstance)
 87{
 88    WNDCLASSEX wcex;
 89
 90    wcex.cbSize = sizeof(WNDCLASSEX);
 91
 92    wcex.style            = CS_HREDRAW | CS_VREDRAW;
 93    wcex.lpfnWndProc    = WndProc;
 94    wcex.cbClsExtra        = 0;
 95    wcex.cbWndExtra        = 0;
 96    wcex.hInstance        = hInstance;
 97    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MINIBASSPLAYER));
 98    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
 99    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
100    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_MINIBASSPLAYER);
101    wcex.lpszClassName    = szWindowClass;
102    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
103
104    return RegisterClassEx(&wcex);
105}

106
107BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
108{
109   HWND hWnd;
110
111   hInst = hInstance;
112
113   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
114      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
115
116   if (!hWnd)
117   {
118      return FALSE;
119   }

120
121   hMainWindow = hWnd;
122   ShowWindow(hWnd, nCmdShow);
123   UpdateWindow(hWnd);
124
125   return TRUE;
126}

127
128LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
129{
130    int wmId, wmEvent;
131    PAINTSTRUCT ps;
132    HDC hdc;
133
134    switch (message)
135    {
136    case WM_COMMAND:
137        wmId    = LOWORD(wParam);
138        wmEvent = HIWORD(wParam);
139
140        switch (wmId)
141        {
142        case IDM_ABOUT:
143            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
144            break;
145        case IDM_EXIT:
146            DestroyWindow(hWnd);
147            break;
148        case IDM_PLAY:
149            if(Play())
150            {
151                if(hStream)
152                {
153                    Sleep(1000);
154                    BASS_ChannelPlay(hStream, FALSE);
155                }

156
157                if(in_module)
158                    in_module->SetVolume(127);
159            }

160            break;
161        default:
162            return DefWindowProc(hWnd, message, wParam, lParam);
163        }

164        break;
165    case WM_PAINT:
166        hdc = BeginPaint(hWnd, &ps);
167        EndPaint(hWnd, &ps);
168        break;
169    case WM_DESTROY:
170        if(hFile != NULL && hFile != INVALID_HANDLE_VALUE)
171        {
172            CloseHandle(hFile);
173            hFile = NULL;
174        }

175
176        PostQuitMessage(0);
177        break;
178    case WM_BASSPLAY:
179        if(hStream)
180            BASS_ChannelPlay(hStream, FALSE);
181        break;
182    case WM_BASSQUIT:
183        if(hFile != NULL && hFile != INVALID_HANDLE_VALUE)
184        {
185            CloseHandle(hFile);
186            hFile = NULL;
187        }

188
189        BASS_ChannelStop(hStream);
190        BASS_StreamFree(hStream);
191        hStream = NULL;
192        break;
193    default:
194        return DefWindowProc(hWnd, message, wParam, lParam);
195    }

196    return 0;
197}

198
199INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
200{
201    UNREFERENCED_PARAMETER(lParam);
202    switch (message)
203    {
204    case WM_INITDIALOG:
205        return (INT_PTR)TRUE;
206
207    case WM_COMMAND:
208        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
209        {
210            EndDialog(hDlg, LOWORD(wParam));
211            return (INT_PTR)TRUE;
212        }

213        break;
214    }

215    return (INT_PTR)FALSE;
216}

217
218static DWORD readChunk(HANDLE hFile, void* buf, size_t size)
219{
220    DWORD readByes;
221    if(ReadFile(hFile, buf, size, &readByes, NULL) == FALSE)
222        return 0;
223
224    return readByes;
225}

226
227DWORD __stdcall StreamWriter(HSTREAM handle, void *buffer, DWORD length, void *user)
228{
229    if(hFile == NULL || hFile == INVALID_HANDLE_VALUE)
230        return BASS_STREAMPROC_END;
231
232    int len = (length < BLOCK_SIZE) ? length : BLOCK_SIZE;
233    DWORD dwReadBytes = 0;
234
235    if(!ReadFile(hFile, buffer, len, &dwReadBytes, NULL))
236    {
237        SendMessage(hMainWindow, WM_BASSQUIT, 00);
238        return BASS_STREAMPROC_END;
239    }

240
241    return len;
242}

243
244BOOL Play()
245{
246    //WAVEFORMATEX wfx;
247    //char riff[5], wave[5], fmt[5], data[5];
248    //DWORD len, struct_len, data_len;
249
250    //if((hFile = CreateFile(
251    //    "D:\\Music\\Love Story.wav", GENERIC_READ, FILE_SHARE_READ, NULL,
252    //        OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) {
253    //        ExitProcess(1);
254    //}
255
256    //readChunk(hFile, (void*)riff, 4);
257    //riff[4] = '\0';
258    //if(strncmp(riff, "RIFF", 4) == 0)
259    //{
260    //    readChunk(hFile, (void*)&len, 4);
261    //    readChunk(hFile, (void*)wave, 4);
262    //    readChunk(hFile, (void*)fmt, 4);
263    //    readChunk(hFile, (void*)&struct_len, 4);
264    //    readChunk(hFile, (void*)&wfx, struct_len);
265    //    readChunk(hFile, (void*)data, 4);
266    //    readChunk(hFile, (void*)&data_len, 4);
267    //}
268    //else
269    //    ExitProcess(1);
270
271    //hStream = BASS_StreamCreate(wfx.nSamplesPerSec, wfx.nChannels, 0, StreamWriter, NULL);
272    //return (hStream != NULL) ? TRUE : FALSE;
273
274    if(in_module)
275    {
276        in_module->Play("D:\\Music\\Love Story.mp3");
277        return TRUE;
278    }

279    else
280        return FALSE;
281}

282
283//////////////////////////////////////////////////////////////////////////
284// Input
285void SAVSAInit( int maxlatency_in_ms, int srate )
286{
287}

288
289void SAVSADeInit()
290{
291}

292
293void SAAddPCMData( void * PCMData, int nch, int bps, int timestamp )
294{
295}

296
297int SAGetMode()
298{
299    return 0;
300}

301
302void SAAdd( void * data, int timestamp, int csa )
303{
304}

305
306void VSAAddPCMData( void * PCMData, int nch, int bps, int timestamp )
307{
308}

309
310int VSAGetMode( int * specNch, int * waveNch )
311{
312    return 0;
313}

314
315void VSAAdd( void * data, int timestamp )
316{
317}

318
319void VSASetInfo( int nch, int srate )
320{
321}

322
323void SetInfo( int bitrate, int srate, int stereo, int synched )
324{
325}

326
327int dsp_isactive()
328{
329    return 0;
330}

331
332int dsp_dosamples( short int * samples, int numsamples, int bps, int nch, int srate )
333{
334    return numsamples;
335}

336
337BOOL LoadWinampInputPlugin()
338{
339#define INPUT_PLUGIN "in_mp3.dll"
340    hInputModule = LoadLibrary(INPUT_PLUGIN);
341    if(!hInputModule)
342        return FALSE;
343
344    typedef In_Module* (__stdcall *pfn_winampGetInModule2)();
345    pfn_winampGetInModule2 winampGetInModule2 = (pfn_winampGetInModule2)GetProcAddress(hInputModule, "winampGetInModule2");
346    if(!winampGetInModule2)
347        return FALSE;
348
349    in_module = winampGetInModule2();
350    if(!in_module)
351        return FALSE;
352
353    in_module->hMainWindow = hMainWindow;
354    in_module->hDllInstance = hInputModule;
355    in_module->outMod = &out_module;
356    in_module->Init();
357
358    in_module->SetInfo = SetInfo;
359    in_module->dsp_isactive = dsp_isactive;
360    in_module->dsp_dosamples = dsp_dosamples;
361    in_module->SAVSAInit = SAVSAInit;
362    in_module->SAVSADeInit = SAVSADeInit;
363    in_module->SAAddPCMData = SAAddPCMData;
364    in_module->SAGetMode = SAGetMode;
365    in_module->SAAdd = SAAdd;
366    in_module->VSASetInfo = VSASetInfo;
367    in_module->VSAAddPCMData = VSAAddPCMData;
368    in_module->VSAGetMode = VSAGetMode;
369    in_module->VSAAdd = VSAAdd;
370
371    return TRUE;
372}

373
374BOOL UnloadWinampInputPlugin()
375{
376    if(in_module)
377        in_module->Quit();
378
379    if(hInputModule)
380        FreeLibrary(hInputModule);
381
382    in_module = NULL;
383    hInputModule = NULL;
384    return TRUE;
385}

386
387//////////////////////////////////////////////////////////////////////////
388// Output
389const int PacketSize = 1152;
390const int WinampBaseSize = 576;
391const int DefaultBufSize = 88200;
392
393unsigned char* pBuf = NULL;
394DWORD bufSize = 0;
395BOOL omodReady = FALSE;
396BOOL PosChanged = FALSE;
397
398DWORD rOffset = 0;
399DWORD wOffset = 0;
400int SPS = 0;
401int BPS = 0;
402int Channels = 0;
403DWORD BASSDataSize = 0;
404BOOL isReading = FALSE;
405BOOL isWriting = FALSE;
406int posDelta = 0;
407__int64 totalWritten = 0;
408BOOL InitialBufferFill = FALSE;
409BOOL ReachedEnd = FALSE;
410BOOL ResumeMode = 0;
411
412BOOL Debug = FALSE;
413HANDLE hRawFile = NULL;
414
415static DWORD FreeSpace(DWORD BufferSize, DWORD ReadOffset, DWORD WriteOffset)
416{
417    if(ReadOffset > WriteOffset)
418        return ReadOffset - WriteOffset;
419    else
420        return BufferSize  - WriteOffset + ReadOffset;
421}

422
423static DWORD DataRemains(DWORD BufferSize, DWORD ReadOffset, DWORD WriteOffset)
424{
425    if(ReadOffset > WriteOffset)
426        return BufferSize  + WriteOffset - ReadOffset;
427    else
428        return WriteOffset - ReadOffset;
429}

430
431DWORD __stdcall StreamWriter2(HSTREAM handle, void *buffer, DWORD length, void *user)
432{
433    unsigned char* p1 = NULL;
434    unsigned char* p2 = NULL;
435    unsigned short wCycle = 0;
436    DWORD OutputTime = 0;
437
438    if(isWriting)
439    {
440        wCycle = 0;
441        do
442        {
443            Sleep(50);
444            wCycle++;
445        }
 while(!isWriting || wCycle == 150);
446    }

447
448    isReading = TRUE;
449    int result = 0;
450
451    p1 = pBuf + rOffset;
452    if(rOffset > wOffset)
453    {
454        if((bufSize - rOffset) > length)
455        {
456            memcpy(buffer, p1, length);
457            rOffset += length;
458            result = length;
459        }

460        else if((bufSize - rOffset) == length)
461        {
462            memcpy(buffer, p1, length);
463            rOffset = 0;
464            result = length;
465        }

466        else
467        {
468            memcpy(buffer, p1, bufSize - rOffset);
469            unsigned char* _buffer = (unsigned char*)buffer;
470            p2 = _buffer + (bufSize - rOffset);
471
472            if((length - (bufSize - rOffset)) < wOffset)
473            {
474                memcpy(p2, pBuf, length - (bufSize - rOffset));
475                rOffset = length - (bufSize - rOffset);
476                result = length;
477            }

478            else
479            {
480                memcpy(p2, pBuf, wOffset);
481                rOffset = wOffset;
482                result = bufSize - rOffset + wOffset;
483            }

484        }

485    }

486    else if(rOffset < wOffset)
487    {
488        if((wOffset - rOffset) >= length)
489        {
490            memcpy(buffer, p1, length);
491            rOffset += length;
492            result = length;
493        }

494        else
495        {
496            memcpy(buffer, p1, wOffset - rOffset);
497            rOffset = wOffset - rOffset;
498            result = wOffset;
499        }

500    }

501    else
502        result = BASS_STREAMPROC_END;
503
504    if(ResumeMode)
505    {
506        if(DataRemains(bufSize, rOffset, wOffset) < length)
507        {
508            wCycle = 0;
509            while(!isWriting)
510            {
511                Sleep(200);
512                wCycle++;
513                if(wCycle == 50)
514                    break;
515            }

516
517            ResumeMode = FALSE;
518        }

519    }

520
521    isReading = FALSE;
522    return result;
523}

524
525void Config(HWND hwndParent)
526{
527    MessageBox(hwndParent, "No configuration is needed.""Confirm", MB_OK);
528}

529
530void About(HWND hwndParent)
531{
532    MessageBox(hwndParent, "This is a Winamp output plug-in emulator using BASS""Confirm", MB_OK);
533}

534
535void Init()
536{
537    if(omodReady)
538        return;
539
540    omodReady = TRUE;
541}

542
543void Quit()
544{
545    if(omodReady)
546        omodReady = FALSE;
547}

548
549int Open(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms)
550{
551    if(!omodReady)
552        return -1;
553
554    DWORD flag = 0;
555    if(bitspersamp == 8)
556        flag = BASS_SAMPLE_8BITS;
557
558    rOffset = 0;
559    wOffset = 0;
560    totalWritten = 0;
561    isReading = FALSE;
562    isWriting = FALSE;
563    PosChanged = FALSE;
564    InitialBufferFill = TRUE;
565    ReachedEnd = FALSE;
566
567    hStream = BASS_StreamCreate(samplerate, numchannels, flag, STREAMPROC_PUSH, NULL);
568    if(!hStream)
569        return -1;
570
571    SPS = samplerate;
572    BPS = bitspersamp;
573    Channels = numchannels;
574    BASSDataSize = (SPS * (BPS >> 3* Channels * 2/ 10;
575
576    if(((BASSDataSize * 2> bufSize) || ((BASSDataSize * 4< bufSize))
577    {
578        if(pBuf != NULL)
579        {
580            delete [] pBuf;
581            pBuf = NULL;
582        }

583
584        bufSize = BASSDataSize * 3;
585        pBuf = new unsigned char[bufSize];
586        if(pBuf == NULL)
587        {
588            bufSize = 0;
589            return -1;
590        }

591    }

592
593    if(Debug)
594        hRawFile = CreateFile("out.raw", GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
595            CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
596
597    posDelta = 0;
598    return 0;
599}

600
601void Close()
602{
603    if(BASS_ChannelIsActive(hStream) == BASS_ACTIVE_PLAYING)
604        BASS_ChannelStop(hStream);
605
606    BASS_StreamFree(hStream);
607
608    if(hRawFile != NULL && Debug == TRUE)
609    {
610        CloseHandle(hRawFile);
611        hRawFile = NULL;
612    }

613    
614    hStream = 0;
615}

616
617int Write(char *buf, int len)
618{
619    if(TRUE)
620    {
621        BASS_StreamPutData(hStream, buf, len);
622        return 0;
623    }

624
625    unsigned char* p1 = NULL;
626    unsigned char* p2 = NULL;
627    unsigned short wCycle = 0;
628
629    if(isReading)
630    {
631        wCycle = 0;
632        do 
633        {
634            Sleep(50);
635            wCycle++;
636        }
 while (!isReading || wCycle == 150);
637    }

638
639    isWriting = TRUE;
640    int result = 0;
641
642    p1 = pBuf + wOffset;
643
644    if(FreeSpace(bufSize, rOffset, wOffset) > (DWORD)len)
645    {
646        if(rOffset > wOffset)
647        {
648            memcpy(p1, buf, len);
649            wOffset += len;
650        }

651        else
652        {
653            if((bufSize - wOffset) > (DWORD)len)
654            {
655                memcpy(p1, buf, len);
656                wOffset += len;
657            }

658            else
659            {
660                memcpy(p1, buf, bufSize - wOffset);
661
662                if((bufSize - wOffset) < (DWORD)len)
663                {
664                    p2 = (unsigned char*)(buf + (bufSize - wOffset));
665                    memcpy(pBuf, p2, len - (bufSize - wOffset));
666                }

667
668                wOffset = len - (bufSize - wOffset);
669            }

670        }

671    }

672    else
673        result = 1;
674
675    isWriting = FALSE;
676
677    if(InitialBufferFill)
678    {
679        DWORD free_space = FreeSpace(bufSize, rOffset, wOffset);
680        DWORD data_remains = DataRemains(bufSize, rOffset, wOffset);
681        DWORD xx = BASSDataSize << 1;
682
683        if(free_space <= 8192 || data_remains >= xx)
684        {
685            InitialBufferFill = FALSE;
686            if(hStream)
687            {
688                ResumeMode = FALSE;
689                BASS_ChannelPlay(hStream, TRUE);
690            }

691        }

692    }

693
694    if(hRawFile != NULL && Debug == TRUE)
695    {
696        DWORD dwWriteBytes = 0;
697        WriteFile(hRawFile, buf, len, &dwWriteBytes, NULL);
698    }

699
700    return result;
701}

702
703int CanWrite()
704{
705    if(isReading)
706        return 0;
707
708    return FreeSpace(bufSize, rOffset, wOffset) - 1;
709}

710
711int IsPlaying()
712{
713    if(BASS_ChannelIsActive(hStream) == BASS_ACTIVE_PLAYING)
714        return 1;
715    else
716        return 0;
717}

718
719int Pause(int pause)
720{
721    int result = 0;
722    if(BASS_ChannelIsActive(hStream) == BASS_ACTIVE_PAUSED)
723        result = 1;
724    else
725        return 0;
726
727    if((pause == 0&& (result == 1))
728    {
729        ResumeMode = TRUE;
730        BASS_ChannelPlay(hStream, FALSE);
731    }

732    else if(pause == 0)
733    {
734        ResumeMode = TRUE;
735        BASS_ChannelPlay(hStream, TRUE);
736    }

737    else if(pause != 0 && pause == 0)
738        BASS_ChannelPause(hStream);
739
740    return result;
741}

742
743void SetVolume(int volume)
744{
745    int SetVolume = 0;
746    if(volume < 0)
747        SetVolume = 0;
748    else if(volume > 255)
749        SetVolume = 255;
750    else
751        SetVolume = volume;
752
753    BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, SetVolume * 39);
754}

755
756void SetPan(int pan)
757{
758    BASS_ChannelSetAttribute(hStream, BASS_ATTRIB_PAN, (float)pan * (100 / 128));
759}

760
761void Flush(int t)
762{
763    DWORD chnStatus = 0;
764    BOOL wasPlaying = FALSE;
765    unsigned short wCycle = 0;
766
767    chnStatus = BASS_ChannelIsActive(hStream);
768
769    if(chnStatus != BASS_ACTIVE_PAUSED && chnStatus != BASS_ACTIVE_STOPPED)
770        if((FreeSpace(bufSize, rOffset, wOffset) > 0|| (chnStatus == BASS_ACTIVE_PLAYING))
771            wasPlaying = TRUE;
772        else
773            wasPlaying = FALSE;
774    else
775        wasPlaying = FALSE;
776
777    if(chnStatus == BASS_ACTIVE_PAUSED)
778        if(!PosChanged)
779            return;
780
781    if(isReading)
782    {
783        wCycle = 0;
784        do 
785        {
786            Sleep(50);
787            wCycle++;
788        }
 while (!isReading || wCycle == 150);
789    }

790
791    BASS_ChannelStop(hStream);
792
793    if(wasPlaying)
794        InitialBufferFill = TRUE;
795
796    posDelta = t;
797    rOffset = 0;
798    wOffset = 0;
799    totalWritten = 0;
800    isWriting = FALSE;
801    PosChanged = FALSE;
802}

803
804#define round(x) (int)((x)>0 ? (x)+0.5 : (x)-0.5)
805
806int GetOutputTime()
807{
808    DWORD Devider = SPS * (BPS >> 3* Channels;
809    if(Devider != 0)
810        return posDelta + round(1000 * BASS_ChannelGetPosition((hStream), BASS_POS_BYTE) / Devider);
811
812    return 0;
813}

814
815int GetWrittenTime()
816{
817    DWORD Devider = SPS * (BPS >> 3* Channels;
818    if(Devider != 0)
819        return posDelta + round(1000 * totalWritten / Devider);
820
821    return 0;
822}

823
824BOOL LoadWinampOutputPlugin()
825{
826    pBuf = new unsigned char[DefaultBufSize];
827    if(pBuf == NULL)
828        return FALSE;
829
830    memset(pBuf, 0sizeof(unsigned char* DefaultBufSize);
831    bufSize = DefaultBufSize;
832
833    out_module.version = 0x10;
834    out_module.description = "BASS Winamp output plug-in emulator";
835    out_module.id = 65536 + 1;
836    out_module.hMainWindow = hMainWindow;
837    out_module.hDllInstance = NULL;
838    out_module.Config = Config;
839    out_module.About = About;
840    out_module.Init = Init;
841    out_module.Quit = Quit;
842    out_module.Open = Open;
843    out_module.Close = Close;
844    out_module.Write = Write;
845    out_module.CanWrite = CanWrite;
846    out_module.IsPlaying = IsPlaying;
847    out_module.Pause = Pause;
848    out_module.SetVolume = SetVolume;
849    out_module.SetPan = SetPan;
850    out_module.Flush = Flush;
851    out_module.GetOutputTime = GetOutputTime;
852    out_module.GetWrittenTime = GetWrittenTime;
853
854    out_module.Init();
855    return TRUE;
856}

857
858BOOL UnloadWinampOutputPlugin()
859{
860    if(pBuf != NULL)
861    {
862        delete [] pBuf;
863        pBuf = NULL;
864    }

865
866    return TRUE;
867}
click here download source code