mp3.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:22k
- /* @(#) mp3.c, last edit: 4/9/1998
- * @(#) Copyright (C) 1998 Syntrillium Software (www.syntrillium.com)
-
- Cool Edit (and Cool Edit Pro) MP3 file reader based on MAPLAY by Jeff Tsay
- A bunch of convoluted code was added to this file filter in order to allow
- for the choice of volume level during decode, and format to decode to.
- That's right, you can decode to 16-bit by truncation, or by dithering, or
- keep an entire 32-bit float for each sample for use in Cool Edit Pro.
- Versions Cool Edit that do not support 32-bit will still say "32-bit" when
- the file is loaded, but rest assured, it's only 16-bit.
- Most of the files for MAPLAY were left untouched, and many were not needed
- for this port, so only the files needed for the port are included here.
- Search for MAPLAY 1.2 or later for original source (and if the source gets
- updated, it should be trivial to add it to this build). Very few of the
- other files were modified, and when they were, they were bracketed by
- "#ifdef COOLPRO" for easy location and such.
- The Obuffer class was modified to take in floats instead of ints for
- reading in with greater accuracy. Since MPEG (which is similar to JPEG
- in this respect) doesn't try to encode the exact sample values, but
- instead is psychoacoustic in nature, higher quality can be gained by
- encoding from a 32-bit source (I haven't found an encoder that can take
- floating point samples yet) and then decoding back to 32-bit. Nothing
- in MPEG says it should be limited to 16-bit I believe (but don't quote
- me on this... I do not know much about the internals of the MPEG format).
- Some links to the binaries of ports of maplay are on Jeff's homepage at:
- http://www-inst.eecs.berkeley.edu/~ctsay/mp2win32.html
- Believe it or not, the speed is much faster than original ISO MPEG code,
- but still slower than Fraunhoffer. Their Windows ACM codec is about
- twice as fast for reading. But the good news is it that it's still fast
- enough for real time previewing (auto-play) on pretty much all Pentiums.
- If you purchase an ACM codec for writing Layer 3 MPEG, use the updated
- ACM Waveform format type found at http://www.syntrillium.com which allows
- for saving any ACM format as raw data thus allowing the saving directly
- to .mp3 files if you have the codec which can write MPEG .wav files.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #include <windows.h>
- #include <math.h>
- #include "filters.h"
- #include "ceglue.h"
- #include "resource.h"
- // Hey! Someone want a _real_ challenge? Implement Layer 3 encoding as well!
-
- typedef struct output_tag // any special vars associated with output file
- { short nFile;
- long lSize;
- } MYOUTPUT;
- typedef struct input_tag // any special vars associated with input file
- { short nFile;
- long lSize;
- long lSamprate;
- DWORD dwFormat;
- BOOL bOpenedMPEG;
- MPEG_INFO mpi;
- double fAttenuation;
- float fScaleBy;
- WORD wBitsPerSample;
- BOOL bDither;
- HANDLE h32bit;
- short * pi32bit;
- } MYINPUT;
- HANDLE myInstance=NULL;
- BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
- {
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
-
- myInstance=hModule;
-
- break;
-
- case DLL_THREAD_ATTACH:
- break;
-
- case DLL_THREAD_DETACH:
- break;
-
- case DLL_PROCESS_DETACH:
- myInstance=NULL;
- break;
- }
-
- return TRUE;
- }
- // Fill COOLQUERY structure with information regarding this file filter
- __declspec(dllexport) short FAR PASCAL QueryCoolFilter(COOLQUERY far * cq)
- { lstrcpy(cq->szName,"MPEG 3");
- lstrcpy(cq->szCopyright,"MPEG (Layer 1,2,3) Decoder (GNU)");
- lstrcpy(cq->szExt,"MP3");
- lstrcpy(cq->szExt2,"MP2");
- lstrcpy(cq->szExt3,"MP1");
- cq->lChunkSize=16384;
- cq->dwFlags=QF_RATEADJUSTABLE|QF_CANLOAD|QF_CANDO32BITFLOATS|QF_HASOPTIONSBOX;
- cq->Stereo8=0;
- cq->Stereo16=R_32075|R_44100|R_48000;
- cq->Stereo24=0;
- cq->Stereo32=R_32075|R_44100|R_48000;
- cq->Mono8=0;
- cq->Mono16=R_32075|R_44100|R_48000;
- cq->Mono24=0;
- cq->Mono32=R_32075|R_44100|R_48000;
- cq->Quad32=0;
- cq->Quad16=0;
- cq->Quad8=0;
- return C_VALIDLIBRARY;
- }
- // Just our little way of not including stdio.h to do float to string cvting
- char * ftos(char *tmp, double d)
- { double dd;
- double mplier;
- short maxdecimal=9;
- char * otemp;
-
- otemp=tmp;
-
- if (d==0)
- { *tmp='0';
- tmp++;
- *tmp=0x00;
- return otemp;
- }
-
- if (d<0)
- { *tmp='-';
- tmp++;
- d=-d;
- }
- d=d+(1.0/65535.0/32768.0);
- dd=d;
- mplier=1.0;
- while (dd>=1.0)
- { dd/=10.0;
- mplier*=10.0;
- }
- mplier/=10.0;
- while (mplier>=1.0)
- { *tmp='0'+(short)(d/mplier);
- tmp++;
- d=d-mplier*(short)(d/mplier);
- mplier/=10.0;
- }
- if (d!=0.0)
- { short digit;
- *tmp='.';
- tmp++;
- while ((d!=0.0) && (maxdecimal!=0))
- { d*=10.0;
- digit=(short)d;
- d-=(double)digit;
- *tmp='0'+digit;
- tmp++;
- maxdecimal--;
- }
- while (*(tmp-1)=='0')
- tmp--;
- if (*(tmp-1)=='.')
- tmp--;
- }
-
- *tmp=0x00;
-
- return otemp;
- }
- __declspec(dllexport) long FAR PASCAL FilterGetFileSize(HANDLE hInput)
- {
- long lSize=0L;
- if (hInput)
- { MYINPUT *mi;
- mi=(MYINPUT *)GlobalLock(hInput);
- lSize=mi->lSize;
- GlobalUnlock(hInput);
- }
- return lSize;
- }
- __declspec(dllexport) BOOL FAR PASCAL FilterGetActualFormat(HANDLE hInput,DWORD dwOptions,long * plSamprate, WORD * pwChannels, WORD * pwBitsPerSample)
- {
- if (hInput)
- { MYINPUT *mi;
- mi=(MYINPUT *)GlobalLock(hInput);
-
- *pwBitsPerSample=HIWORD(dwOptions)&0x00FF;
- GlobalUnlock(hInput);
- }
- return TRUE;
- }
- __declspec(dllexport) BOOL FAR PASCAL FilterUnderstandsFormat(LPSTR filename)
- {
- if ((lstrlen(filename)>4) &&
- ((strcmpi(filename+lstrlen(filename)-4,".mp3")==0) ||
- (strcmpi(filename+lstrlen(filename)-4,".mp2")==0) ||
- (strcmpi(filename+lstrlen(filename)-4,".mp1")==0)
- ))
- {
- return TRUE;
- }
- return FALSE;
- }
- __declspec(dllexport) BOOL FAR PASCAL DIALOGMsgProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
- { switch(Message)
- { case WM_INITDIALOG:
- { WORD wBitsPerSample;
- double fAttenuation;
- BOOL bDither;
- char tmp[30];
- wBitsPerSample=HIWORD(lParam)&0x00FF;
- bDither=(lParam&0x01000000)?TRUE:FALSE;
- fAttenuation=(double)((DWORD)lParam&0xffff)/100.0-200.0;
- if (fAttenuation>200.0)
- fAttenuation=0.0;
- //wsprintf(tmp," Read MPEG As %d-bit ",wBitsPerSample);
- //SetDlgItemText(hWndDlg,IDC_TEXT1,tmp);
-
- if (wBitsPerSample==16)
- { CheckDlgButton(hWndDlg,IDC_RADIO1,TRUE);
- }
- else if (wBitsPerSample==32)
- { CheckDlgButton(hWndDlg,IDC_RADIO2,TRUE);
- }
- else
- { CheckDlgButton(hWndDlg,IDC_RADIO1,TRUE);
- }
-
- CheckDlgButton(hWndDlg,IDC_CHECK1,bDither);
- ftos(tmp,fAttenuation);
- SetDlgItemText(hWndDlg,IDC_EDIT1,tmp);
- EnableWindow(GetDlgItem(hWndDlg,IDC_CHECK1),IsDlgButtonChecked(hWndDlg,IDC_RADIO1)?TRUE:FALSE);
- }
- break;
- case WM_CLOSE:
- PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
- break;
- case WM_COMMAND:
- { WORD wNotifyCode=HIWORD(wParam);
- wParam=(WPARAM)LOWORD(wParam);
- switch(wParam)
- {
- case IDC_RADIO1:
- case IDC_RADIO2:
- EnableWindow(GetDlgItem(hWndDlg,IDC_CHECK1),IsDlgButtonChecked(hWndDlg,IDC_RADIO1)?TRUE:FALSE);
- break;
-
- case IDOK:
- { long nDialogReturn=0;
- char tmp[30];
-
- if (IsDlgButtonChecked(hWndDlg,IDC_RADIO2))
- { nDialogReturn=32L<<16;
- }
- else
- { nDialogReturn=16L<<16;
- }
- GetDlgItemText(hWndDlg,IDC_EDIT1,tmp,29);
- nDialogReturn|=(WORD)max(0,min(40000,(atof(tmp)+200.0)*100.0));
- if (IsDlgButtonChecked(hWndDlg,IDC_CHECK1))
- nDialogReturn|=0x01000000;
- EndDialog(hWndDlg, nDialogReturn);
- }
- break;
- case IDCANCEL:
- EndDialog(hWndDlg, FALSE);
- break;
- }
- break;
- }
- default:
- return FALSE;
- }
- return TRUE;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterGetOptions(HWND hWnd, HINSTANCE hInst, long lSamprate, WORD wChannels, WORD wBitsPerSample, DWORD dwOptions) // return 0 if no options box
- {
- long nDialogReturn=0L;
- FARPROC lpfnDIALOGMsgProc;
- lpfnDIALOGMsgProc = GetProcAddress(hInst,(LPCSTR)MAKELONG(20,0));
-
- if (dwOptions==0)
- {
- nDialogReturn=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
- if (nDialogReturn==0)
- nDialogReturn=(WORD)max(0,min(40000,(100.0+200.0)*100.0));
- }
- else
- nDialogReturn=dwOptions;
-
- // These were to force the dialog to have _only_ 16 or 32... now we let user choose
- //nDialogReturn=(nDialogReturn&0xFF00FFFF)|(((DWORD)wBitsPerSample)<<8);
- //nDialogReturn|=MAKELONG(nDialogReturn&0x0FF,wBitsPerSample);
-
- nDialogReturn = (long)DialogBoxParam((HINSTANCE)hInst,(LPCSTR)MAKEINTRESOURCE(IDD_COMPRESSION), (HWND)hWnd, (DLGPROC)lpfnDIALOGMsgProc,nDialogReturn);
-
- if (nDialogReturn)
- { char m[30];
- wsprintf(m,"%d",nDialogReturn);
- WritePrivateProfileString("MPEG Filter","InputFormat",m,"coolrw.ini");
- }
- return nDialogReturn;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterSetOptions2(HANDLE hInput, DWORD dwOptions, long * plSamprate, WORD * pwChannels, WORD * pwBitsPerSample)
- {
- DWORD dwOldOptions;
- MYINPUT *mi;
- mi=(MYINPUT *)GlobalLock(hInput);
-
- dwOldOptions=mi->dwFormat;
- if (!dwOptions)
- { dwOptions=(DWORD)GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
- if (!dwOptions)
- dwOptions=(WORD)max(0,min(40000,(200.0)*100.0))|(16L<<16);
- }
-
- mi->wBitsPerSample=HIWORD(dwOptions)&0x00FF;
- mi->fAttenuation=(double)((DWORD)dwOptions&0xffff)/100.0-200.0;
- mi->bDither=(dwOptions&0x01000000)?TRUE:FALSE;
-
- mi->dwFormat=dwOptions;
- if ((mi->fAttenuation<-199.0) || (mi->fAttenuation>200.0))
- mi->fAttenuation=0;
- if (mi->wBitsPerSample==16)
- { *pwBitsPerSample=16;
- if (!mi->h32bit)
- { mi->h32bit=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,32768);
- mi->pi32bit=(short *)GlobalLock(mi->h32bit);
- }
- }
- else
- { *pwBitsPerSample=32;
- }
- mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(*plSamprate)/1000.0)*(*pwChannels)*(*pwBitsPerSample/8);
- mi->fScaleBy=(float)(32768.0*(pow(10.0,mi->fAttenuation/20.0)));
-
- GlobalUnlock(hInput);
-
- return dwOldOptions;
-
- }
- // Dummy, but must be here... FilterSetOptions2 is actually called instead if it exists
- __declspec(dllexport) DWORD FAR PASCAL FilterSetOptions(HANDLE hInput, DWORD dwOptions, long lSamprate, WORD wChannels, WORD wBitsPerSample)
- {
- DWORD dwOldOptions;
- MYINPUT *mi;
- mi=(MYINPUT *)GlobalLock(hInput);
-
- dwOldOptions=mi->dwFormat;
- mi->dwFormat=dwOptions;
- mi->wBitsPerSample=HIWORD(dwOptions)&0x00FF;
- mi->fAttenuation=(double)((DWORD)dwOptions&0xffff)/100.0-200.0;
- mi->bDither=(dwOptions&0x01000000)?TRUE:FALSE;
-
- if ((mi->fAttenuation<-199.0) || (mi->fAttenuation>200.0))
- mi->fAttenuation=0;
- if (mi->wBitsPerSample==16)
- { if (!mi->h32bit)
- { mi->h32bit=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,32768);
- mi->pi32bit=(short *)GlobalLock(mi->h32bit);
- }
- }
- mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(lSamprate)/1000.0)*(wChannels)*(wBitsPerSample/8);
- mi->fScaleBy=(float)(32768.0*(pow(10.0,mi->fAttenuation/20.0)));
- GlobalUnlock(hInput);
-
- return dwOldOptions;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterOptions(HANDLE hInput)
- { MYINPUT *mi;
- DWORD dwFormat;
- if (!hInput) return 0;
- mi=(MYINPUT *)GlobalLock(hInput);
-
- dwFormat=(DWORD)mi->dwFormat;
- GlobalUnlock(hInput);
- return dwFormat;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterOptionsString(HANDLE hInput, LPSTR szString)
- { MYINPUT *mi;
- DWORD dwFormat;
-
- if (!hInput) return 0;
- mi=(MYINPUT *)GlobalLock(hInput);
- dwFormat=(DWORD)mi->dwFormat;
- wsprintf(szString,"%s Layer %drn(%s)",mi->mpi.szVersion,mi->mpi.iLayer,mi->mpi.szBitrate);
-
- GlobalUnlock(hInput);
- return dwFormat;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterCanWriteSpecial(HANDLE hOutput, DWORD idType)
- {
- return 0L;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterCanReadSpecial(HANDLE hInput, DWORD idType)
- {
- return 0L;
- }
-
- __declspec(dllexport) DWORD FAR PASCAL FilterWriteSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
- {
- return 0L;
- }
- __declspec(dllexport) DWORD FAR PASCAL FilterReadSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
- {
- return 0L;
- }
- __declspec(dllexport) HANDLE FAR PASCAL OpenFilterOutput(LPSTR lpstrFilename,long lSamprate,WORD wBitsPerSample,WORD wChannels,long lSize,long far *lpChunkSize,DWORD dwOptions)
- { HANDLE hOutput;
- short nFile;
- nFile=_lcreat(lpstrFilename,0);
- if (nFile==-1) return NULL;
- hOutput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(MYOUTPUT));
- if (hOutput)
- { MYOUTPUT *mo;
- mo=(MYOUTPUT *)GlobalLock(hOutput);
- mo->nFile=nFile;
- mo->lSize=lSize;
- GlobalUnlock(hOutput);
- }
- *lpChunkSize=16384;
- return hOutput;
- }
- __declspec(dllexport) void FAR PASCAL CloseFilterOutput(HANDLE hOutput)
- { if (hOutput)
- { MYOUTPUT *mo;
- mo=(MYOUTPUT *)GlobalLock(hOutput);
- if (mo->nFile!=-1)
- { _lclose(mo->nFile);
- mo->nFile=-1;
- }
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- }
- }
- __declspec(dllexport) DWORD FAR PASCAL WriteFilterOutput(HANDLE hOutput, unsigned char far *buf, long lBytes)
- { DWORD written=0L;
- if (hOutput)
- { MYOUTPUT *mo;
- mo=(MYOUTPUT *)GlobalLock(hOutput);
- written=(DWORD)_lwrite(mo->nFile,buf,(UINT)lBytes);
- GlobalUnlock(hOutput);
- }
- return written;
- }
- DWORD valJ=524309;
- DWORD valI=12345; // reset to time at startup
- double fRandom(void) // 0 to 1
- { DWORDLONG dwl;
- dwl=UInt32x32To64(valJ,valI);
- dwl++;
- valI=(DWORD)(dwl&0x1FFFFF);
- return (double)valI/2097152.0;
- }
- // This is the 32-bit to 16-bit converter from Cool Edit, but with only the code
- // for the straight triangular dithering. For higher quality, read in the file
- // as 32-bit, then use Cool Edit Pro's dithering options for going to 16-bit.
- void HfCvt32To16InMem(short *piDest, float *pfSource, long dwSourceSamples, BOOL bStereo, double fDitherAmount)
- { long t;
- double fFilteredError=0;
- double fSourceBeforeNoise;
- double qq=1.0;
- double fMultiplier=0.5;
- double fNoise;
- double fSource;
- double fSqrtDitherAmount;
- long quant;
- static double fError=0;
- static double fError1=0;
- static double fError2=0;
- static double fError3=0;
- static double fError4=0;
- static double fError5=0;
- static double fErrorR=0;
- static double fErrorR1=0;
- static double fErrorR2=0;
- static double fErrorR3=0;
- static double fErrorR4=0;
- static double fErrorR5=0;
-
- {
- if (fDitherAmount>0)
- fSqrtDitherAmount=sqrt(fDitherAmount);
- else
- fSqrtDitherAmount=0;
-
- if (bStereo)
- {
- for (t=0;t<dwSourceSamples;t+=2)
- {
- fFilteredError=0;
-
- fError4=fError3;
- fError3=fError2;
- fError2=fError1;
- fError1=fFilteredError;
-
- fSource=*pfSource;
- pfSource++;
-
- // Don't Shift out 8 bits
- fSource=fSource-fFilteredError; //*fDitherMultiplier;
-
- fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
-
- fSourceBeforeNoise=fSource;
- // Add Noise (v)
- fSource+=fNoise; //*fDitherMultiplier; //*2.0;
-
- // Quantization
- quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
- // Error for input to H(z)
- fError=(double)quant-fSourceBeforeNoise;
- if (quant>=-32768)
- { if (quant<=32767)
- *piDest=(short)quant;
- else
- *piDest=32767;
- }
- else
- *piDest=-32768;
- piDest++;
- fFilteredError=0;
-
- fErrorR4=fErrorR3;
- fErrorR3=fErrorR2;
- fErrorR2=fErrorR1;
- fErrorR1=fFilteredError;
-
- fSource=*pfSource;
- pfSource++;
- // Don't Shift out 8 bits
- fSource=fSource-fFilteredError; //*fDitherMultiplier;
-
- fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
-
- fSourceBeforeNoise=fSource;
- // Add Noise (v)
- fSource+=fNoise; //*fDitherMultiplier; //*2.0;
-
- // Quantization
- quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
- // Error for input to H(z)
- fErrorR=(double)quant-fSourceBeforeNoise;
- if (quant>=-32768)
- { if (quant<=32767)
- *piDest=(short)quant;
- else
- *piDest=32767;
- }
- else
- *piDest=-32768;
- piDest++;
- }
- }
- else
- {
- for (t=0;t<dwSourceSamples;t++)
- { fFilteredError=0;
-
- fError5=fError4;
- fError4=fError3;
- fError3=fError2;
- fError2=fError1;
- fError1=fFilteredError;
- fSource=*pfSource;
- pfSource++;
-
- // Don't Shift out 8 bits
- fSource=fSource-fFilteredError; //*fDitherMultiplier;
- // Triangular Dither Noise
-
- fNoise=fDitherAmount*(fRandom()+fRandom()-1.0);
-
- fSourceBeforeNoise=fSource;
- // Add Noise (v)
- fSource+=fNoise; //*fDitherMultiplier; //*2.0;
-
- // Quantization
- quant=(long)(fSource+500000+0.5)-500000; // floor function, values -1000 to +1000 OK
- // Error for input to H(z)
- fError=(double)quant-fSourceBeforeNoise;
- if (quant>=-32768)
- { if (quant<=32767)
- *piDest=(short)quant;
- else
- *piDest=32767;
- }
- else
- *piDest=-32768;
- piDest++;
- }
- }
- }
- }
- __declspec(dllexport) void FAR PASCAL GetSuggestedSampleType(long far *lSugSamprate,WORD far *wSugBitsPerSample, WORD far *wSugChannels)
- { // return 0 for don't care
- *lSugSamprate=0;
- { int n=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
- *wSugBitsPerSample=HIWORD(n)&0x00FF;
- if ((*wSugBitsPerSample!=16) && (*wSugBitsPerSample!=32))
- *wSugBitsPerSample=16;
- }
- *wSugChannels=0;
- }
- // return handle that will be passed in to close, and write routines
- __declspec(dllexport) HANDLE FAR PASCAL OpenFilterInput( LPSTR lpstrFilename,
- long *lSamprate,
- WORD *wBitsPerSample,
- WORD *wChannels,
- HWND hWnd,
- long *lChunkSize)
- { HANDLE hInput;
- short source;
- long fullsize;
- DWORD dwOptions;
-
- dwOptions=0;
- valI=GetTickCount()%50000;
- source=_lopen(lpstrFilename,OF_READ);
- if (source==-1) return NULL;
-
- fullsize=_llseek(source,0L,2);
- _lclose(source);
-
- hInput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT,sizeof(MYINPUT));
- if (hInput)
- { MYINPUT *mi;
-
- mi=(MYINPUT *)GlobalLock(hInput);
- mi->wBitsPerSample=32;
- mi->fAttenuation=0;
- mi->dwFormat=0; // Force asking of format, and default to 32-bit No attenuation
- mi->fScaleBy=32768.0f;
- mi->bDither=FALSE;
-
- // return 0 for cool to inquire user for sample rates (we aren't doing that though)
- *lSamprate=44100;
- *wBitsPerSample=32;
- *wChannels=2;
- *lChunkSize=16384;
- mi->bOpenedMPEG=MPEG_Open(lpstrFilename);
- if (!mi->bOpenedMPEG)
- { GlobalUnlock(hInput);
- GlobalFree(hInput);
- return NULL;
- }
-
- MPEG_GetInfo(&mi->mpi);
- *lSamprate=mi->mpi.iSamplerate;
- *wChannels=mi->mpi.iChannels;
- { int n=GetPrivateProfileInt("MPEG Filter","InputFormat",0,"coolrw.ini");
- *wBitsPerSample=HIWORD(n)&0x00FF;
- if ((*wBitsPerSample!=16) && (*wBitsPerSample!=32))
- *wBitsPerSample=16;
- }
- mi->wBitsPerSample=*wBitsPerSample;
-
- mi->lSize=(int)(mi->mpi.fLengthInMilliseconds*(*lSamprate)/1000.0)*(*wChannels)*(*wBitsPerSample/8);
- GlobalUnlock(hInput);
- }
-
- return hInput;
- }
- __declspec(dllexport) void FAR PASCAL CloseFilterInput(HANDLE hInput)
- { if (hInput)
- { MYINPUT *mi;
- mi=(MYINPUT *)GlobalLock(hInput);
-
- if (mi->bOpenedMPEG)
- MPEG_Close();
-
- if (mi->h32bit)
- { GlobalUnlock(mi->h32bit);
- GlobalFree(mi->h32bit);
- }
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- }
- }
- __declspec(dllexport) DWORD FAR PASCAL ReadFilterInput(HANDLE hInput, unsigned char far *bufout, long lBytes)
- { DWORD read=0L;
- if (hInput)
- { MYINPUT *mi;
- float fScaleBy;
- mi=(MYINPUT *)GlobalLock(hInput);
- fScaleBy=mi->fScaleBy;
- if (mi->wBitsPerSample==32)
- { // just scale
- read=(DWORD)MPEG_Read(bufout);
-
- { int iNum=read/4;
- float * pBuf=(float *)bufout;
- while (iNum--)
- { *pBuf++*=fScaleBy;
- }
- }
-
- }
- else if (mi->wBitsPerSample==16)
- { // Convert to 16-bit with scaling and dithering
- int iNum;
- float * pfBuf;
- short * piBuf;
- pfBuf=(float *)mi->pi32bit;
- piBuf=(short *)bufout;
- read=(DWORD)MPEG_Read((BYTE *)mi->pi32bit);
- iNum=read/4;
- // Dither it to 16-bit
- if (mi->bDither)
- { // Scale it first
- { int iNum=read/4;
- float * pBuf=pfBuf;
- while (iNum--)
- { *pBuf++*=fScaleBy;
- }
- }
- // Dither and Clip
- HfCvt32To16InMem(piBuf, pfBuf, iNum,
- (mi->mpi.iChannels==2)?TRUE:FALSE, 1.0);
- }
- else
- { // Scale, Truncate, and Clip
- float f;
- while (iNum--)
- { f=*pfBuf++*fScaleBy;
- if (f>=(float)(-32767.0))
- { if (f<=(float)32767.0)
- *piBuf++=(short)f;
- else
- *piBuf++=32767;
- }
- else
- *piBuf++=-32767;
- }
- }
- read/=2;
- }
- GlobalUnlock(hInput);
- }
- return read;
- }