Skip to content

Commit

Permalink
SOUND: Hide the implementation of WMA behind makeWMAStream
Browse files Browse the repository at this point in the history
  • Loading branch information
clone2727 authored and DrMcCoy committed Aug 18, 2018
1 parent 2892f90 commit b3c8687
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 228 deletions.
2 changes: 1 addition & 1 deletion src/sound/decoders/asf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ ASFStream::Packet *ASFStream::readPacket() {
PacketizedAudioStream *ASFStream::createAudioStream() {
switch (_compression) {
case kWaveWMAv2:
return new WMACodec(2, _sampleRate, _channels, _bitRate, _blockAlign, _extraData.get());
return makeWMAStream(2, _sampleRate, _channels, _bitRate, _blockAlign, *_extraData);
default:
throw Common::Exception("ASFStream::createAudioStream(): Unknown compression 0x%04x", _compression);
}
Expand Down
201 changes: 201 additions & 0 deletions src/sound/decoders/wma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
#include "src/common/mdct.h"
#include "src/common/bitstream.h"
#include "src/common/huffman.h"
#include "src/common/types.h"
#include "src/common/scopedptr.h"
#include "src/common/ptrvector.h"

#include "src/sound/audiostream.h"

Expand Down Expand Up @@ -94,6 +97,200 @@ static inline void vectorFMulReverse(float *dst, const float *src0,
*dst++ = *src0++ * *src1--;
}

struct WMACoefHuffmanParam;

class WMACodec : public PacketizedAudioStream {
public:
WMACodec(int version, uint32 sampleRate, uint8 channels,
uint32 bitRate, uint32 blockAlign, Common::SeekableReadStream *extraData = 0);
~WMACodec();

// AudioStream API
int getChannels() const { return _channels; }
int getRate() const { return _sampleRate; }
bool endOfData() const { return _audStream->endOfData(); }
bool endOfStream() const { return _audStream->endOfStream(); }
size_t readBuffer(int16 *buffer, const size_t numSamples) { return _audStream->readBuffer(buffer, numSamples); }

// PacketizedAudioStream API
void finish() { _audStream->finish(); }
bool isFinished() const { return _audStream->isFinished(); }
void queuePacket(Common::SeekableReadStream *data);

private:
static const int kChannelsMax = 2; ///< Max number of channels we support.

static const int kBlockBitsMin = 7; ///< Min number of bits in a block.
static const int kBlockBitsMax = 11; ///< Max number of bits in a block.

/** Max number of bytes in a block. */
static const int kBlockSizeMax = (1 << kBlockBitsMax);

static const int kBlockNBSizes = (kBlockBitsMax - kBlockBitsMin + 1);

/** Max size of a superframe. */
static const int kSuperframeSizeMax = 16384;

/** Max size of a high band. */
static const int kHighBandSizeMax = 16;

/** Size of the noise table. */
static const int kNoiseTabSize = 8192;

/** Number of bits for the LSP power value. */
static const int kLSPPowBits = 7;

int _version; ///< WMA version.

uint32 _sampleRate; ///< Output sample rate.
uint8 _channels; ///< Output channel count.
uint32 _bitRate; ///< Input bit rate.
uint32 _blockAlign; ///< Input block align.
byte _audioFlags; ///< Output flags.

bool _useExpHuffman; ///< Exponents in Huffman code? Otherwise, in LSP.
bool _useBitReservoir; ///< Is each frame packet a "superframe"?
bool _useVariableBlockLen; ///< Are the block lengths variable?
bool _useNoiseCoding; ///< Should perceptual noise be added?

bool _resetBlockLengths; ///< Do we need new block lengths?

int _curFrame; ///< The number of the frame we're currently in.
int _frameLen; ///< The frame length.
int _frameLenBits; ///< log2 of the frame length.
int _blockSizeCount; ///< Number of block sizes.
int _framePos; ///< The position within the frame we're currently in.

int _curBlock; ///< The number of the block we're currently in.
int _blockLen; ///< Current block length.
int _blockLenBits; ///< log2 of current block length.
int _nextBlockLenBits; ///< log2 of next block length.
int _prevBlockLenBits; ///< log2 of previous block length.

int _byteOffsetBits;

// Coefficients
int _coefsStart; ///< First coded coef.
int _coefsEnd[kBlockNBSizes]; ///< Max number of coded coefficients.
int _exponentSizes[kBlockNBSizes];
uint16 _exponentBands[kBlockNBSizes][25];
int _highBandStart[kBlockNBSizes]; ///< Index of first coef in high band.
int _exponentHighSizes[kBlockNBSizes];
int _exponentHighBands[kBlockNBSizes][kHighBandSizeMax];

Common::ScopedPtr<Common::Huffman> _coefHuffman[2]; ///< Coefficients Huffman codes.

const WMACoefHuffmanParam *_coefHuffmanParam[2]; ///< Params for coef Huffman codes.

Common::ScopedArray<uint16> _coefHuffmanRunTable[2]; ///< Run table for the coef Huffman.
Common::ScopedArray<float> _coefHuffmanLevelTable[2]; ///< Level table for the coef Huffman.
Common::ScopedArray<uint16> _coefHuffmanIntTable[2]; ///< Int table for the coef Huffman.

// Noise
float _noiseMult; ///< Noise multiplier.
float _noiseTable[kNoiseTabSize]; ///< Noise table.
int _noiseIndex;

Common::ScopedPtr<Common::Huffman> _hgainHuffman; ///< Perceptual noise Huffman code.

// Exponents
int _exponentsBSize[kChannelsMax];
float _exponents[kChannelsMax][kBlockSizeMax];
float _maxExponent[kChannelsMax];

Common::ScopedPtr<Common::Huffman> _expHuffman; ///< Exponents Huffman code.

// Coded values in high bands
bool _highBandCoded [kChannelsMax][kHighBandSizeMax];
int _highBandValues[kChannelsMax][kHighBandSizeMax];

// Coefficients
float _coefs1[kChannelsMax][kBlockSizeMax];
float _coefs [kChannelsMax][kBlockSizeMax];

// Line spectral pairs
float _lspCosTable[kBlockSizeMax];
float _lspPowETable[256];
float _lspPowMTable1[(1 << kLSPPowBits)];
float _lspPowMTable2[(1 << kLSPPowBits)];

// MDCT
Common::PtrVector<Common::MDCT> _mdct; ///< MDCT contexts.
std::vector<const float *> _mdctWindow; ///< MDCT window functions.

/** Overhang from the last superframe. */
byte _lastSuperframe[kSuperframeSizeMax + 4];
int _lastSuperframeLen; ///< Size of the overhang data.
int _lastBitoffset; ///< Bit position within the overhang.

// Output
float _output[kBlockSizeMax * 2];
float _frameOut[kChannelsMax][kBlockSizeMax * 2];

// Backing stream for PacketizedAudioStream
Common::ScopedPtr<QueuingAudioStream> _audStream;

// Init helpers

void init(Common::SeekableReadStream *extraData);

uint16 getFlags(Common::SeekableReadStream *extraData);
void evalFlags(uint16 flags, Common::SeekableReadStream *extraData);
int getFrameBitLength();
int getBlockSizeCount(uint16 flags);
uint32 getNormalizedSampleRate();
bool useNoiseCoding(float &highFreq, float &bps);
void evalMDCTScales(float highFreq);
void initNoise();
void initCoefHuffman(float bps);
void initMDCT();
void initExponents();

Common::Huffman *initCoefHuffman(Common::ScopedArray<uint16> &runTable,
Common::ScopedArray<float> &levelTable,
Common::ScopedArray<uint16> &intTable,
const WMACoefHuffmanParam &params);
void initLSPToCurve();

// Decoding

Common::SeekableReadStream *decodeSuperFrame(Common::SeekableReadStream &data);
bool decodeFrame(Common::BitStream &bits, int16 *outputData);
int decodeBlock(Common::BitStream &bits);
AudioStream *decodeFrame(Common::SeekableReadStream &data);

// Decoding helpers

bool evalBlockLength(Common::BitStream &bits);
bool decodeChannels(Common::BitStream &bits, int bSize, bool msStereo, bool *hasChannel);
bool calculateIMDCT(int bSize, bool msStereo, bool *hasChannel);

void calculateCoefCount(int *coefCount, int bSize) const;
bool decodeNoise(Common::BitStream &bits, int bSize, bool *hasChannel, int *coefCount);
bool decodeExponents(Common::BitStream &bits, int bSize, bool *hasChannel);
bool decodeSpectralCoef(Common::BitStream &bits, bool msStereo, bool *hasChannel,
int *coefCount, int coefBitCount);
float getNormalizedMDCTLength() const;
void calculateMDCTCoefficients(int bSize, bool *hasChannel,
int *coefCount, int totalGain, float mdctNorm);

bool decodeExpHuffman(Common::BitStream &bits, int ch);
bool decodeExpLSP(Common::BitStream &bits, int ch);
bool decodeRunLevel(Common::BitStream &bits, const Common::Huffman &huffman,
const float *levelTable, const uint16 *runTable, int version, float *ptr,
int offset, int numCoefs, int blockLen, int frameLenBits, int coefNbBits);

void lspToCurve(float *out, float *val_max_ptr, int n, float *lsp);

void window(float *out) const;

float pow_m1_4(float x) const;

static int readTotalGain(Common::BitStream &bits);
static int totalGainToBits(int totalGain);
static uint32 getLargeVal(Common::BitStream &bits);
};


WMACodec::WMACodec(int version, uint32 sampleRate, uint8 channels,
uint32 bitRate, uint32 blockAlign, Common::SeekableReadStream *extraData) :
Expand Down Expand Up @@ -1525,4 +1722,8 @@ void WMACodec::queuePacket(Common::SeekableReadStream *data) {
_audStream->queueAudioStream(stream);
}

PacketizedAudioStream *makeWMAStream(int version, uint32 sampleRate, uint8 channels, uint32 bitRate, uint32 blockAlign, Common::SeekableReadStream &extraData) {
return new WMACodec(version, sampleRate, channels, bitRate, blockAlign, &extraData);
}

} // End of namespace Sound

0 comments on commit b3c8687

Please sign in to comment.