161 lines
5.6 KiB
C++
161 lines
5.6 KiB
C++
//
|
|
// tools/audwaveencoder/waveencoder_xenon.cpp
|
|
//
|
|
// Copyright (C) 1999-2005 Rockstar Games. All Rights Reserved.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "forceinclude/win32_release.h"
|
|
|
|
#ifdef __XENON
|
|
#undef __XENON
|
|
#endif // __XENON
|
|
#define __XENON 1
|
|
|
|
#include "libresample.h"
|
|
#include "math.h"
|
|
#include "stdio.h"
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4201)//Nonstandard extension used : nameless struct/union
|
|
#pragma warning(disable: 4668)//#if condition not defined
|
|
#pragma comment(lib, "XMAClean.lib")
|
|
#pragma comment(lib, "Ws2_32.lib")//don't ask
|
|
//#define __servprov_h__
|
|
#include "waveencoder_xenon.h"
|
|
|
|
static const unsigned int g_XmaBlockSamples = 128;
|
|
|
|
#include "xmaencoder.h"
|
|
#include "xmaclean.h"
|
|
|
|
//FILE _iob[];
|
|
//FILE *_iob = __iob_func();
|
|
extern "C" {
|
|
FILE _iob[3] = {__iob_func()[0], __iob_func()[1], __iob_func()[2]};
|
|
}
|
|
|
|
|
|
|
|
namespace audWaveEncoding {
|
|
|
|
bool audWaveEncoderXenon::Encode(audWaveMetadataBaseWrapper *waveMetadataInWrapped, unsigned int waveSampleDataOffsetBytes,
|
|
void **waveMetadataOut, unsigned int &waveMetadataOutLengthBytes, void **waveSampleDataOut,
|
|
unsigned int &waveSampleDataOutLengthBytes, int compression, int &preloopPadding, unsigned int &/*outBitsInLastPacket*/)
|
|
{
|
|
XMAENCODERSTREAM stream = {0};
|
|
WAVEFORMATEXTENSIBLE waveFormat = {0};
|
|
DWORD encodeFlags = 0;
|
|
audWaveMetadataBase *waveMetadataIn = waveMetadataInWrapped->GetMetadata();
|
|
|
|
if(waveMetadataIn->loopStartOffsetSamples >= 0)
|
|
{
|
|
//Align pre-loop and loop lengths via resampling and zero-padding.
|
|
if(!AlignLoop(waveMetadataIn, g_XmaBlockSamples, preloopPadding))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
stream.LoopStart = waveMetadataIn->loopStartOffsetSamples ;
|
|
stream.LoopLength = waveMetadataIn->lengthSamples - (waveMetadataIn->loopStartOffsetSamples);
|
|
encodeFlags = XMAENCODER_LOOP;
|
|
}
|
|
|
|
//Setup convoluted input data structures.
|
|
waveFormat.Format.wFormatTag = WAVE_FORMAT_PCM;
|
|
waveFormat.Format.nChannels = 1;
|
|
waveFormat.Format.nSamplesPerSec = waveMetadataIn->sampleRate;
|
|
waveFormat.Format.nBlockAlign = 2;
|
|
waveFormat.Format.nAvgBytesPerSec = waveFormat.Format.nBlockAlign * waveFormat.Format.nSamplesPerSec;
|
|
waveFormat.Format.wBitsPerSample = 16;
|
|
|
|
stream.Format = waveFormat;
|
|
stream.pBuffer = waveMetadataIn->waveData;
|
|
stream.BufferSize = waveMetadataIn->lengthBytes;
|
|
|
|
VOID *encodedData = NULL;
|
|
DWORD numEncodedDataBytes;
|
|
XMAWAVEFORMAT *encodedDataFormat = NULL;
|
|
DWORD numEncodedDataFormatBytes;
|
|
DWORD *seekTable = NULL;
|
|
DWORD numSeekTableBytes;
|
|
|
|
//Perform XMA encode using static library.
|
|
if(FAILED(XMAInMemoryEncoder(1, &stream, compression, encodeFlags, &encodedData, &numEncodedDataBytes,
|
|
&encodedDataFormat, &numEncodedDataFormatBytes, &seekTable, &numSeekTableBytes)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*try DWORD LastBitsInLastPacket=0;
|
|
DWORD CountOfBits=0;
|
|
CXMAClean x;
|
|
HRESULT result = S_OK;
|
|
|
|
|
|
{
|
|
result = x.CleanStream(false, false, (BYTE*)encodedData,numEncodedDataBytes,&LastBitsInLastPacket, &CountOfBits);
|
|
}
|
|
catch(...)
|
|
{
|
|
System::Diagnostics::EventLog *entryLog = new System::Diagnostics::EventLog();
|
|
entryLog->WriteEntry(S"CleanStream Failed");
|
|
}
|
|
|
|
outBitsInLastPacket = (unsigned int)LastBitsInLastPacket;*/
|
|
|
|
audWaveMetadata encodedWaveMetadata;
|
|
|
|
//Convert metadata to platform endianness.
|
|
unsigned __int64 waveDataOffsetBytes = (unsigned __int64)waveSampleDataOffsetBytes;
|
|
encodedWaveMetadata.base.waveDataOffsetBytes = FlipEndian(waveDataOffsetBytes);
|
|
encodedWaveMetadata.base.lengthBytes = FlipEndian((unsigned int)numEncodedDataBytes);
|
|
encodedWaveMetadata.base.lengthSamples = FlipEndian(waveMetadataIn->lengthSamples);
|
|
encodedWaveMetadata.base.loopStartOffsetSamples = (int)FlipEndian((unsigned int)waveMetadataIn->
|
|
loopStartOffsetSamples);
|
|
encodedWaveMetadata.base.sampleRate = FlipEndian(waveMetadataIn->sampleRate);
|
|
encodedWaveMetadata.base.headroom = (short)FlipEndian((unsigned short)waveMetadataIn->headroom);
|
|
encodedWaveMetadata.base.flags = 0;
|
|
|
|
encodedWaveMetadata.platform.loopStartBits = FlipEndian((unsigned int)encodedDataFormat->XmaStreams[0].LoopStart);
|
|
encodedWaveMetadata.platform.loopEndBits = FlipEndian((unsigned int)encodedDataFormat->XmaStreams[0].LoopEnd);
|
|
encodedWaveMetadata.platform.loopSubframeData = encodedDataFormat->XmaStreams[0].SubframeData;
|
|
encodedWaveMetadata.platform.loopSubframeData = FlipEndian(encodedWaveMetadata.platform.loopSubframeData);
|
|
free(encodedDataFormat);
|
|
|
|
//Skip the first 8 bytes of the seek table - which appear to be header...
|
|
DWORD *trimmedSeekTable = seekTable + 2;
|
|
numSeekTableBytes -= 8;
|
|
//Convert seek table to platform endianness (as the XMA encoder doesn't.)
|
|
for(unsigned int i=0; i<numSeekTableBytes / sizeof(DWORD); i++)
|
|
{
|
|
trimmedSeekTable[i] = FlipEndian((unsigned int)trimmedSeekTable[i]);
|
|
}
|
|
|
|
unsigned __int64 seekTableOffsetBytes = (unsigned __int64)sizeof(audWaveMetadata);
|
|
encodedWaveMetadata.platform.seekTableOffsetBytes = FlipEndian(seekTableOffsetBytes);
|
|
encodedWaveMetadata.platform.seekTableLengthSamples = FlipEndian((unsigned int)(numSeekTableBytes / sizeof(DWORD)));
|
|
|
|
//Allocate output buffers and copy data.
|
|
|
|
waveSampleDataOutLengthBytes = numEncodedDataBytes;
|
|
*waveSampleDataOut = new unsigned char[waveSampleDataOutLengthBytes];
|
|
memcpy(*waveSampleDataOut, encodedData, waveSampleDataOutLengthBytes);
|
|
free(encodedData);
|
|
|
|
waveMetadataOutLengthBytes = sizeof(audWaveMetadata) + numSeekTableBytes;
|
|
*waveMetadataOut = new unsigned char[waveMetadataOutLengthBytes];
|
|
memcpy(*waveMetadataOut, &encodedWaveMetadata, sizeof(audWaveMetadata));
|
|
memcpy(((char *)(*waveMetadataOut)) + sizeof(audWaveMetadata), trimmedSeekTable, numSeekTableBytes);
|
|
free(seekTable);
|
|
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace audWaveEncoding
|
|
|
|
#pragma warning(pop) //Reenable the warnings
|