📄 audiosource.cpp
字号:
,BOS=2
,EOS=4
};
char Magic[4]; // The String "OggS" in ASCII
uint8 Version; // Currently 0
uint8 Flags; // Enf of stream, Beginning of stream
uint64 GranulePos; // Not used for header packets. This is big endian !!!
uint32 Serial; // serial number of the stream used for multiplexing/chaining
uint32 PageNumber; // Page number within the stream
uint32 CRC; // CRC value, similar to the ZIP CRC32, but with swapped bits. For more info I can provide a small Java class.
uint8 LacingCount;
};
#pragma pack()
uint8*HeaderStart[3]={Header[0],Header[1],Header[2]};
const uint8*BufferStart=Buffer;
for(size_t PacketIndex=0;PacketIndex<3;)
{
// Read the next header
if(BufferSize<sizeof(PageHeader))
return false; // No data available for fixed header
// Read the fixed header
const PageHeader*CurrentPageHeader=reinterpret_cast<const PageHeader*>(Buffer);
Buffer+=sizeof(PageHeader);
BufferSize-=sizeof(PageHeader);
// Verify some fields
if(CurrentPageHeader->Magic[0]!='O'
||CurrentPageHeader->Magic[1]!='g'
||CurrentPageHeader->Magic[2]!='g'
||CurrentPageHeader->Magic[3]!='S'
)
return false; // Our minimum requirement failed, see above for details
if(CurrentPageHeader->LacingCount>BufferSize)
return false; // No data available for lacing values
const uint8*CurrentLacings=Buffer;
Buffer+=CurrentPageHeader->LacingCount;
BufferSize-=CurrentPageHeader->LacingCount;
for(uint8 LacingIndex=0;PacketIndex<3&&LacingIndex<CurrentPageHeader->LacingCount;)
{
for(;PacketIndex<3&&LacingIndex<CurrentPageHeader->LacingCount;++LacingIndex)
{
if(BufferSize<CurrentLacings[LacingIndex])
return false; // No more data for the current part
// Copy the data
if(HeaderSize[PacketIndex]<CurrentLacings[LacingIndex])
return false; // No more space in output buffer
memcpy(Header[PacketIndex],Buffer,CurrentLacings[LacingIndex]);
HeaderSize[PacketIndex]-=CurrentLacings[LacingIndex];
Header[PacketIndex]+=CurrentLacings[LacingIndex];
Buffer+=CurrentLacings[LacingIndex];
if(CurrentLacings[LacingIndex]<255)
{
// Found new end of packet. If this is the last header
// packet, we must be at the page end.
if(PacketIndex==2&&LacingIndex<(CurrentPageHeader->LacingCount-1))
return false;
++PacketIndex;
}
}
}
}
// Buffer points to the end of the last header page
SplitPosition=Buffer-BufferStart;
for(size_t i=0;i<3;++i)
{
HeaderSize[i]=Header[i]-HeaderStart[i];
Header[i]=HeaderStart[i];
}
return true;
}
BOOL AudioSourceOggVorbis::init() {
if( !f ) return FALSE;
char *buffer;
int bytes;
ogg_sync_init(&oy); /* Now we can read pages */
if( streamInit()==FALSE ) return FALSE;
fseek( f, 0, SEEK_SET );
uint8* Buffer = (uint8*)malloc( pos );
size_t Size = fread( Buffer, 1, pos, f );
uint8* Header = (uint8*)malloc( pos );
uint8* Comments = (uint8*)malloc( pos );
uint8* Codebook = (uint8*)malloc( pos );
if( Buffer==NULL || Header==NULL || Comments==NULL || Codebook==NULL ) {
failed:
if( Buffer ) free( Buffer );
if( Header ) free( Header );
if( Comments ) free( Comments );
if( Codebook ) free( Codebook );
return FALSE;
}
size_t SplitPosition;
size_t PacketSizes[] = { pos, pos, pos };
uint8* PacketAddresses[] = { Header, Comments, Codebook };
if( splitHeader( Buffer, Size, SplitPosition, PacketAddresses, PacketSizes )==FALSE )
goto failed;
int s = sizeof(WAVEFORMATEXTENSIBLE)+3*sizeof(size_t)+PacketSizes[0]+PacketSizes[1]+PacketSizes[2];
s = (s+7) & -8;
if( !allocFormat( s ) )
goto failed;
// prepare WAVEFORMAT
WAVEFORMATEXTENSIBLE *wfext = (WAVEFORMATEXTENSIBLE *)getWaveFormat();
wfext->Format.wFormatTag = 0xFFFE; // WAVE_FORMAT_EXTENSIBLE
wfext->Format.nChannels = vi.channels;
wfext->Format.nSamplesPerSec = vi.rate;
wfext->Format.nAvgBytesPerSec = 176400;
wfext->Format.nBlockAlign = 20000; // ahem, testing...
wfext->Format.wBitsPerSample = 0;
wfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)
+3*sizeof(size_t)
+PacketSizes[0]+PacketSizes[1]+PacketSizes[2]
-sizeof(WAVEFORMATEX);
// wfext->Samples.wValidBitsPerSample = 0; /* bits of precision */
// wfext->Samples.wSamplesPerBlock = 0; /* valid if wBitsPerSample==0 */
wfext->Samples.wReserved = 0; /* If neither applies, set to zero. */
wfext->dwChannelMask = (1<<vi.channels)-1;
// {6BA47966-3F83-4178-9665-00F0BF6292E5}
// DEFINE_GUID(MEDIASUBTYPE_VorbisStream,0x6ba47966, 0x3f83, 0x4178, 0x96, 0x65, 0x0, 0xf0, 0xbf, 0x62, 0x92, 0xe5);
GUID guid = { 0x6ba47966, 0x3f83, 0x4178, { 0x96, 0x65, 0x0, 0xf0, 0xbf, 0x62, 0x92, 0xe5 } };
wfext->SubFormat = guid;
// append the Ogg headers to the Wav header
char* p = (char*)getWaveFormat()+sizeof(WAVEFORMATEXTENSIBLE);
*(size_t*)p = PacketSizes[0]; p += sizeof(size_t);
*(size_t*)p = PacketSizes[1]; p += sizeof(size_t);
*(size_t*)p = PacketSizes[2]; p += sizeof(size_t);
memcpy( p, PacketAddresses[0], PacketSizes[0] ); p += PacketSizes[0];
memcpy( p, PacketAddresses[1], PacketSizes[1] ); p += PacketSizes[1];
memcpy( p, PacketAddresses[2], PacketSizes[2] ); p += PacketSizes[2];
// We need to know the length of the stream. Sure, there are other methods...
int tot_pcm_samples = 0;
// vorbis_synthesis_init( &vd, &vi );
// vorbis_block_init( &vd, &vb );
while( !eos ) {
while( !eos ) {
int result = ogg_sync_pageout( &oy, &og );
if( result==0 ) break;
if( result<0 ){
//fprintf(stderr,"Corrupt or missing data in bitstream; continuing...\n");
}else{
ogg_stream_pagein( &os, &og );
while( TRUE ) {
result = ogg_stream_packetout( &os, &op );
if( result==0 ) break;
if( result<0 ) {
/* no reason to complain; already complained above */
}else{
int samples;
float **pcm;
if( vorbis_synthesis( &vb, &op )==0 ) /* test for success! */
vorbis_synthesis_blockin( &vd, &vb );
if( (samples=vorbis_synthesis_pcmout( &vd, &pcm ))>0) {
tot_pcm_samples += samples;
vorbis_synthesis_read( &vd, samples );
}
}
}
if( ogg_page_eos( &og ) ) eos = 1;
}
}
if( !eos ) {
buffer = ogg_sync_buffer( &oy, 1 );
bytes = fread( buffer, 1, 1, f);
ogg_sync_wrote( &oy, bytes );
if( bytes==0 ) eos = 1;
}
}
ogg_stream_clear( &os );
vorbis_block_clear( &vb );
vorbis_dsp_clear( &vd );
vorbis_comment_clear( &vc );
vorbis_info_clear( &vi );
// init some variables
lSampleFirst = 0;
lSampleLast = (tot_pcm_samples/20000)+1;
pcm_samples = 0;
pcm_written = 0;
// reset the input
fseek( f, 0, SEEK_SET );
streamInit();
while( pcm_samples<20000 ) {
readPage();
decodePage();
}
lCurrentSample = 0;
if( Buffer ) free( Buffer );
if( Header ) free( Header );
if( Comments ) free( Comments );
if( Codebook ) free( Codebook );
// prepare StreamInfo
streamInfo.fccType = streamtypeAUDIO;
streamInfo.fccHandler = 0;
streamInfo.dwFlags = 0;
streamInfo.wPriority = 0;
streamInfo.wLanguage = 0;
streamInfo.dwInitialFrames = 0;
streamInfo.dwScale = 20000;
streamInfo.dwRate = vi.rate;
streamInfo.dwStart = 0;
streamInfo.dwLength = lSampleLast;
streamInfo.dwSuggestedBufferSize = 0;
streamInfo.dwQuality = 0xffffffff;
streamInfo.dwSampleSize = 0;
return TRUE;
}
void AudioSourceOggVorbis::readPage()
{
char *buffer;
int bytes;
while( eos==0 && ogg_sync_pageout( &oy, &og )!=1 ) {
buffer = ogg_sync_buffer( &oy, 1 );
bytes = fread( buffer, 1, 1, f );
ogg_sync_wrote( &oy, bytes );
if( bytes==0 ) eos = 1;
}
}
void AudioSourceOggVorbis::decodePage()
{
ogg_stream_pagein( &os, &og );
while( TRUE ) {
int result = ogg_stream_packetout( &os, &op );
if( result==0 ) break;
if( result<0 ) {
/* no reason to complain; already complained above */
}else{
int samples;
float **pcm;
if( vorbis_synthesis( &vb, &op )==0 ) /* test for success! */
vorbis_synthesis_blockin( &vd, &vb );
if( (samples=vorbis_synthesis_pcmout( &vd, &pcm ))>0) {
pcm_samples += samples;
vorbis_synthesis_read( &vd, samples );
}
}
}
if( ogg_page_eos( &og ) ) eos = 1;
}
int AudioSourceOggVorbis::_read(LONG lStart, LONG lCount, LPVOID buffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead)
{
*lSamplesRead = 0;
*lBytesRead = 0;
if( buffer ) {
if (lStart != lCurrentSample) {
ogg_stream_clear( &os );
vorbis_block_clear( &vb );
vorbis_dsp_clear( &vd );
vorbis_comment_clear( &vc );
vorbis_info_clear( &vi );
fseek( f, 0, SEEK_SET );
streamInit();
readPage();
lCurrentSample = 0;
while( lStart != lCurrentSample ) {
fgetpos( f, &pos );
readPage();
lCurrentSample++;
}
}
__int64 pos2;
fgetpos( f, &pos2 );
uint32 frame_size = (uint32)pos2 - pos;
if( frame_size>cbBuffer ) return AVIERR_OK;
fseek( f, pos, SEEK_SET );
fread( buffer, frame_size, 1, f );
cbBuffer -= frame_size;
buffer = (void *)(((unsigned long)buffer)+frame_size);
(*lBytesRead) += frame_size;
pcm_samples -= 20000;
pos = pos2;
while( pcm_samples<20000 ) {
readPage();
decodePage();
}
lCurrentSample++;
(*lSamplesRead) = 1;
}
return AVIERR_OK;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
AudioSourceAC3::AudioSourceAC3(char *szFile, LONG inputBufferSize)
{
ac3File = fopen(szFile,"rb");
}
AudioSourceAC3::~AudioSourceAC3()
{
if (ac3File!=NULL) fclose(ac3File);
}
BOOL AudioSourceAC3::init()
{
WAVEFORMATEX *fmt, ac3WFmt;
if( ac3File==NULL ) return FALSE;
// extract WAVEFORMATEX from the AC3 file
AC3FileSrc *ac3Src = new AC3FileSrc(ac3File);
if( !ac3Src->Parse(&ac3WFmt) ) {
delete ac3Src;
return FALSE;
}
delete ac3Src;
// allocate format structure
if (!(fmt=(WAVEFORMATEX *) allocFormat(sizeof(WAVEFORMATEX)))) return FALSE;
*fmt = ac3WFmt;
{
char szBuf[256];
sprintf(szBuf, "FmtTag: 0x%x, SampFreq: %d, Channels: %d, bitrate: %d kb/s",
fmt->wFormatTag,
fmt->nSamplesPerSec,
fmt->nChannels,
(fmt->nAvgBytesPerSec*8)/1000);
MessageBox(NULL,szBuf,"AC3 file parameters",MB_OK);
}
// get the length of the file
fseek(ac3File,0,SEEK_END);
chunkDATA.cksize = ftell(ac3File);
chunkDATA.dwDataOffset = 0;
fseek(ac3File,0,SEEK_SET);
bytesPerSample= getWaveFormat()->nBlockAlign; //getWaveFormat()->nAvgBytesPerSec / getWaveFormat()->nSamplesPerSec;
lSampleFirst = 0;
lSampleLast = chunkDATA.cksize / bytesPerSample;
lCurrentSample= 0;
streamInfo.fccType = streamtypeAUDIO;
streamInfo.fccHandler = 0;
streamInfo.dwFlags = 0;
streamInfo.wPriority = 0;
streamInfo.wLanguage = 0;
streamInfo.dwInitialFrames = 0;
streamInfo.dwScale = bytesPerSample;
streamInfo.dwRate = getWaveFormat()->nAvgBytesPerSec;
streamInfo.dwStart = 0;
streamInfo.dwLength = chunkDATA.cksize / bytesPerSample;
streamInfo.dwSuggestedBufferSize = 0;
streamInfo.dwQuality = 0xffffffff;
streamInfo.dwSampleSize = bytesPerSample;
return TRUE;
}
int AudioSourceAC3::_read(LONG lStart, LONG lCount, LPVOID buffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead)
{
LONG lBytes = lCount * bytesPerSample;
if (lStart != lCurrentSample)
if (-1 == fseek(ac3File, chunkDATA.dwDataOffset + bytesPerSample*lStart, SEEK_SET))
return AVIERR_FILEREAD;
if (lBytes != fread((char *)buffer, 1, lBytes, ac3File))
return AVIERR_FILEREAD;
*lSamplesRead = lCount;
*lBytesRead = lBytes;
lCurrentSample = lStart + lCount;
return AVIERR_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -