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

📄 in_aac.c

📁 AAC音频解码算法程序
💻 C
字号:

#ifdef PLUGIN

#include <windows.h>
#include <stdio.h>

#include "in2.h"
#include "faad.h"
#include "all.h"


// post this to the main window at end of file (after playback as stopped)
#define WM_WA_AAC_EOF WM_USER+2

// raw configuration
#define NCH 2
#define SAMPLERATE 44100
#define BPS 16


faadAACInfo fInfo;

In_Module mod; // the output module (declared near the bottom of this file)
char lastfn[MAX_PATH]; // currently playing file (used for getting info on the current file)
int file_length; // file length, in bytes
int decode_pos_ms; // current decoding position, in milliseconds
int paused; // are we paused?
int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
char sample_buffer[1024*NCH*(BPS/8)]; // sample buffer

int killPlayThread=0;					// the kill switch for the decode thread
HANDLE play_thread_handle=INVALID_HANDLE_VALUE;	// the handle to the decode thread

DWORD WINAPI __stdcall PlayThread(void *b); // the decode thread procedure

void config(HWND hwndParent)
{
	MessageBox(hwndParent,
		"AAC files without an ADIF header must be 44100kHz\n"
		"and must be encoded using MAIN or LOW profile.\n"
		"When an ADIF header is present, configuration\n"
		"will be done automatically.",
		"Configuration",MB_OK);
}
void about(HWND hwndParent)
{
	MessageBox(hwndParent,"Freeware AAC Player v0.5\nhttp://www.slimline.net/aac/","About AAC Player",MB_OK);
}

void init() { }

void quit() { }

int isourfile(char *fn) { return 0; } 
// used for detecting URL streams.. unused here. strncmp(fn,"http://",7) to detect HTTP streams, etc

int play(char *fn) 
{ 
	int maxlatency;
	int thread_id;

	aac_decode_init(&fInfo, fn);

	strcpy(lastfn,fn);
	paused=0;
	decode_pos_ms=0;
	seek_needed=-1;

	maxlatency = mod.outMod->Open(fInfo.sampling_rate,fInfo.channels, BPS, -1,-1);
	if (maxlatency < 0) // error opening device
	{
		return 1;
	}

	// initialize vis stuff
	mod.SAVSAInit(maxlatency, fInfo.sampling_rate);
	mod.VSASetInfo(fInfo.sampling_rate, fInfo.channels);

	mod.outMod->SetVolume(-666); // set the output plug-ins default volume

	killPlayThread = 0;
	play_thread_handle = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) PlayThread,(void *) &killPlayThread,0,&thread_id);

	return 0; 
}

void pause() { paused=1; mod.outMod->Pause(1); }
void unpause() { paused=0; mod.outMod->Pause(0); }
int ispaused() { return paused; }

void stop()
{
	if (play_thread_handle != INVALID_HANDLE_VALUE)
	{
		killPlayThread=1;
		if (WaitForSingleObject(play_thread_handle,INFINITE) == WAIT_TIMEOUT)
		{
			MessageBox(mod.hMainWindow,"error asking thread to die!\n","error killing decode thread",0);
			TerminateThread(play_thread_handle,0);
		}
		CloseHandle(play_thread_handle);
		play_thread_handle = INVALID_HANDLE_VALUE;
	}
	aac_decode_free();

	mod.outMod->Close();

	mod.SAVSADeInit();
}

int getlength()
{
//	return (int)((file_length/(((Bitrate*8)/1000)*BPS))*1000);
	return fInfo.length;
}

int getoutputtime() { 
	return decode_pos_ms+(mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime()); 
}

void setoutputtime(int time_in_ms) { 
	seek_needed=time_in_ms; 
}

void setvolume(int volume) { mod.outMod->SetVolume(volume); }
void setpan(int pan) { mod.outMod->SetPan(pan); }


int EOFfound = 0;
unsigned long bitbuf;
unsigned int subbitbuf;
int bitcount;
#define CHAR_BIT 8
#define BITBUFSIZ (CHAR_BIT * sizeof(bitbuf))


void fillbuf(int n, FILE *file)
{
	bitbuf <<= n;
	while (n > bitcount) {
		bitbuf |= subbitbuf << (n -= bitcount);
		subbitbuf = (unsigned char) fgetc(file);
		bitcount = CHAR_BIT;
	}
	bitbuf |= subbitbuf >> (bitcount -= n);
}

unsigned int TMPgetbits(int n, FILE *file)
{
	unsigned int x;

	x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n, file);
	return x;
}


void init_getbits(FILE *file)
{
	bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
	fillbuf(BITBUFSIZ, file);
}

int infoDlg(char *fn, HWND hwnd)
{
	char Info[500];
	char *strProfile;
	char adif_id[5];
	FILE *file;
	int i;
	int unused;
	int bitstream, bitrate, profile, sr_idx, srate;
	static int SampleRates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};

	file = fopen(fn,"rb");
	for (i=0; i<LEN_ADIF_ID; i++)
		adif_id[i] = fgetc(file);
	adif_id[i] = 0;

	if (strncmp(adif_id, "ADIF", 4) == 0) {
		init_getbits(file);

		/* copyright string */	
		if ((TMPgetbits(LEN_COPYRT_PRES, file)) == 1) {
			for (i=0; i<LEN_COPYRT_ID; i++)
				unused = TMPgetbits(LEN_BYTE, file); 
		}
		unused = TMPgetbits(LEN_ORIG, file);
		unused = TMPgetbits(LEN_HOME, file);
		bitstream = TMPgetbits(LEN_BS_TYPE, file);
		bitrate = TMPgetbits(LEN_BIT_RATE, file);

		/* program config elements */ 
		TMPgetbits(LEN_NUM_PCE, file);
		unused = (bitstream == 0) ? TMPgetbits(LEN_ADIF_BF, file) : 0;
		TMPgetbits(LEN_TAG, file);

		profile = TMPgetbits(LEN_PROFILE, file);
		sr_idx = TMPgetbits(LEN_SAMP_IDX, file);
		if (profile == Main_Profile)
			strProfile = "Main";
		else if (profile == LC_Profile)
			strProfile = "Low Complexity";
		else if (profile == 2 /* SSR */)
			strProfile = "SSR (unsupported)";

		srate = SampleRates[sr_idx];

		wsprintf(Info,
			"%s\n\n"
			"ADIF header info:\n"
			"Profile: %s\n"
			"Bitrate: %dbps\n"
			"Sampling rate: %dHz\n"
			"Channels: %d\n",
			fn, strProfile, bitrate, srate, 2);
		MessageBox(hwnd, Info, "AAC file info box",MB_OK);
	} else {
		wsprintf(Info,
			"%s\n\n"
			"No ADIF header found\n"
			"Assumed configuration:\n"
			"Profile: Main\n"
			"Bitrate: 128000bps\n"
			"Sampling rate: 44100Hz\n"
			"Channels: 2\n",
			fn);
		MessageBox(hwnd, Info, "AAC file info box",MB_OK);
	}

	fclose(file);

	return 0;
}

LPTSTR PathFindFileName(LPCTSTR pPath)
{
    LPCTSTR pT;

    for (pT = pPath; *pPath; pPath = CharNext(pPath)) {
        if ((pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) && pPath[1] && (pPath[1] != TEXT('\\')))
            pT = pPath + 1;
    }

    return (LPTSTR)pT;   // const -> non const
}

int getbitrate(char *fn)
{
	FILE *file;
	char adif_id[5];
	int i, unused, bitrate;

	file = fopen(fn,"rb");
	for (i=0; i<LEN_ADIF_ID; i++)
		adif_id[i] = fgetc(file);
	adif_id[i] = 0;

	if (strncmp(adif_id, "ADIF", 4) == 0) {
		init_getbits(file);

		/* copyright string */	
		if ((TMPgetbits(LEN_COPYRT_PRES, file)) == 1) {
			for (i=0; i<LEN_COPYRT_ID; i++)
				unused = TMPgetbits(LEN_BYTE, file); 
		}
		unused = TMPgetbits(LEN_ORIG, file);
		unused = TMPgetbits(LEN_HOME, file);
		unused = TMPgetbits(LEN_BS_TYPE, file);
		bitrate = TMPgetbits(LEN_BIT_RATE, file);
	} else
		bitrate = 128000;

	fclose(file);

	return bitrate;
}

void getfileinfo(char *filename, char *title, int *length_in_ms)
{
	if (!filename || !*filename)  // currently playing file
	{
		if (length_in_ms) *length_in_ms=getlength();
		if (title) 
		{
			char *p=lastfn+strlen(lastfn);
			while (*p != '\\' && p >= lastfn) p--;
			strcpy(title,++p);
			if (title[lstrlen(title)-4] == '.')
				title[lstrlen(title)-4] = '\0';
		}
	}
	else // some other file
	{
		if (length_in_ms) 
		{
			HANDLE hFile;
			*length_in_ms=-1000;
			hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
				OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
			if (hFile != INVALID_HANDLE_VALUE)
			{
				int bitrate = getbitrate(filename);
				*length_in_ms = (GetFileSize(hFile,NULL)/(((bitrate*8)/1000)*BPS))*1000;
			}
			CloseHandle(hFile);
		}
		if (title) 
		{
			char *p=filename+strlen(filename);
			while (*p != '\\' && p >= filename) p--;
			strcpy(title,++p);
			if (title[lstrlen(title)-4] == '.')
				title[lstrlen(title)-4] = '\0';
		}
	}
}

void eq_set(int on, char data[10], int preamp) 
{ 
}

DWORD WINAPI __stdcall PlayThread(void *b)
{
	int done=0;
	int framebits = 0;
	int tmp_bits;
	int framecount = 0;

	char sample_buffer[2048*2];

	int frame = 0;
	int last_frame = 0;

	while (! *((int *)b) ) 
	{
		if (done)
		{
			mod.outMod->CanWrite();
			if (!mod.outMod->IsPlaying())
			{
				PostMessage(mod.hMainWindow,WM_WA_AAC_EOF,0,0);
				return 0;
			}
			Sleep(10);
		}
		else if (mod.outMod->CanWrite() >= ((1024*fInfo.channels*2)<<(mod.dsp_isactive()?1:0)))
		{
			int l = 1024*2*fInfo.channels;
			if (last_frame) 
			{
				done=1;
			}
			else
			{
				tmp_bits = aac_decode_frame((short*)sample_buffer);

				if (!tmp_bits)
					last_frame = 1;
				framebits += tmp_bits;
				framecount++;
				if (framecount==(int)(fInfo.sampling_rate/8192))
				{
					mod.SetInfo((int)(((framebits*8)/1000)*1.08+0.5),fInfo.sampling_rate/1000,fInfo.channels,1);
					framecount = 0;
					framebits = 0;
				}
				if ((frame > 0)&&(!stop_now)) {
					mod.SAAddPCMData(sample_buffer,fInfo.channels,BPS,decode_pos_ms);
					mod.VSAAddPCMData(sample_buffer,fInfo.channels,BPS,decode_pos_ms);
					decode_pos_ms+=(1024*1000)/fInfo.sampling_rate;
					if (mod.dsp_isactive()) l=mod.dsp_dosamples((short *)sample_buffer,l/fInfo.channels/(BPS/8),BPS,fInfo.channels,fInfo.sampling_rate)*(fInfo.channels*(BPS/8));
					mod.outMod->Write(sample_buffer,l);
				}
				frame++;
			}
		}
		else Sleep(10);
	}
	return 0;
}

void CommonWarning(char *message)
{
	MessageBox(mod.hMainWindow,message,"Warning...",MB_OK);
}

void CommonExit(int errorcode, char *message)
{
	MessageBox(mod.hMainWindow,message,"Error...",MB_OK);
	stop_now = 1;
}

In_Module mod = 
{
	IN_VER,
	"Freeware AAC Decoder v0.5",
	0,	// hMainWindow
	0,  // hDllInstance
	"AAC\0AAC File (*.AAC)\0"
	,
	0,	// is_seekable
	1, // uses output
	config,
	about,
	init,
	quit,
	getfileinfo,
	infoDlg,
	isourfile,
	play,
	pause,
	unpause,
	ispaused,
	stop,
	
	getlength,
	getoutputtime,
	setoutputtime,

	setvolume,
	setpan,

	0,0,0,0,0,0,0,0,0, // vis stuff


	0,0, // dsp

	eq_set,

	NULL,		// setinfo

	0 // out_mod

};

__declspec( dllexport ) In_Module * winampGetInModule2()
{
	return &mod;
}

#endif // PLUGIN

⌨️ 快捷键说明

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