AudioCodec.cpp
上传用户:lusi_8715
上传日期:2007-01-08
资源大小:199k
文件大小:13k
- /**************************************************************************************
- * *
- * This application contains code from OpenDivX and is released as a "Larger Work" *
- * under that license. Consistant with that license, this application is released *
- * under the GNU General Public License. *
- * *
- * The OpenDivX license can be found at: http://www.projectmayo.com/opendivx/docs.php *
- * The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
- * *
- * Copyright (c) 2001 - Project Mayo *
- * *
- * Authors: Damien Chavarria <adrc at projectmayo.com> *
- * *
- **************************************************************************************/
- #include "AudioCodec.h"
- /*
- * Class functions
- */
- /*
- * Private wrapper
- * around my C functions
- *
- */
- int AudioCodec::DecompressMp3(char *outmemory, int outmemsize, int *done)
- {
- if(this->last_result == MP3_OK) {
- this->last_result = decodeMP3(&this->mp, NULL, 0, outmemory, outmemsize, done);
-
- if(this->last_result == MP3_NEED_MORE) {
-
- if( this->decaps->ReadAudio(this->in_buffer, 16384) != -1) {
-
- this->last_result = decodeMP3(&this->mp, this->in_buffer, 16384, outmemory, outmemsize, done);
- return 1;
- }
- else {
-
- return 0;
- }
- }
- else {
- return 1;
- }
- }
- else {
-
- if( this->decaps->ReadAudio(this->in_buffer, 16384) != -1) {
- this->last_result = decodeMP3(&this->mp, this->in_buffer, 16384, outmemory, outmemsize, done);
- return 1;
- }
- else {
-
- return 0;
- }
- }
- }
- /*
- * Constructor : tries to init the stream
- *
- */
- AudioCodec::AudioCodec(AviDecaps *decaps, WAVEFORMATEX *lpWave)
- {
- this->mpeg = 0;
- this->acm = 0;
- this->in_buffer = NULL;
- this->out_buffer = NULL;
- this->oFormat = NULL;
- memset(&this->mp, 0, sizeof(this->mp));
- if(lpWave) {
- this->decaps = decaps;
- if(lpWave->wFormatTag == 85 /* MP3 */) {
-
- InitMP3(&this->mp);
-
- this->last_result = MP3_NEED_MORE;
- ring_init();
- this->in_buffer = (char *) malloc(INPUT_BUFFER_SIZE);
- this->out_buffer = (char *) malloc(65536);
- if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == MP3_ERR) {
- ExitMP3(&this->mp);
- return;
- }
-
- /*
- * Buffering
- */
- while(!ring_full(this->real_size))
- {
- this->DecompressMp3(this->out_buffer, 16384, &this->real_size);
- ring_write(this->out_buffer, this->real_size);
- }
- this->mpeg = 1;
- /*
- * and sets up the output
- * format for the renderer
- */
- this->oFormat = (WAVEFORMATEX *) malloc(sizeof(WAVEFORMATEX));
- memcpy(this->oFormat, lpWave, sizeof(WAVEFORMATEX));
-
- this->oFormat->wFormatTag = WAVE_FORMAT_PCM;
- if (oFormat->wBitsPerSample != 8 && oFormat->wBitsPerSample != 16)
- oFormat->wBitsPerSample = 16;
- if (oFormat->nChannels!=1 && oFormat->nChannels!=2)
- oFormat->nChannels = 2;
- oFormat->nBlockAlign = (oFormat->wBitsPerSample/8) * oFormat->nChannels;
- oFormat->nAvgBytesPerSec = oFormat->nBlockAlign * oFormat->nSamplesPerSec;
- oFormat->cbSize = 0;
- }
- else {
- MMRESULT mmres;
- this->oFormat = (WAVEFORMATEX *) malloc(sizeof(WAVEFORMATEX));
-
- memcpy(this->oFormat, lpWave, sizeof(WAVEFORMATEX));
- this->oFormat->wFormatTag = WAVE_FORMAT_PCM;
- mmres = acmStreamOpen(&hacm, NULL, lpWave, this->oFormat, NULL, NULL, 0, 0);
- if(mmres != 0) {
- /*
- * No Audio
- */
- return;
- }
- /*
- * Here we have a valid stream
- *
- */
- ring_init();
- this->in_buffer = (char *) malloc(INPUT_BUFFER_SIZE);
- this->out_buffer = (char *) malloc(256000);
- this->acmInLeft = 0;
- this->acmLeft = 0;
- this->acm = 1;
- //Decompress(this->out_buffer, 0);
- }
- }
- }
- /*
- * Destructor: Cleanup.
- *
- */
- AudioCodec::~AudioCodec()
- {
- if(this->in_buffer != NULL) {
- free(this->in_buffer);
- }
- if(this->out_buffer) {
- free(this->out_buffer);
- }
-
- if(this->oFormat) {
- free(this->oFormat);
- }
- }
- /*
- * Return TRUE is codec is
- * ready to decompress
- */
- BOOL AudioCodec::IsOK()
- {
- return (this->mpeg == 1 || this->acm == 1);
- }
- /*
- * Return the output format
- * (used by the renderer)
- *
- */
- WAVEFORMATEX *AudioCodec::GetFormat()
- {
- return this->oFormat;
- }
- /*
- * Empty all buffers
- *
- */
- int AudioCodec::EmptyBuffers()
- {
- ring_init();
- if(this->mpeg) {
-
- this->last_result = MP3_NEED_MORE;
- ExitMP3(&this->mp);
- InitMP3(&this->mp);
- }
- return 1;
- }
- /*
- * decompress size octets of
- * audio to buffer
- *
- */
- int AudioCodec::Decompress(void *buffer, int size)
- {
- int i;
- if(this->mpeg) {
- char msg[256];
- if(size == 0)
- return 1;
- if(size < 4096) {
- /*
- * we only read once
- */
- while(!ring_full(this->real_size)) {
-
- if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == 1) {
- ring_write(this->out_buffer, this->real_size);
- }
- else {
- return 0;
- }
- }
-
- ring_read((char *) buffer, size);
- }
- else {
- int blocks = size / 4096;
- for(i = 0; i < blocks; i++) {
-
- while(!ring_full(this->real_size)) {
-
- if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == 1) {
- ring_write(this->out_buffer, this->real_size);
- }
- else {
- return 0;
- }
- }
-
- ring_read(((char *) buffer) + i*4096, 4096);
- }
- /*
- * the last bit
- */
-
- int left = size - (blocks * 4096);
- if(left > 0)
- ring_read(((char *) buffer) + (blocks - 1)*4096, left);
- }
- }
- else {
- if(this->acm) {
- MMRESULT res;
- if(size < 4096) {
- if(this->acmLeft > 0 && !ring_full(this->acmLeft)) {
-
- /*
- * Copy what we have left
- */
-
- ring_write((char *) this->out_buffer, this->acmLeft);
- this->acmLeft = 0;
- }
- if(this->acmLeft > 0)
- goto done;
-
- if(!this->acmInLeft)
- this->decaps->ReadAudio(this->in_buffer, 2048);
- memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
-
- this->acmHeader.cbStruct = sizeof(ACMSTREAMHEADER);
-
- if(this->acmInLeft > 0) {
-
- this->acmHeader.pbSrc = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
- this->acmHeader.cbSrcLength = this->acmInLeft;
-
- this->acmInLeft = 0;
- }
- else {
- this->acmHeader.pbSrc = (unsigned char *) this->in_buffer;
- this->acmHeader.cbSrcLength = 2048;
- }
-
- this->acmHeader.pbDst = (unsigned char *) this->out_buffer;
- this->acmHeader.cbDstLength = 256000;
- res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
- }
- res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Could not convert", "", MB_OK);
- }
- while(!ring_full(this->acmHeader.cbDstLengthUsed)) {
-
- /*
- * We store it
- */
- ring_write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
- /*
- * unprepare and start again
- */
- acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(!this->acmInLeft)
- this->decaps->ReadAudio(this->in_buffer, 2048);
- memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
- this->acmHeader.cbStruct = sizeof(ACMSTREAMHEADER);
-
- if(this->acmInLeft > 0) {
-
- this->acmHeader.pbSrc = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
- this->acmHeader.cbSrcLength = this->acmInLeft;
-
- this->acmInLeft = 0;
- }
- else {
- this->acmHeader.pbSrc = (unsigned char *) this->in_buffer;
- this->acmHeader.cbSrcLength = 2048;
- }
- this->acmHeader.pbDst = (unsigned char *) this->out_buffer;
- this->acmHeader.cbDstLength = 256000;
-
- res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
- }
- res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Could not convert", "", MB_OK);
- }
-
- this->acmInLeft = 2048 - this->acmHeader.cbSrcLengthUsed;
- }
- this->acmLeft = this->acmHeader.cbDstLengthUsed;
-
- acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
- done:
-
- ring_read((char *) buffer, size);
-
- return 1;
- }
- else {
-
- int blocks = size / 4096;
-
- for(i = 0; i < blocks; i++) {
- if(this->acmLeft > 0 && !ring_full(this->acmLeft)) {
-
- /*
- * Copy what we have left
- */
-
- ring_write((char *) this->out_buffer, this->acmLeft);
- this->acmLeft = 0;
- }
- if(this->acmLeft > 0)
- goto done2;
-
- if(!this->acmInLeft)
- this->decaps->ReadAudio(this->in_buffer, 2048);
- memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
-
- this->acmHeader.cbStruct = sizeof(ACMSTREAMHEADER);
-
- if(this->acmInLeft > 0) {
-
- this->acmHeader.pbSrc = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
- this->acmHeader.cbSrcLength = this->acmInLeft;
-
- this->acmInLeft = 0;
- }
- else {
- this->acmHeader.pbSrc = (unsigned char *) this->in_buffer;
- this->acmHeader.cbSrcLength = 2048;
- }
-
- this->acmHeader.pbDst = (unsigned char *) this->out_buffer;
- this->acmHeader.cbDstLength = 256000;
- res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
- }
-
- res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Could not convert", "", MB_OK);
- }
- while(!ring_full(this->acmHeader.cbDstLengthUsed)) {
-
- /*
- * We store it
- */
- ring_write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
- /*
- * unprepare and start again
- */
-
- acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(!this->acmInLeft)
- this->decaps->ReadAudio(this->in_buffer, 2048);
- memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
- this->acmHeader.cbStruct = sizeof(ACMSTREAMHEADER);
-
- if(this->acmInLeft > 0) {
-
- this->acmHeader.pbSrc = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
- this->acmHeader.cbSrcLength = this->acmInLeft;
-
- this->acmInLeft = 0;
- }
- else {
- this->acmHeader.pbSrc = (unsigned char *) this->in_buffer;
- this->acmHeader.cbSrcLength = 2048;
- }
- this->acmHeader.pbDst = (unsigned char *) this->out_buffer;
- this->acmHeader.cbDstLength = 256000;
-
- res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
- }
- res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
-
- if(res > 0) {
-
- MessageBox(NULL, "Could not convert", "", MB_OK);
- }
-
- this->acmInLeft = 2048 - this->acmHeader.cbSrcLengthUsed;
- }
- this->acmLeft = this->acmHeader.cbDstLengthUsed;
-
- acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
- done2:
-
- ring_read(((char *) buffer) + i*4096, 4096);
- }
- /*
- * The last bit
- */
-
- int left = size - (blocks * 4096);
- if(left > 0)
- ring_read(((char *) buffer) + (blocks - 1)*4096, left);
- }
- }
- }
- return 1;
- }
- /*
- * Returns the codec Name
- *
- */
- char *AudioCodec::GetCodecName()
- {
- if(this->mpeg == 1) {
- return "MPEG-1 Layer-3 audio codec";
- }
- else {
- if(this->hacm != NULL) {
- char *name;
- HACMDRIVERID dId;
- ACMDRIVERDETAILS details;
- name = (char *) malloc(128);
- if(acmDriverID((HACMOBJ) this->hacm, &dId, 0) > 0) {
-
- return NULL;
- }
- memset(&details, 0, sizeof(ACMDRIVERDETAILS));
- details.cbStruct = sizeof(ACMDRIVERDETAILS);
- if(acmDriverDetails(dId, &details, 0) == MMSYSERR_INVALHANDLE) {
- return NULL;
- }
- strcpy(name, details.szLongName);
- return name;
- }
- }
- return NULL;
- }
- /*
- * Closes the decding engine
- *
- */
- int AudioCodec::Close()
- {
- if(this->mpeg) {
- ExitMP3(&this->mp);
- }
- return 1;
- }