📄 in_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 + -