www.pudn.com > 播放mp3的控件.rar > stream.cpp


#include  
#include  
#include "stream.h" 
#include "args.h" 
#include "player.h" 
 
// Bitrate index,in order: MPEG version,layer,bitrate index  
int BitRateIndex[2][3][16]= 
{{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, 
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,}, 
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,}}, 
{{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, 
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, 
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}}}; 
 
struct ibuf  
{ 
    struct ibuf *next; 
    struct ibuf *prev; 
    unsigned char *buf; 
    unsigned char *pnt; 
    int len; 
}; 
 
struct ibuf ibufs[2]; 
struct ibuf *cibuf; 
unsigned char bsspace[2][MAXFRAMESIZE+512],*bsbuf=bsspace[1],*bsbufold; 
static HGLOBAL MBHnd; 
static char *MappedBuffer = NULL; 
static DWORD MappedPointer = 0; 
static int framesize; 
 
int bitindex; 
unsigned char *wordpointer; 
HANDLE StreamHandle; 
bool StreamOpen; 
unsigned long StreamSize; 
ID3TagStruct *ID3; 
bool ID3TagSupported;  
int ibufnum, fsize, fsizeold, ssize, bsnum; 
unsigned long oldhead,firsthead, MinFrames, MaxFrames; 
esInputMode InputMode; 
 
bool StreamInit = false; 
 
bool Init_Stream(){ 
    StreamSize = 0;  
    char *buf = (char *)malloc(128); 
    SECURITY_ATTRIBUTES Sec; 
    long numread; 
    // Set the security attributes  
    Sec.nLength = sizeof(SECURITY_ATTRIBUTES); 
    Sec.lpSecurityDescriptor = false; 
    Sec.bInheritHandle = false; 
    // Open the stream using CreateFile 
    InputMode = Args->InputMode;     
    if (InputMode == imCallback) { 
        if (!Args->InOpenCB(Args->InCBData1, &Args->InCBData2, &Args->Seekable)) { 
            free(buf);  
            throw 1; 
        }; 
        if (!Args->InGetSizeCB(Args->InCBData1, Args->InCBData2, &StreamSize)) { 
            free(buf);  
            throw 1; 
        }; 
    } else { 
        // Open the stream using CreateFile 
        StreamHandle = CreateFile(Args->InName, GENERIC_READ, FILE_SHARE_READ,&Sec, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); 
        if(StreamHandle == INVALID_HANDLE_VALUE) {  
            free(buf);  
            throw 1;         
        }; 
        StreamSize = GetFileSize(StreamHandle, NULL); 
    } 
 
    // Set "stream is open" flag 
    StreamOpen = true; 
     
    if (InputMode == imCallback) { 
        if (!Args->InSeekCB(Args->InCBData1, Args->InCBData2, -128, FILE_END)) { 
            ID3TagSupported=false; 
        } else 
        if (!Args->InReadCB (Args->InCBData1, Args->InCBData2, buf, 127, (DWORD*) &numread) || (numread != 127)) { 
            free(buf); 
            throw 1; 
        } 
    } else { 
        // Seek to filelength - 128, the desired position for the ID3V1 Tag struct  
        if (SetFilePointer(StreamHandle,-128, 0, FILE_END) == 0xFFFFFFFF) { 
            ID3TagSupported=false; 
        } else  
        if (!ReadFile(StreamHandle, buf, 127, (DWORD*) &numread, NULL) || (numread != 127))  { 
            free(buf); 
            throw 1; 
        } 
    }     
    // Cast the buf to a ID3Tag structure  
    ID3=(ID3TagStruct *)buf; 
    // Check for "TAG" at the beginning,validating the tag 
    if (ID3->TagHeader[0]==84&&ID3->TagHeader[1]==65&&ID3->TagHeader[2]==71) ID3TagSupported=true; else ID3TagSupported=false; 
    // Sets the file pointer back to file begin 
    if (InputMode == imCallback) { 
        if (!Args->InSeekCB(Args->InCBData1, Args->InCBData2, 0, FILE_BEGIN)) { 
            free(buf); 
            throw 1; 
        } 
    } else { 
        // Seek to filelength - 128, the desired position for the ID3V1 Tag struct  
        if (SetFilePointer(StreamHandle, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) { 
            free(buf); 
            throw 1; 
        } 
    }     
    // Global initializations 
    ibufnum=0;fsize=0,fsizeold=0;bsnum=0;oldhead=0;firsthead=0; 
    StreamInit = true;     
    return true; 
} 
 
/* 
int BackFrame(int num) 
{ 
    long bytes; 
    long numread=1; 
    unsigned char buf[4]; 
    unsigned long newhead; 
    if(!firsthead)      return 0; 
    bytes=(fsize+8)*(num+2); 
     
     
 
    if(SetFilePointer(StreamHandle,-bytes,NULL,FILE_CURRENT)<0) return 0; 
     
    bool Res=ReadFile(StreamHandle,buf,4,(DWORD*)&numread,NULL); 
    if(!Res||numread!=4) return 0; 
    newhead=(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; 
    while((newhead&HDRCMPMASK)!=(firsthead&HDRCMPMASK))  
    { 
        Res=ReadFile(StreamHandle,buf,1,(DWORD*)&numread,NULL); 
        if(!Res||numread!=1) return 0; 
        newhead<<=8; 
        newhead|=buf[0]; 
        newhead&=0xffffffff; 
    } 
    if(SetFilePointer(StreamHandle,-4,NULL,FILE_CURRENT)<0) return 0; 
    ReadFrame(); 
    ReadFrame(); 
    if(fr.lay==3) SetPointer(512); 
    return 0; 
} 
*/ 
int head_read(unsigned char *hbuf,unsigned long *newhead) 
{ 
    long numread; 
    bool res; 
    if (InputMode == imCallback)  
        res = Args->InReadCB (Args->InCBData1, Args->InCBData2, hbuf, 4, (DWORD *)&numread); 
    else  
        res=ReadFile(StreamHandle, hbuf, 4, (DWORD *)&numread, NULL); 
     
    if(!res||numread!=4) return FALSE; 
    *newhead=((unsigned long) hbuf[0] << 24) | 
        ((unsigned long) hbuf[1] << 16) | 
        ((unsigned long) hbuf[2] << 8)  | 
        (unsigned long) hbuf[3]; 
    return TRUE; 
} 
 
int head_check(unsigned long newhead)  
{ 
    if((newhead&0xffe00000)!=0xffe00000) return FALSE; 
    if(!((newhead>>17)&3))      return FALSE; 
    if(((newhead>>12)&0xf)==0xf) return FALSE; 
    if(((newhead>>10)&0x3)==0x3) return FALSE; 
    return TRUE; 
} 
 
int ReadFrame() 
{ 
    static unsigned char ssave[34]; 
    static int halfphase = 0; 
    int l;long temp,numread=0; 
    int tryme = 0; 
    unsigned char hbuf[8]; 
    static unsigned long newhead; 
    bool Res; 
 
read_again: 
    int tmpsize=4; 
    if(!head_read(hbuf,&newhead)) { 
        LastError = peInputError; 
        throw 1; 
    } 
    if(oldhead!=newhead||!oldhead) 
    { 
        fr.header_change = 1; 
init_resync: 
        if(!firsthead&&!head_check(newhead)) { 
            int i; 
            if(newhead==('R'<<24)+('I'<<16)+('F'<<8)+'F') 
            { 
                char buf[68]; 
                 
                if (InputMode ==imCallback)  
                    Res = Args->InReadCB (Args->InCBData1, Args->InCBData2, buf, 68, (DWORD*) &numread); 
                else  
                    Res = ReadFile(StreamHandle, buf, 68, (DWORD*) &numread, NULL); 
 
                if(Res&&numread==0) return -2; 
                if(!Res||numread!=68) throw 1; 
                goto read_again; 
            } 
            for(i=0;i<512;i++)  
            { 
                if(!head_read(hbuf,&newhead)) throw 1; 
                if(head_check(newhead)) break; 
            } 
            if(i==512)  
            { 
                for(i=0;i<2048;i++)  
                { 
                    memmove(&hbuf[0],&hbuf[1],3); 
                     
                    if (InputMode ==imCallback)  
                        Res = Args->InReadCB (Args->InCBData1, Args->InCBData2, hbuf+3, 1, (DWORD*) &numread); 
                    else  
                        Res = ReadFile(StreamHandle, hbuf+3, 1, (DWORD*) &numread, NULL); 
                     
                    if(Res&&numread==0) return -2; 
                    if(!Res||numread!=1) throw 1; 
                    newhead<<=8; 
                    newhead|=hbuf[3]; 
                    newhead&=0xffffffff; 
                    if(head_check(newhead)) break; 
                } 
                if(i==2048) return FALSE;  
            } 
        } 
        if((newhead&0xffe00000)!=0xffe00000)  
        { 
            if(Args->TryResync)  
            { 
                do  
                { 
                    tryme++; 
                    memmove(&hbuf[0],&hbuf[1],7); 
                     
                    if (InputMode ==imCallback)  
                        Res = Args->InReadCB (Args->InCBData1, Args->InCBData2, &hbuf[3], 1, (DWORD*) &numread); 
                    else  
                        Res = ReadFile(StreamHandle, &hbuf[3], 1, (DWORD*) &numread, NULL); 
 
                    if(Res&&numread==0) return -2; 
                    if(!Res||numread!=1) throw 1; 
                    newhead=((newhead<<8)|hbuf[3])&0xffffffff; 
                    if(!oldhead) goto init_resync; 
                } while((newhead&HDRCMPMASK)!=(oldhead&HDRCMPMASK)&&(newhead&HDRCMPMASK)!=(firsthead&HDRCMPMASK)); 
            } else return (0); 
        } 
        if(!firsthead) firsthead=newhead; 
        if(newhead&(1<<20))  
        { 
            fr.lsf=(newhead&(1<<19))?0x0:0x1; 
            fr.mpeg25 = 0; 
        } else  
        { 
            fr.lsf = 1; 
            fr.mpeg25 = 1; 
        } 
        if(!Args->TryResync||!oldhead)  
        { 
            fr.lay = 4-((newhead>>17)&3); 
            fr.bitrate_index = ((newhead>>12)&0xf); 
            if(((newhead>>10)&0x3)==0x3) { 
                throw 1; 
            } 
            if(fr.mpeg25) fr.sampling_frequency=6+((newhead>>10)&0x3); 
            else fr.sampling_frequency=((newhead>>10)&0x3)+(fr.lsf*3); 
            fr.error_protection=((newhead>>16)&0x1)^0x1; 
        } 
        if(fr.mpeg25) fr.bitrate_index = ((newhead>>12)&0xf); 
        fr.padding   = ((newhead>>9)&0x1); 
        fr.extension = ((newhead>>8)&0x1); 
        fr.mode      = ((newhead>>6)&0x3); 
        fr.mode_ext  = ((newhead>>4)&0x3); 
        fr.copyright = ((newhead>>3)&0x1); 
        fr.original  = ((newhead>>2)&0x1); 
        fr.emphasis  = newhead & 0x3; 
        fr.stereo    = (fr.mode == MPG_MD_MONO) ? 1 : 2; 
        if(FreqIndex[fr.sampling_frequency]>44100) fr.sampling_frequency=0; 
        oldhead = newhead; 
        if(!fr.bitrate_index) 
        { 
            // No free format allowed ;) 
            throw 1; 
        } 
        switch(fr.lay) 
        { 
        case 1: 
            fr.WhatLayer=1;  
            fr.jsbound=(fr.mode==MPG_MD_JOINT_STEREO)?(fr.mode_ext<<2)+4:32; 
            framesize=(long)BitRateIndex[fr.lsf][0][fr.bitrate_index]*12000; 
            framesize/=FreqIndex[fr.sampling_frequency]; 
            framesize=((framesize+fr.padding)<<2)-4; 
            break; 
        case 2: 
            fr.WhatLayer=2;  
            GetLayer2(); 
            fr.jsbound=(fr.mode==MPG_MD_JOINT_STEREO)?(fr.mode_ext<<2)+4:fr.II_sblimit; 
            framesize=(long)BitRateIndex[fr.lsf][1][fr.bitrate_index]*144000; 
            framesize/=FreqIndex[fr.sampling_frequency]; 
            framesize+=fr.padding - 4; 
            break; 
        case 3: 
            fr.WhatLayer=3;  
            if(fr.lsf) ssize=(fr.stereo==1)?9:17; 
            else ssize=(fr.stereo==1)?17:32; 
            if(fr.error_protection) ssize += 2; 
            framesize=(long)BitRateIndex[fr.lsf][2][fr.bitrate_index] * 144000; 
            framesize/=FreqIndex[fr.sampling_frequency]<<(fr.lsf); 
            framesize=framesize + fr.padding - 4; 
            break;  
        default: 
            throw 1;             
        } 
    } else fr.header_change=0; 
    fsizeold=fsize; 
    bsbufold=bsbuf;         
    bsbuf=bsspace[bsnum]+512; 
    bsnum=(bsnum+1)&1; 
    fsize=framesize; 
 
    if (InputMode ==imCallback)  
        Res = Args->InReadCB (Args->InCBData1, Args->InCBData2, bsbuf,fsize, (DWORD*) &numread); 
    else  
        Res = ReadFile(StreamHandle, bsbuf,fsize, (DWORD*) &numread, NULL); 
     
    if(Res&&numread==0) return -2; 
    if(!Res||numread!=fsize) { 
        memset(bsbuf+numread,0,fsize-numread); 
    }  
    bitindex=0; 
    wordpointer=(unsigned char *)bsbuf; 
    MaxFrames = GetMaxFrames(); 
    MinFrames = GetMinFrames(); 
    return 1; 
} 
 
ID3TagStruct* GetID3Tag() 
{ 
    if(ID3TagSupported) 
    {  
        ID3->Title[29]=0;ID3->Album[29]=0;ID3->Artist[29]=0;ID3->Comment[29]=0;ID3->Year[4]=0;    
        return(ID3); 
    } 
    return NULL; 
} 
 
// Return stream bitrate 
unsigned long GetBitrate() 
{ 
    return BitRateIndex[fr.lsf][fr.lay-1][fr.bitrate_index]*1000; 
} 
 
// Return stream samplerate 
unsigned long GetSampleRate() 
{ 
    return(FreqIndex[fr.sampling_frequency]); 
} 
 
// Get the minimum count of frames in the stream 
unsigned long GetMinFrames() 
{ 
    return(StreamSize/(CalcFramesize()+4-fr.padding)); 
} 
 
// Get the maximum count of frames in the stream 
unsigned long GetMaxFrames() 
{ 
    return(StreamSize/(CalcFramesize()+5-fr.padding)); 
} 
 
// Return framesize 
unsigned long CalcFramesize() 
{ 
    return framesize; 
} 
 
// Returns the milli seconds one frame has 
real Frame2ms() 
{ 
    static real ms_per_frame_array[3][3]={{8.707483f,8.0f,12.0f},{26.12245f,24.0f,36.0f},{26.12245f,24.0f, 36.0f}}; 
    return(ms_per_frame_array[1][fr.sampling_frequency]); 
} 
 
real Totalms() 
{ 
    return(GetMaxFrames()*Frame2ms()); 
} 
 
unsigned long Currentms() 
{ 
    return(Args->CurrentPos*Frame2ms()); 
} 
 
bool Seek_Stream(unsigned long Position) 
{ 
    unsigned long Posi = Position/Frame2ms(); 
    if(Posi>0&&PosiInSeekCB(Args->InCBData1, Args->InCBData2, CalcFramesize()*Posi, FILE_BEGIN)) { 
                return false; 
            } 
        } else { 
            if (SetFilePointer(StreamHandle, CalcFramesize()*Posi, 0, FILE_BEGIN) == 0xFFFFFFFF)  
                return false; 
        } 
 
        SetFilePointer(StreamHandle,CalcFramesize()*Posi,0,FILE_BEGIN); 
        Args->CurrentPos=Posi; 
read_again:  
        int Res = ReadFrame(); 
        if(Res) Args->CurrentPos++;  
        if(!Res&&Res!=-2) goto read_again; 
        return true;  
    } 
    return false; 
} 
 
void Reset_Stream() 
{ 
    if (InputMode ==imCallback) { 
        if (!Args->InSeekCB(Args->InCBData1, Args->InCBData2, 0, FILE_BEGIN)) { 
            return; 
        } 
    } else { 
        if (SetFilePointer(StreamHandle, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)  
            return; 
    } 
    Args->CurrentPos=0; 
} 
 
#if !defined(I386_ASSEM) 
unsigned long GetBits(int number_of_bits) 
{ 
    unsigned long rval; 
    if(!number_of_bits) return 0; 
    { 
        rval = wordpointer[0]; 
        rval <<= 8; 
        rval |= wordpointer[1]; 
        rval <<= 8; 
        rval |= wordpointer[2]; 
        rval <<= bitindex; 
        rval &= 0xffffff; 
        bitindex += number_of_bits; 
        rval >>= (24-number_of_bits); 
        wordpointer += (bitindex>>3); 
        bitindex &= 7; 
    } 
    return rval; 
} 
 
unsigned long GetBitsFast(int number_of_bits) 
{ 
    unsigned long rval; 
    { 
        rval = wordpointer[0]; 
        rval <<= 8;      
        rval |= wordpointer[1]; 
        rval <<= bitindex; 
        rval &= 0xffff; 
        bitindex += number_of_bits; 
        rval >>= (16-number_of_bits); 
        wordpointer += (bitindex>>3); 
        bitindex &= 7; 
    } 
    return rval; 
} 
 
unsigned long Get1Bit(void) 
{ 
    unsigned char rval; 
    rval = *wordpointer << bitindex; 
    bitindex++; 
    wordpointer += (bitindex>>3); 
    bitindex &= 7; 
    return rval>>7; 
} 
#endif 
 
void SetPointer(long backstep) 
{ 
    wordpointer=bsbuf+ssize-backstep; 
    if(backstep) memcpy(wordpointer,bsbufold+fsizeold-backstep,backstep); 
    bitindex=0;  
} 
 
bool Done_Stream(){ 
    if(StreamOpen) CloseHandle(StreamHandle); 
    StreamInit = false; 
    return true; 
}