⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3.c

📁 MP3解压程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  @(#) 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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -