Files
GTASource/rage/base/tools/audio/audwaveencoder/waveencoder_xenon.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

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