AudioSource.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:24k
- // VirtualDub - Video processing and capture application
- // Copyright (C) 1998-2001 Avery Lee
- //
- // 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 <stdio.h>
- #include <stdlib.h>
- #include <windows.h>
- #include <vfw.h>
- #include "AudioSource.h"
- #include "AVIReadHandler.h"
- #include "AC3FileSrc.h"
- AudioSourceWAV::AudioSourceWAV(char *szFile, LONG inputBufferSize) {
- MMIOINFO mmi;
- memset(&mmi,0,sizeof mmi);
- mmi.cchBuffer = inputBufferSize;
- hmmioFile = mmioOpen(szFile, &mmi, MMIO_READ | MMIO_ALLOCBUF);
- }
- AudioSourceWAV::~AudioSourceWAV() {
- mmioClose(hmmioFile, 0);
- }
- BOOL AudioSourceWAV::init() {
- if (!hmmioFile) return FALSE;
- chunkRIFF.fccType = mmioFOURCC('W','A','V','E');
- if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkRIFF, NULL, MMIO_FINDRIFF))
- return FALSE;
- chunkDATA.ckid = mmioFOURCC('f','m','t',' ');
- if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkDATA, &chunkRIFF, MMIO_FINDCHUNK))
- return FALSE;
- if (!allocFormat(chunkDATA.cksize)) return FALSE;
- if (chunkDATA.cksize != mmioRead(hmmioFile, (char *)getWaveFormat(), chunkDATA.cksize))
- return FALSE;
- if (MMSYSERR_NOERROR != mmioAscend(hmmioFile, &chunkDATA, 0))
- return FALSE;
- chunkDATA.ckid = mmioFOURCC('d','a','t','a');
- if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkDATA, &chunkRIFF, MMIO_FINDCHUNK))
- return FALSE;
- 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 AudioSourceWAV::_read(LONG lStart, LONG lCount, LPVOID buffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
- LONG lBytes = lCount * bytesPerSample;
-
- if (buffer) {
- if (lStart != lCurrentSample)
- if (-1 == mmioSeek(hmmioFile, chunkDATA.dwDataOffset + bytesPerSample*lStart, SEEK_SET))
- return AVIERR_FILEREAD;
- if (lBytes != mmioRead(hmmioFile, (char *)buffer, lBytes))
- return AVIERR_FILEREAD;
- lCurrentSample = lStart + lCount;
- }
- *lSamplesRead = lCount;
- *lBytesRead = lBytes;
- return AVIERR_OK;
- }
- ///////////////////////////
- AudioSourceAVI::AudioSourceAVI(IAVIReadHandler *pAVI) {
- pAVIFile = pAVI;
- pAVIStream = NULL;
- }
- AudioSourceAVI::~AudioSourceAVI() {
- if (pAVIStream)
- delete pAVIStream;
- }
- BOOL AudioSourceAVI::init() {
- LONG format_len;
- pAVIStream = pAVIFile->GetStream(streamtypeAUDIO, 0);
- if (!pAVIStream) return FALSE;
- if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
- return FALSE;
- pAVIStream->FormatSize(0, &format_len);
- if (!allocFormat(format_len)) return FALSE;
- if (pAVIStream->ReadFormat(0, getFormat(), &format_len))
- return FALSE;
- lSampleFirst = pAVIStream->Start();
- lSampleLast = pAVIStream->End();
- return TRUE;
- }
- void AudioSourceAVI::Reinit() {
- pAVIStream->Info(&streamInfo, sizeof streamInfo);
- lSampleFirst = pAVIStream->Start();
- lSampleLast = pAVIStream->End();
- }
- bool AudioSourceAVI::isStreaming() {
- return pAVIStream->isStreaming();
- }
- void AudioSourceAVI::streamBegin(bool fRealTime) {
- pAVIStream->BeginStreaming(lSampleFirst, lSampleLast, fRealTime ? 1000 : 2000);
- }
- void AudioSourceAVI::streamEnd() {
- pAVIStream->EndStreaming();
- }
- BOOL AudioSourceAVI::_isKey(LONG lSample) {
- return pAVIStream->IsKeyFrame(lSample);
- }
- int AudioSourceAVI::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lpBytesRead, LONG *lpSamplesRead) {
- int err;
- long lBytes, lSamples;
- // There are some video clips roaming around with truncated audio streams
- // (audio streams that state their length as being longer than they
- // really are). We use a kludge here to get around the problem.
- err = pAVIStream->Read(lStart, lCount, lpBuffer, cbBuffer, lpBytesRead, lpSamplesRead);
- if (err != AVIERR_FILEREAD)
- return err;
- // Suspect a truncated stream.
- //
- // AVISTREAMREAD_CONVENIENT will tell us if we're actually encountering a
- // true read error or not. At least for the AVI handler, it returns
- // AVIERR_ERROR if we've broached the end.
- *lpBytesRead = *lpSamplesRead = 0;
- while(lCount > 0) {
- err = pAVIStream->Read(lStart, AVISTREAMREAD_CONVENIENT, NULL, 0, &lBytes, &lSamples);
- if (err)
- return 0;
- if (!lSamples) return AVIERR_OK;
- if (lSamples > lCount) lSamples = lCount;
- err = pAVIStream->Read(lStart, lSamples, lpBuffer, cbBuffer, &lBytes, &lSamples);
- if (err)
- return err;
- lpBuffer = (LPVOID)((char *)lpBuffer + lBytes);
- cbBuffer -= lBytes;
- lCount -= lSamples;
- *lpBytesRead += lBytes;
- *lpSamplesRead += lSamples;
- }
- return AVIERR_OK;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // Dummy CRC pointer
- Crc16 *crc;
- AudioSourceMP3::AudioSourceMP3(char *szFile) {
- stream = new Ibitstream(szFile);
- header = new Header;
- f = fopen( szFile, "rb" );
- }
- AudioSourceMP3::~AudioSourceMP3() {
- if( f ) fclose( f );
- delete header;
- delete stream;
- }
- BOOL AudioSourceMP3::init() {
- if( !f ) return FALSE;
- if (!header->read_header(stream, &crc)){
- return FALSE;
- }
- do {
- } while( header->read_header(stream, &crc) );
- real s_len = (stream->current_frame()+1)*header->ms_per_frame()/1000;
- if (!allocFormat(sizeof MPEGLAYER3WAVEFORMAT)) return FALSE;
- MPEGLAYER3WAVEFORMAT *mp3format = (MPEGLAYER3WAVEFORMAT *)getWaveFormat();
- mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; /* format type */
- mp3format->wfx.nChannels = (header->mode() == single_channel) ? 1 : 2; /* number of channels (i.e. mono, stereo...) */
- mp3format->wfx.nSamplesPerSec = header->frequency(); /* sample rate */
- mp3format->wfx.nAvgBytesPerSec = stream->file_size()/s_len; /* for buffer estimation */
- mp3format->wfx.nBlockAlign = 1152; /* block size of data */
- mp3format->wfx.wBitsPerSample = 0; /* Number of bits per sample of mono data */
- mp3format->wfx.cbSize = 12; /* The count in bytes of the size of
- extra information (after cbSize) */
- mp3format->wID = 1;
- mp3format->fdwFlags = 2;
- mp3format->nBlockSize = stream->file_size()/(stream->current_frame()+1);
- mp3format->nFramesPerBlock = 1;
- mp3format->nCodecDelay = 0;
- lSampleFirst = 0;
- lSampleLast = stream->current_frame()+1;
- streamInfo.fccType = streamtypeAUDIO;
- streamInfo.fccHandler = 0;
- streamInfo.dwFlags = 0;
- streamInfo.wPriority = 0;
- streamInfo.wLanguage = 0;
- streamInfo.dwInitialFrames = 0;
- streamInfo.dwScale = 1152;
- streamInfo.dwRate = header->frequency();
- streamInfo.dwStart = 0;
- streamInfo.dwLength = lSampleLast;
- streamInfo.dwSuggestedBufferSize = 0;
- streamInfo.dwQuality = 0xffffffff;
- streamInfo.dwSampleSize = 0;
- delete header;
- header = new Header;
- stream->reset();
- pos = 0;
- header->read_header(stream, &crc);
- return TRUE;
- }
- int AudioSourceMP3::_read(LONG lStart, LONG lCount, LPVOID buffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead)
- {
- *lSamplesRead = 0;
- *lBytesRead = 0;
- if( buffer )
- {
- if (lStart != stream->current_frame())
- {
- delete header;
- header = new Header;
- stream->reset();
- while( stream->current_frame() != lStart )
- {
- pos = stream->file_pos();
- header->read_header(stream, &crc);
- }
- }
- uint32 frame_size = stream->file_pos() - 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;
- pos = stream->file_pos();
- header->read_header(stream, &crc);
- (*lSamplesRead) = 1;
- }
-
- return AVIERR_OK;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- AudioSourceOggVorbis::AudioSourceOggVorbis(char *szFile) {
- f = fopen( szFile, "rb" );
- pos = 0;
- }
- AudioSourceOggVorbis::~AudioSourceOggVorbis() {
- if( f ) fclose( f );
- }
- #ifndef _WAVEFORMATEXTENSIBLE_
- #define _WAVEFORMATEXTENSIBLE_
- #pragma pack(1)
- typedef struct {
- WAVEFORMATEX Format;
- union {
- WORD wValidBitsPerSample; /* bits of precision */
- WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
- WORD wReserved; /* If neither applies, set to zero. */
- } Samples;
- DWORD dwChannelMask; /* which channels are */
- /* present in stream */
- GUID SubFormat;
- } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
- #pragma pack()
- #endif // !_WAVEFORMATEXTENSIBLE_
- BOOL AudioSourceOggVorbis::streamInit() {
- char *buffer;
- int bytes;
- eos = 0;
- while( ogg_sync_pageout( &oy, &og )!=1 ) {
- buffer = ogg_sync_buffer( &oy, 1 );
- bytes = fread( buffer, 1, 1, f );
- ogg_sync_wrote( &oy, bytes );
- }
- ogg_stream_init( &os, ogg_page_serialno( &og ) );
- vorbis_info_init( &vi );
- vorbis_comment_init( &vc );
- if( ogg_stream_pagein( &os, &og )<0 ) {
- return FALSE;
- }
- if( ogg_stream_packetout( &os, &op )!=1 ) {
- return FALSE;
- }
- if( vorbis_synthesis_headerin( &vi, &vc, &op )<0 ) {
- return FALSE;
- }
-
- int i = 0;
- while( i<2 ) {
- while( i<2 ) {
- int result = ogg_sync_pageout( &oy, &og );
- if( result==0 ) break; /* Need more data */
- /* Don't complain about missing or corrupt data yet. We'll
- catch it at the packet output phase */
- if( result==1 ) {
- ogg_stream_pagein( &os, &og ); /* we can ignore any errors here
- as they'll also become apparent
- at packetout */
- while( i<2 ) {
- result = ogg_stream_packetout( &os, &op );
- if( result==0 ) break;
- if( result<0 ) {
- /* Uh oh; data at some point was corrupted or missing!
- We can't tolerate that in a header. Die. */
- return FALSE;
- }
- vorbis_synthesis_headerin( &vi, &vc, &op );
- i++;
- }
- }
- }
- /* no harm in not checking before adding more */
- buffer = ogg_sync_buffer( &oy, 1 );
- bytes = fread( buffer, 1, 1, f );
- if( bytes==0 && i<2 ) {
- return FALSE;
- }
- ogg_sync_wrote( &oy, bytes );
- }
- fgetpos( f, &pos );
- --pos;
- vorbis_synthesis_init( &vd, &vi );
- vorbis_block_init( &vd, &vb );
- return TRUE;
- }
- typedef unsigned __int8 uint8;
- //typedef unsigned __int32 uint32;
- typedef unsigned __int64 uint64;
- bool splitHeader( const uint8* Buffer, size_t BufferSize, size_t& SplitPosition, uint8** Header,size_t*HeaderSize )
- {
- // Just for your information, here's the format of an Ogg Page header:
- #pragma pack(1)
- struct PageHeader
- {
- // Flag values
- enum
- {
- CONTINUED=1
- ,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;
- }