mp3.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:22k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /*  @(#) mp3.c, last edit: 4/9/1998
  2.  *  @(#) Copyright (C) 1998 Syntrillium Software (www.syntrillium.com)
  3.  
  4. Cool Edit (and Cool Edit Pro) MP3 file reader based on MAPLAY by Jeff Tsay
  5. A bunch of convoluted code was added to this file filter in order to allow
  6. for the choice of volume level during decode, and format to decode to. 
  7. That's right, you can decode to 16-bit by truncation, or by dithering, or
  8. keep an entire 32-bit float for each sample for use in Cool Edit Pro.
  9.     Versions Cool Edit that do not support 32-bit will still say "32-bit" when
  10. the file is loaded, but rest assured, it's only 16-bit.
  11. Most of the files for MAPLAY were left untouched, and many were not needed
  12. for this port, so only the files needed for the port are included here.
  13.     Search for MAPLAY 1.2 or later for original source (and if the source gets
  14. updated, it should be trivial to add it to this build).  Very few of the 
  15. other files were modified, and when they were, they were bracketed by 
  16. "#ifdef COOLPRO" for easy location and such.
  17. The Obuffer class was modified to take in floats instead of ints for
  18. reading in with greater accuracy.  Since MPEG (which is similar to JPEG
  19. in this respect) doesn't try to encode the exact sample values, but 
  20. instead is psychoacoustic in nature, higher quality can be gained by
  21. encoding from a 32-bit source (I haven't found an encoder that can take
  22. floating point samples yet) and then decoding back to 32-bit.  Nothing
  23. in MPEG says it should be limited to 16-bit I believe (but don't quote
  24. me on this... I do not know much about the internals of the MPEG format).
  25. Some links to the binaries of ports of maplay are on Jeff's homepage at:
  26. http://www-inst.eecs.berkeley.edu/~ctsay/mp2win32.html
  27.   Believe it or not, the speed is much faster than original ISO MPEG code,
  28.   but still slower than Fraunhoffer.  Their Windows ACM codec is about
  29.   twice as fast for reading.  But the good news is it that it's still fast
  30.   enough for real time previewing (auto-play) on pretty much all Pentiums.
  31.   If you purchase an ACM codec for writing Layer 3 MPEG, use the updated
  32.   ACM Waveform format type found at http://www.syntrillium.com which allows
  33.   for saving any ACM format as raw data thus allowing the saving directly
  34.   to .mp3 files if you have the codec which can write MPEG .wav files.
  35.  *
  36.  *  This program is free software; you can redistribute it and/or modify
  37.  *  it under the terms of the GNU General Public License as published by
  38.  *  the Free Software Foundation; either version 2 of the License, or
  39.  *  (at your option) any later version.
  40.  *
  41.  *  This program is distributed in the hope that it will be useful,
  42.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  43.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  44.  *  GNU General Public License for more details.
  45.  *
  46.  *  You should have received a copy of the GNU General Public License
  47.  *  along with this program; if not, write to the Free Software
  48.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  49.  *
  50. */
  51. #include <windows.h>
  52. #include <math.h>
  53. #include "filters.h"
  54. #include "ceglue.h"
  55. #include "resource.h"
  56. // Hey!  Someone want a _real_ challenge?  Implement Layer 3 encoding as well!
  57.     
  58. typedef struct output_tag  // any special vars associated with output file
  59. { short nFile;         
  60. long lSize;
  61. } MYOUTPUT;
  62. typedef struct input_tag // any special vars associated with input file
  63. { short nFile;
  64. long lSize;
  65. long lSamprate;
  66. DWORD dwFormat;
  67. BOOL bOpenedMPEG;
  68. MPEG_INFO mpi;
  69. double fAttenuation;
  70. float fScaleBy;
  71. WORD wBitsPerSample;
  72. BOOL bDither;
  73. HANDLE h32bit;
  74. short * pi32bit;
  75. } MYINPUT;
  76. HANDLE myInstance=NULL;
  77. BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
  78. {
  79.    switch (fdwReason)
  80.    {
  81.       case DLL_PROCESS_ATTACH:
  82.         
  83.  myInstance=hModule;
  84.     
  85.          break;
  86.  
  87.       case DLL_THREAD_ATTACH:
  88.          break;
  89.  
  90.       case DLL_THREAD_DETACH:
  91.          break;
  92.  
  93.       case DLL_PROCESS_DETACH:
  94.          myInstance=NULL;
  95.          break;
  96.    }
  97.  
  98.    return TRUE;   
  99. }
  100. // Fill COOLQUERY structure with information regarding this file filter
  101. __declspec(dllexport) short FAR PASCAL QueryCoolFilter(COOLQUERY far * cq)
  102. {   lstrcpy(cq->szName,"MPEG 3");         
  103. lstrcpy(cq->szCopyright,"MPEG (Layer 1,2,3) Decoder (GNU)");
  104. lstrcpy(cq->szExt,"MP3");
  105. lstrcpy(cq->szExt2,"MP2");
  106. lstrcpy(cq->szExt3,"MP1");
  107. cq->lChunkSize=16384; 
  108. cq->dwFlags=QF_RATEADJUSTABLE|QF_CANLOAD|QF_CANDO32BITFLOATS|QF_HASOPTIONSBOX;
  109. cq->Stereo8=0; 
  110. cq->Stereo16=R_32075|R_44100|R_48000;
  111. cq->Stereo24=0;
  112. cq->Stereo32=R_32075|R_44100|R_48000;
  113. cq->Mono8=0; 
  114. cq->Mono16=R_32075|R_44100|R_48000;
  115. cq->Mono24=0;
  116. cq->Mono32=R_32075|R_44100|R_48000;
  117. cq->Quad32=0;
  118. cq->Quad16=0;
  119. cq->Quad8=0;
  120. return C_VALIDLIBRARY;
  121. }
  122. // Just our little way of not including stdio.h to do float to string cvting
  123. char * ftos(char *tmp, double d)
  124. { double dd;
  125. double mplier;
  126. short maxdecimal=9;
  127. char * otemp;
  128. otemp=tmp;
  129. if (d==0)
  130. { *tmp='0';
  131.   tmp++;
  132.   *tmp=0x00;
  133.   return otemp;
  134. if (d<0)
  135. { *tmp='-';
  136. tmp++;
  137. d=-d;
  138. }
  139. d=d+(1.0/65535.0/32768.0);
  140. dd=d;         
  141. mplier=1.0;
  142. while (dd>=1.0)
  143. { dd/=10.0;
  144. mplier*=10.0;
  145. }   
  146. mplier/=10.0;             
  147. while (mplier>=1.0)
  148. { *tmp='0'+(short)(d/mplier);
  149. tmp++;
  150. d=d-mplier*(short)(d/mplier);
  151. mplier/=10.0;
  152. }
  153.     if (d!=0.0)
  154.     { short digit;
  155.      *tmp='.';
  156.      tmp++;
  157.      while ((d!=0.0) && (maxdecimal!=0))
  158.      { d*=10.0;
  159.      digit=(short)d;
  160.      d-=(double)digit;
  161.      *tmp='0'+digit;
  162.      tmp++;
  163.      maxdecimal--;         
  164.      }             
  165.      while (*(tmp-1)=='0')
  166.      tmp--;
  167.      if (*(tmp-1)=='.')
  168.      tmp--;
  169.     }
  170.                   
  171.     *tmp=0x00;   
  172.     
  173.     return otemp;
  174. }                                  
  175. __declspec(dllexport) long FAR PASCAL FilterGetFileSize(HANDLE hInput)
  176. {
  177. long lSize=0L;
  178. if (hInput)
  179. {       MYINPUT *mi;
  180. mi=(MYINPUT *)GlobalLock(hInput);
  181. lSize=mi->lSize;
  182. GlobalUnlock(hInput);
  183. }
  184.     return lSize;
  185. }
  186. __declspec(dllexport) BOOL FAR PASCAL FilterGetActualFormat(HANDLE hInput,DWORD dwOptions,long * plSamprate, WORD * pwChannels, WORD * pwBitsPerSample)
  187. {   
  188. if (hInput)
  189. { MYINPUT *mi;
  190. mi=(MYINPUT *)GlobalLock(hInput);
  191. *pwBitsPerSample=HIWORD(dwOptions)&0x00FF;
  192. GlobalUnlock(hInput);
  193. }
  194.     return TRUE;
  195. }
  196. __declspec(dllexport) BOOL FAR PASCAL FilterUnderstandsFormat(LPSTR filename)
  197. {
  198. if ((lstrlen(filename)>4) && 
  199. ((strcmpi(filename+lstrlen(filename)-4,".mp3")==0) ||
  200.  (strcmpi(filename+lstrlen(filename)-4,".mp2")==0) ||
  201.  (strcmpi(filename+lstrlen(filename)-4,".mp1")==0)  
  202.  ))
  203. {
  204.    return TRUE;
  205.    }
  206.    return FALSE;
  207. }
  208. __declspec(dllexport) BOOL FAR PASCAL DIALOGMsgProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  209. { switch(Message)
  210. { case WM_INITDIALOG:
  211. {  WORD wBitsPerSample;
  212.  double fAttenuation;
  213.  BOOL bDither;
  214.  char tmp[30];
  215.            wBitsPerSample=HIWORD(lParam)&0x00FF;
  216.  bDither=(lParam&0x01000000)?TRUE:FALSE;
  217.  fAttenuation=(double)((DWORD)lParam&0xffff)/100.0-200.0;
  218.              if (fAttenuation>200.0)
  219.  fAttenuation=0.0;
  220.  //wsprintf(tmp," Read MPEG As %d-bit ",wBitsPerSample);
  221.  //SetDlgItemText(hWndDlg,IDC_TEXT1,tmp);
  222.              
  223.  if (wBitsPerSample==16)
  224.          { CheckDlgButton(hWndDlg,IDC_RADIO1,TRUE);
  225.          }
  226.          else if (wBitsPerSample==32)
  227.          {  CheckDlgButton(hWndDlg,IDC_RADIO2,TRUE);
  228.          }
  229.          else
  230.          { CheckDlgButton(hWndDlg,IDC_RADIO1,TRUE);
  231.          }
  232.  
  233.  CheckDlgButton(hWndDlg,IDC_CHECK1,bDither);
  234.          ftos(tmp,fAttenuation);
  235.  SetDlgItemText(hWndDlg,IDC_EDIT1,tmp);
  236.  EnableWindow(GetDlgItem(hWndDlg,IDC_CHECK1),IsDlgButtonChecked(hWndDlg,IDC_RADIO1)?TRUE:FALSE);
  237.          }         
  238.          break; 
  239. case WM_CLOSE:         
  240.  PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
  241.  break; 
  242. case WM_COMMAND:
  243. { WORD wNotifyCode=HIWORD(wParam);
  244. wParam=(WPARAM)LOWORD(wParam);
  245. switch(wParam)
  246. {
  247. case IDC_RADIO1:
  248. case IDC_RADIO2:
  249. EnableWindow(GetDlgItem(hWndDlg,IDC_CHECK1),IsDlgButtonChecked(hWndDlg,IDC_RADIO1)?TRUE:FALSE);
  250. break;
  251. case IDOK:
  252. { long nDialogReturn=0;
  253.              char tmp[30];
  254. if (IsDlgButtonChecked(hWndDlg,IDC_RADIO2))
  255. { nDialogReturn=32L<<16;
  256. }
  257. else
  258. { nDialogReturn=16L<<16;
  259. }
  260. GetDlgItemText(hWndDlg,IDC_EDIT1,tmp,29);
  261. nDialogReturn|=(WORD)max(0,min(40000,(atof(tmp)+200.0)*100.0));
  262. if (IsDlgButtonChecked(hWndDlg,IDC_CHECK1))
  263. nDialogReturn|=0x01000000;
  264. EndDialog(hWndDlg, nDialogReturn);
  265. }
  266. break;
  267. case IDCANCEL:
  268.  EndDialog(hWndDlg, FALSE);
  269.  break;
  270. }
  271. break;
  272. }
  273. default:
  274. return FALSE;
  275. }
  276. return TRUE;
  277. __declspec(dllexport) DWORD FAR PASCAL FilterGetOptions(HWND hWnd, HINSTANCE hInst, long lSamprate, WORD wChannels, WORD wBitsPerSample, DWORD dwOptions) // return 0 if no options box
  278. {
  279. long nDialogReturn=0L;
  280. FARPROC lpfnDIALOGMsgProc;
  281. lpfnDIALOGMsgProc = GetProcAddress(hInst,(LPCSTR)MAKELONG(20,0));
  282. if (dwOptions==0)
  283. {
  284. nDialogReturn=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
  285. if (nDialogReturn==0)
  286. nDialogReturn=(WORD)max(0,min(40000,(100.0+200.0)*100.0));
  287. }
  288. else
  289. nDialogReturn=dwOptions;
  290. // These were to force the dialog to have _only_ 16 or 32... now we let user choose
  291. //nDialogReturn=(nDialogReturn&0xFF00FFFF)|(((DWORD)wBitsPerSample)<<8);
  292. //nDialogReturn|=MAKELONG(nDialogReturn&0x0FF,wBitsPerSample);
  293. nDialogReturn = (long)DialogBoxParam((HINSTANCE)hInst,(LPCSTR)MAKEINTRESOURCE(IDD_COMPRESSION), (HWND)hWnd, (DLGPROC)lpfnDIALOGMsgProc,nDialogReturn);
  294. if (nDialogReturn)
  295. { char m[30];
  296. wsprintf(m,"%d",nDialogReturn);
  297. WritePrivateProfileString("MPEG Filter","InputFormat",m,"coolrw.ini");
  298. }
  299. return nDialogReturn;
  300. }          
  301. __declspec(dllexport) DWORD FAR PASCAL FilterSetOptions2(HANDLE hInput, DWORD dwOptions, long * plSamprate, WORD * pwChannels, WORD * pwBitsPerSample)
  302. {
  303. DWORD dwOldOptions;
  304. MYINPUT *mi;
  305. mi=(MYINPUT *)GlobalLock(hInput);
  306. dwOldOptions=mi->dwFormat;
  307. if (!dwOptions)
  308. { dwOptions=(DWORD)GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
  309. if (!dwOptions)
  310. dwOptions=(WORD)max(0,min(40000,(200.0)*100.0))|(16L<<16);
  311. }
  312. mi->wBitsPerSample=HIWORD(dwOptions)&0x00FF;
  313. mi->fAttenuation=(double)((DWORD)dwOptions&0xffff)/100.0-200.0;
  314. mi->bDither=(dwOptions&0x01000000)?TRUE:FALSE;
  315.     mi->dwFormat=dwOptions;
  316. if ((mi->fAttenuation<-199.0) || (mi->fAttenuation>200.0))
  317. mi->fAttenuation=0;
  318. if (mi->wBitsPerSample==16)
  319. { *pwBitsPerSample=16;
  320. if (!mi->h32bit)
  321. { mi->h32bit=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,32768);
  322. mi->pi32bit=(short *)GlobalLock(mi->h32bit);
  323. }
  324. }
  325. else
  326. { *pwBitsPerSample=32;
  327. }
  328. mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(*plSamprate)/1000.0)*(*pwChannels)*(*pwBitsPerSample/8);
  329. mi->fScaleBy=(float)(32768.0*(pow(10.0,mi->fAttenuation/20.0)));
  330.     GlobalUnlock(hInput);
  331.     
  332.     return dwOldOptions;
  333.         
  334. }
  335. // Dummy, but must be here... FilterSetOptions2 is actually called instead if it exists
  336. __declspec(dllexport) DWORD FAR PASCAL FilterSetOptions(HANDLE hInput, DWORD dwOptions, long lSamprate, WORD wChannels, WORD wBitsPerSample)
  337. {
  338. DWORD dwOldOptions;
  339. MYINPUT *mi;
  340. mi=(MYINPUT *)GlobalLock(hInput);
  341. dwOldOptions=mi->dwFormat;
  342.     mi->dwFormat=dwOptions;
  343. mi->wBitsPerSample=HIWORD(dwOptions)&0x00FF;
  344. mi->fAttenuation=(double)((DWORD)dwOptions&0xffff)/100.0-200.0;
  345. mi->bDither=(dwOptions&0x01000000)?TRUE:FALSE;
  346. if ((mi->fAttenuation<-199.0) || (mi->fAttenuation>200.0))
  347. mi->fAttenuation=0;
  348. if (mi->wBitsPerSample==16)
  349. { if (!mi->h32bit)
  350. { mi->h32bit=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,32768);
  351. mi->pi32bit=(short *)GlobalLock(mi->h32bit);
  352. }
  353. }
  354. mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(lSamprate)/1000.0)*(wChannels)*(wBitsPerSample/8);
  355. mi->fScaleBy=(float)(32768.0*(pow(10.0,mi->fAttenuation/20.0)));
  356.     GlobalUnlock(hInput);
  357.     
  358.     return dwOldOptions;
  359. }
  360. __declspec(dllexport) DWORD FAR PASCAL FilterOptions(HANDLE hInput)
  361. {   MYINPUT *mi;
  362. DWORD dwFormat;
  363. if (!hInput) return 0;
  364. mi=(MYINPUT *)GlobalLock(hInput);
  365. dwFormat=(DWORD)mi->dwFormat;
  366.     GlobalUnlock(hInput);
  367.     return dwFormat;
  368. }
  369. __declspec(dllexport) DWORD FAR PASCAL FilterOptionsString(HANDLE hInput, LPSTR szString)
  370. {   MYINPUT *mi;
  371. DWORD dwFormat;
  372. if (!hInput) return 0;
  373. mi=(MYINPUT *)GlobalLock(hInput);
  374.     dwFormat=(DWORD)mi->dwFormat;
  375. wsprintf(szString,"%s Layer %drn(%s)",mi->mpi.szVersion,mi->mpi.iLayer,mi->mpi.szBitrate);
  376.     GlobalUnlock(hInput);
  377.     return dwFormat;
  378. }
  379. __declspec(dllexport) DWORD FAR PASCAL FilterCanWriteSpecial(HANDLE hOutput, DWORD idType)
  380. {
  381.  return 0L;
  382. }
  383. __declspec(dllexport) DWORD FAR PASCAL FilterCanReadSpecial(HANDLE hInput, DWORD idType)
  384. {
  385.  return 0L;
  386. }
  387.  
  388. __declspec(dllexport) DWORD FAR PASCAL FilterWriteSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
  389. {
  390.  return 0L;
  391. }
  392. __declspec(dllexport) DWORD FAR PASCAL FilterReadSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
  393. {
  394.  return 0L;
  395. }
  396. __declspec(dllexport) HANDLE FAR PASCAL OpenFilterOutput(LPSTR lpstrFilename,long lSamprate,WORD wBitsPerSample,WORD wChannels,long lSize,long far *lpChunkSize,DWORD dwOptions)
  397. {   HANDLE hOutput;
  398. short nFile;
  399. nFile=_lcreat(lpstrFilename,0);
  400.     if (nFile==-1) return NULL;
  401.     hOutput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(MYOUTPUT));
  402.     if (hOutput)
  403.     {   MYOUTPUT *mo;
  404. mo=(MYOUTPUT *)GlobalLock(hOutput);
  405. mo->nFile=nFile;
  406. mo->lSize=lSize;
  407. GlobalUnlock(hOutput);
  408.     }
  409.     *lpChunkSize=16384;
  410.     return hOutput;
  411. }
  412. __declspec(dllexport) void FAR PASCAL CloseFilterOutput(HANDLE hOutput)
  413. {   if (hOutput)
  414. {       MYOUTPUT *mo;
  415. mo=(MYOUTPUT *)GlobalLock(hOutput);
  416. if (mo->nFile!=-1)
  417. {       _lclose(mo->nFile);
  418. mo->nFile=-1;
  419. }
  420. GlobalUnlock(hOutput);
  421. GlobalFree(hOutput);
  422. }
  423. }
  424. __declspec(dllexport) DWORD FAR PASCAL WriteFilterOutput(HANDLE hOutput, unsigned char far *buf, long lBytes)
  425. {       DWORD written=0L;
  426. if (hOutput)
  427. {       MYOUTPUT *mo;
  428. mo=(MYOUTPUT *)GlobalLock(hOutput);
  429. written=(DWORD)_lwrite(mo->nFile,buf,(UINT)lBytes);
  430. GlobalUnlock(hOutput);
  431. }
  432. return written; 
  433. }
  434. DWORD valJ=524309;
  435. DWORD valI=12345; // reset to time at startup
  436. double fRandom(void) // 0 to 1
  437. { DWORDLONG dwl;
  438. dwl=UInt32x32To64(valJ,valI);
  439. dwl++;
  440. valI=(DWORD)(dwl&0x1FFFFF);
  441. return (double)valI/2097152.0;
  442. }
  443. // This is the 32-bit to 16-bit converter from Cool Edit, but with only the code
  444. // for the straight triangular dithering.  For higher quality, read in the file
  445. // as 32-bit, then use Cool Edit Pro's dithering options for going to 16-bit.
  446. void HfCvt32To16InMem(short *piDest, float *pfSource, long dwSourceSamples, BOOL bStereo, double fDitherAmount)
  447. { long t;
  448. double fFilteredError=0;
  449. double fSourceBeforeNoise;
  450. double qq=1.0;
  451. double fMultiplier=0.5;
  452. double fNoise;
  453. double fSource;
  454. double fSqrtDitherAmount;
  455. long quant;
  456. static double fError=0;
  457. static double fError1=0;
  458. static double fError2=0;
  459. static double fError3=0;
  460. static double fError4=0;
  461. static double fError5=0;
  462. static double fErrorR=0;
  463. static double fErrorR1=0;
  464. static double fErrorR2=0;
  465. static double fErrorR3=0;
  466. static double fErrorR4=0;
  467. static double fErrorR5=0;
  468.     
  469. {   
  470. if (fDitherAmount>0)
  471. fSqrtDitherAmount=sqrt(fDitherAmount);
  472. else
  473. fSqrtDitherAmount=0;
  474. if (bStereo)
  475.   {
  476. for (t=0;t<dwSourceSamples;t+=2)
  477. {
  478. fFilteredError=0;
  479. fError4=fError3;
  480. fError3=fError2;
  481. fError2=fError1;
  482. fError1=fFilteredError;
  483. fSource=*pfSource;
  484. pfSource++;
  485. // Don't Shift out 8 bits
  486. fSource=fSource-fFilteredError; //*fDitherMultiplier;
  487. fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
  488. fSourceBeforeNoise=fSource;
  489. // Add Noise (v)
  490. fSource+=fNoise; //*fDitherMultiplier; //*2.0;
  491. // Quantization
  492. quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
  493. // Error for input to H(z)
  494. fError=(double)quant-fSourceBeforeNoise;
  495. if (quant>=-32768)
  496. { if (quant<=32767)
  497. *piDest=(short)quant;
  498. else
  499. *piDest=32767;
  500. }
  501. else
  502. *piDest=-32768;
  503. piDest++;
  504. fFilteredError=0;
  505. fErrorR4=fErrorR3;
  506. fErrorR3=fErrorR2;
  507. fErrorR2=fErrorR1;
  508. fErrorR1=fFilteredError;
  509. fSource=*pfSource;
  510. pfSource++;
  511. // Don't Shift out 8 bits
  512. fSource=fSource-fFilteredError; //*fDitherMultiplier;
  513. fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
  514. fSourceBeforeNoise=fSource;
  515. // Add Noise (v)
  516. fSource+=fNoise; //*fDitherMultiplier; //*2.0;
  517. // Quantization
  518. quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
  519. // Error for input to H(z)
  520. fErrorR=(double)quant-fSourceBeforeNoise;
  521. if (quant>=-32768)
  522. { if (quant<=32767)
  523. *piDest=(short)quant;
  524. else
  525. *piDest=32767;
  526. }
  527. else
  528. *piDest=-32768;
  529. piDest++;
  530. }
  531.   }       
  532.   else
  533.   {   
  534. for (t=0;t<dwSourceSamples;t++)
  535. { fFilteredError=0;
  536. fError5=fError4;
  537. fError4=fError3;
  538. fError3=fError2;
  539. fError2=fError1;
  540. fError1=fFilteredError;
  541. fSource=*pfSource;
  542. pfSource++;
  543. // Don't Shift out 8 bits
  544. fSource=fSource-fFilteredError; //*fDitherMultiplier;
  545. // Triangular Dither Noise
  546. fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
  547. fSourceBeforeNoise=fSource;
  548. // Add Noise (v)
  549. fSource+=fNoise; //*fDitherMultiplier; //*2.0;
  550. // Quantization
  551. quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
  552. // Error for input to H(z)
  553. fError=(double)quant-fSourceBeforeNoise;
  554. if (quant>=-32768)
  555. { if (quant<=32767)
  556. *piDest=(short)quant;
  557. else
  558. *piDest=32767;
  559. }
  560. else
  561. *piDest=-32768;
  562. piDest++;
  563. }
  564. }
  565. }
  566. __declspec(dllexport) void FAR PASCAL GetSuggestedSampleType(long far *lSugSamprate,WORD far *wSugBitsPerSample, WORD far *wSugChannels)
  567. {   // return 0 for don't care
  568.   *lSugSamprate=0;
  569. { int n=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
  570. *wSugBitsPerSample=HIWORD(n)&0x00FF;
  571. if ((*wSugBitsPerSample!=16) && (*wSugBitsPerSample!=32))
  572. *wSugBitsPerSample=16;
  573. }
  574.   *wSugChannels=0;
  575. }
  576. // return handle that will be passed in to close, and write routines
  577. __declspec(dllexport) HANDLE FAR PASCAL OpenFilterInput( LPSTR lpstrFilename,
  578. long *lSamprate,
  579. WORD *wBitsPerSample,
  580. WORD *wChannels,
  581. HWND hWnd,
  582. long *lChunkSize)
  583. { HANDLE hInput;
  584. short source; 
  585. long fullsize;
  586. DWORD dwOptions;
  587. dwOptions=0;
  588. valI=GetTickCount()%50000;
  589. source=_lopen(lpstrFilename,OF_READ);
  590.     if (source==-1) return NULL;     
  591.     
  592.     fullsize=_llseek(source,0L,2);
  593. _lclose(source);
  594.     hInput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT,sizeof(MYINPUT));
  595.     if (hInput)
  596.     {   MYINPUT *mi;
  597. mi=(MYINPUT *)GlobalLock(hInput);
  598. mi->wBitsPerSample=32; 
  599. mi->fAttenuation=0; 
  600. mi->dwFormat=0; // Force asking of format, and default to 32-bit No attenuation
  601. mi->fScaleBy=32768.0f;
  602. mi->bDither=FALSE;
  603. // return 0 for cool to inquire user for sample rates (we aren't doing that though)
  604. *lSamprate=44100;
  605. *wBitsPerSample=32;
  606. *wChannels=2;
  607. *lChunkSize=16384;
  608. mi->bOpenedMPEG=MPEG_Open(lpstrFilename);
  609. if (!mi->bOpenedMPEG)
  610. { GlobalUnlock(hInput);
  611.       GlobalFree(hInput);
  612.       return NULL;
  613. }
  614. MPEG_GetInfo(&mi->mpi);
  615. *lSamprate=mi->mpi.iSamplerate;
  616. *wChannels=mi->mpi.iChannels;
  617. { int n=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
  618. *wBitsPerSample=HIWORD(n)&0x00FF;
  619. if ((*wBitsPerSample!=16) && (*wBitsPerSample!=32))
  620. *wBitsPerSample=16;
  621. }
  622. mi->wBitsPerSample=*wBitsPerSample;
  623. mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(*lSamprate)/1000.0)*(*wChannels)*(*wBitsPerSample/8);
  624. GlobalUnlock(hInput);
  625.     }
  626.     
  627.     return hInput;
  628. }
  629. __declspec(dllexport) void FAR PASCAL CloseFilterInput(HANDLE hInput)
  630. {   if (hInput)  
  631. {       MYINPUT *mi;
  632. mi=(MYINPUT *)GlobalLock(hInput);
  633. if (mi->bOpenedMPEG)
  634. MPEG_Close();
  635.     
  636. if (mi->h32bit)
  637. { GlobalUnlock(mi->h32bit);
  638. GlobalFree(mi->h32bit);
  639. }
  640. GlobalUnlock(hInput);
  641. GlobalFree(hInput);
  642. }
  643. }
  644. __declspec(dllexport) DWORD FAR PASCAL ReadFilterInput(HANDLE hInput, unsigned char far *bufout, long lBytes)
  645. {       DWORD read=0L;
  646. if (hInput)
  647. {   MYINPUT *mi;
  648. float fScaleBy;
  649. mi=(MYINPUT *)GlobalLock(hInput);
  650. fScaleBy=mi->fScaleBy;
  651. if (mi->wBitsPerSample==32)
  652. { // just scale
  653. read=(DWORD)MPEG_Read(bufout);
  654. { int iNum=read/4;
  655. float * pBuf=(float *)bufout;
  656. while (iNum--)
  657. { *pBuf++*=fScaleBy;
  658. }
  659. }
  660. }
  661. else if (mi->wBitsPerSample==16)
  662. { // Convert to 16-bit with scaling and dithering
  663. int iNum;
  664. float * pfBuf;
  665. short * piBuf;
  666. pfBuf=(float *)mi->pi32bit;
  667. piBuf=(short *)bufout;
  668. read=(DWORD)MPEG_Read((BYTE *)mi->pi32bit);
  669. iNum=read/4;
  670. // Dither it to 16-bit
  671. if (mi->bDither)
  672. { // Scale it first
  673. { int iNum=read/4;
  674. float * pBuf=pfBuf;
  675. while (iNum--)
  676. { *pBuf++*=fScaleBy;
  677. }
  678. }
  679. // Dither and Clip
  680. HfCvt32To16InMem(piBuf, pfBuf, iNum,
  681. (mi->mpi.iChannels==2)?TRUE:FALSE, 1.0);
  682. }
  683. else 
  684. { // Scale, Truncate, and Clip
  685. float f;
  686. while (iNum--)
  687. { f=*pfBuf++*fScaleBy;
  688. if (f>=(float)(-32767.0))
  689. { if (f<=(float)32767.0)
  690. *piBuf++=(short)f;
  691. else
  692. *piBuf++=32767;
  693. }
  694. else
  695. *piBuf++=-32767;
  696. }
  697. }
  698. read/=2;
  699. }
  700. GlobalUnlock(hInput);
  701. }
  702. return read;
  703. }