mirror of
https://gitlab.com/ecodis/exhale.git
synced 2025-02-02 00:26:50 +01:00
finish 1.1.5 release
This commit is contained in:
parent
cc4151b9c7
commit
94a4ed9adf
@ -16,7 +16,7 @@ if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
|
||||
project(exhale VERSION 1.1.4 LANGUAGES CXX)
|
||||
project(exhale VERSION 1.1.5 LANGUAGES CXX)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE Release
|
||||
|
@ -33,7 +33,7 @@ exhale is being made available under an open-source license which is
|
||||
based on the 3-clause BSD license but modified to address particular
|
||||
aspects dictated by the nature and the output of this application.
|
||||
|
||||
The license text and release notes for the current version 1.1.4 can
|
||||
The license text and release notes for the current version 1.1.5 can
|
||||
be found in the `include` subdirectory of the exhale distribution.
|
||||
|
||||
|
||||
@ -115,9 +115,10 @@ the application directory (here, `./Input.wav` or `.\Input.wav`).
|
||||
After downloading from www.foobar2000.org and starting the software,
|
||||
load the desired input audio files into the playlist. Mark all files
|
||||
to be converted, rightclick on one of them, and select `Convert` ->
|
||||
`...`. In the newly opened window click on `Output format` and, once
|
||||
the window content changed, on `Add New`. Then select `Custom` under
|
||||
"Encoder" and enter the following information:
|
||||
`...`. In the newly opened window click on `Output format`. Once the
|
||||
window content changed, double-click on entry `AAC (exhale)` and set
|
||||
up the conversion. If that entry does not exist, click on `Add New`,
|
||||
select `Custom` under "Encoder" and enter the following information:
|
||||
|
||||
- *Encoder file:* exhale.exe (including path to the executable)
|
||||
- *Extension:* m4a
|
||||
|
@ -25,9 +25,15 @@
|
||||
<td valign="top">
|
||||
|
||||
<h1><br><span class="pink">exhale</span> - <span class="pink">e</span>codis e<span class="pink">x</span>tended <span class="pink">h</span>igh-efficiency <span class="pink">a</span>nd <span class="pink">l</span>ow-complexity <span class="pink">e</span>ncoder<br><span class="gray"><sup><br>Software Release Notes, Version History, Known Issues, Upcoming Feature Roadmap</sup></span><br><br></h1>
|
||||
<h3> The version of this distribution of the «exhale» software release is <b>1.1.4</b> (official pub­lic minor release) from March 2021. Please check <a href="http://www.ecodis.de/audio.htm#mpeg">www.ecodis.de</a> regularly for new versions of this software. A summary of each version up to this release, a list of known issues with this release, and a roadmap of additional functionality are provided below.</h3>
|
||||
<h3> The version of this distribution of the «exhale» software release is <b>1.1.5</b> (official pub­lic minor release) from April 2021. Please check <a href="http://www.ecodis.de/audio.htm#mpeg">www.ecodis.de</a> regularly for new versions of this software. A summary of each version up to this release, a list of known issues with this release, and a roadmap of additional functionality are provided below.</h3>
|
||||
<h3><br><b>Chronological Version History</b></h3>
|
||||
<h3> Version <b>1.1.4 <span class="gray"> Mar. 2021, this release</span></b></h3>
|
||||
<h3> Version <b>1.1.5 <span class="gray"> Apr. 2021, this release</span></b></h3>
|
||||
<ul>
|
||||
<li><h3>exhaleApp: correct print-out of Unicode file names and paths, minor code cleanup</h3></li>
|
||||
<li><h3>exhaleLib: minor tuning of immediate playout frames, no changes to audio quality</h3></li>
|
||||
<li><h3>makefile: support for compilation of Universal 2 binaries on MacOS™ (C. Snowhill)</h3></li>
|
||||
</ul>
|
||||
<h3> Version <b>1.1.4 <span class="gray"> Mar. 2021</span></b></h3>
|
||||
<ul>
|
||||
<li><h3>exhaleApp: removed LUFS/dBFS command arguments again, code now automatic</h3></li>
|
||||
<li><h3>exhaleApp: consider the working instead of application path if no path is specified</h3></li>
|
||||
@ -140,7 +146,7 @@
|
||||
<li><h3>exhaleLib: speed-ups and further quality tuning for difficult signals, as necessary.</h3></li>
|
||||
</ul>
|
||||
<h3><br></h3>
|
||||
<h4><span class="gray">Written by C. R. Helmrich for exhale 1.1.4, Mar. 2021. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
|
||||
<h4><span class="gray">Written by C. R. Helmrich for exhale 1.1.5, Apr. 2021. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
|
||||
|
||||
</td>
|
||||
<td valign="top" colspan="2">
|
||||
|
@ -15,5 +15,5 @@
|
||||
# define EXHALELIB_VERSION_MINOR "1"
|
||||
#endif
|
||||
#ifndef EXHALELIB_VERSION_BUGFIX
|
||||
# define EXHALELIB_VERSION_BUGFIX ".4" // "RC" or ".0", ".1", ...
|
||||
# define EXHALELIB_VERSION_BUGFIX ".5" // "RC" or ".0", ".1", ...
|
||||
#endif
|
||||
|
1
makefile
1
makefile
@ -1,5 +1,6 @@
|
||||
## makefile - master user make-file for compiling exhale on Linux and MacOS platforms
|
||||
# written by C. R. Helmrich, last modified in 2021 - see License.htm for legal notices
|
||||
# Universal 2 support for macOS added by Christopher Snowhill on hydrogenaud.io in 2021
|
||||
#
|
||||
# The copyright in this software is being made available under the exhale Copyright License
|
||||
# and comes with ABSOLUTELY NO WARRANTY. This software may be subject to other third-
|
||||
|
@ -112,7 +112,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
|
||||
{
|
||||
const unsigned numFramesFirstPeriod = __min (m_frameCount, m_rndAccPeriod);
|
||||
const unsigned numFramesFinalPeriod = (m_frameCount <= m_rndAccPeriod ? 0 : m_frameCount % m_rndAccPeriod);
|
||||
const unsigned numSamplesFinalFrame = (audioLength + m_pregapLength) % m_frameLength;
|
||||
const unsigned numSamplesFinalFrame = (audioLength + m_preLength + m_postLength) % m_frameLength;
|
||||
const uint32_t stszAtomSize = STSX_BSIZE + 4 /*bytes for sampleSize*/ + m_frameCount * 4;
|
||||
const uint32_t stscAtomSize = STSX_BSIZE + (numFramesFinalPeriod == 0 ? 12 : 24);
|
||||
const uint32_t stcoAtomSize = STSX_BSIZE + (uint32_t) m_rndAccOffsets.size () * 4;
|
||||
@ -165,12 +165,12 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
|
||||
header4Byte[164>>2] = trakAtomSize;
|
||||
header4Byte[200>>2] = numSamplesBE;
|
||||
header4Byte[300>>2] = mdiaAtomSize;
|
||||
header4Byte[332>>2] = toBigEndian (audioLength + m_pregapLength);
|
||||
header4Byte[332>>2] = toBigEndian (audioLength + m_preLength);
|
||||
header4Byte[376>>2] = minfAtomSize;
|
||||
header4Byte[288>>2] = numSamplesBE; // elst
|
||||
header4Byte[436>>2] = stblAtomSize;
|
||||
header4Byte[460>>2] = toBigEndian (m_frameCount - 1); // 2 entries used
|
||||
header4Byte[472>>2] = toBigEndian (numSamplesFinalFrame == 0 ? m_frameLength : numSamplesFinalFrame);
|
||||
header4Byte[472>>2] = toBigEndian ((numSamplesFinalFrame == 0 ? m_frameLength : __max (m_postLength + 1u, numSamplesFinalFrame)) - m_postLength);
|
||||
|
||||
m_staticHeader[558] = ((maxBitrate >> 24) & UCHAR_MAX);
|
||||
m_staticHeader[559] = ((maxBitrate >> 16) & UCHAR_MAX);
|
||||
@ -318,7 +318,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
|
||||
|
||||
int BasicMP4Writer::initHeader (const uint32_t audioLength, const unsigned extraDelay)
|
||||
{
|
||||
const unsigned frameCount = (audioLength + m_pregapLength - extraDelay + m_sampleRate / 200u + m_frameLength - 1u) / m_frameLength;
|
||||
const unsigned frameCount = (audioLength + m_preLength + m_postLength - extraDelay + m_frameLength - 1u) / m_frameLength;
|
||||
const unsigned chunkCount = ((frameCount + m_rndAccPeriod - 1) / m_rndAccPeriod);
|
||||
const unsigned numFramesFirstPeriod = __min (frameCount, m_rndAccPeriod);
|
||||
const unsigned numFramesFinalPeriod = (frameCount <= m_rndAccPeriod ? 0 : frameCount % m_rndAccPeriod);
|
||||
@ -337,6 +337,7 @@ int BasicMP4Writer::initHeader (const uint32_t audioLength, const unsigned extra
|
||||
bytesWritten += _WRITE (m_fileHandle, m_staticHeader, __min (i, STAT_HEADER_SIZE));
|
||||
}
|
||||
m_mediaOffset = bytesWritten; // first frame will be written at this offset
|
||||
m_postLength -= __min (m_postLength, extraDelay);
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
@ -427,7 +428,8 @@ void BasicMP4Writer::reset (const unsigned frameLength, const unsigned pregapLen
|
||||
m_frameLength = frameLength;
|
||||
m_mediaOffset = 0; // offset of first 'mdat' data byte serialized to file
|
||||
m_mediaSize = 0; // total length of 'mdat' (access unit) payload in file
|
||||
m_pregapLength = pregapLength;
|
||||
m_preLength = pregapLength;
|
||||
m_postLength = sampleRate / 200u;
|
||||
m_rndAccPeriod = raPeriod;
|
||||
m_sampleRate = sampleRate;
|
||||
m_dynamicHeader.clear ();
|
||||
|
@ -37,7 +37,8 @@ private:
|
||||
unsigned m_frameLength;
|
||||
uint32_t m_mediaOffset; // offset of first mdat payload
|
||||
uint32_t m_mediaSize; // number of bytes of mdat content
|
||||
unsigned m_pregapLength; // encoder look-ahead, pre-roll
|
||||
unsigned m_preLength; // encoding look-ahead, pre-roll
|
||||
unsigned m_postLength; // decoding look-ahead, post-roll
|
||||
unsigned m_rndAccPeriod; // random-access (RA) interval
|
||||
unsigned m_sampleRate;
|
||||
uint8_t m_staticHeader[STAT_HEADER_SIZE]; // fixed-size
|
||||
|
@ -742,7 +742,7 @@ int main (const int argc, char* argv[])
|
||||
#else
|
||||
const unsigned sampleRate = wavReader.getSampleRate ();
|
||||
#endif
|
||||
const unsigned indepPeriod = (sampleRate < 48000 ? (sampleRate - 320) / frameLength : 45 /*for 50-Hz video, use 50 for 60-Hz video*/);
|
||||
const unsigned indepPeriod = (sampleRate < 48000 ? sampleRate - 320u : 50u << 10u) / frameLength;
|
||||
const unsigned mod3Percent = unsigned ((expectLength * (3 + (coreSbrFrameLengthIndex & 3))) >> 17);
|
||||
uint32_t byteCount = 0, bw = (numChannels < 7 ? loudStats : 0);
|
||||
uint32_t br, bwMax = 0; // br will be used to hold bytes read and/or bit-rate
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
0 ICON "exhaleApp.ico"
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,4
|
||||
FILEVERSION 1,1,5
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
|
@ -80,6 +80,71 @@ static uint8_t getNumEnvBits (const int32_t int32Value, const uint8_t maxBitCoun
|
||||
return bits;
|
||||
}
|
||||
|
||||
#ifndef NO_PREROLL_DATA
|
||||
static unsigned getLowRatePreRollAU (uint8_t* const byteBuffer, const CoreCoderData& elData, EntropyCoder& entrCoder,
|
||||
const uint8_t* ipfAuState, const uint8_t sbrRatioShiftValue)
|
||||
{
|
||||
const uint16_t et = elData.elementType & 1;
|
||||
const bool notLFE = (elData.elementType < ID_USAC_LFE);
|
||||
const bool useSbr = (sbrRatioShiftValue > 0 && notLFE);
|
||||
unsigned byteCount;
|
||||
|
||||
if (ipfAuState[0] == 0) // create zero-spectrum AU
|
||||
{
|
||||
byteCount = (8 + et * 6) >> (useSbr ? 0 : 1);
|
||||
memcpy (byteBuffer, zeroAu[et], byteCount);
|
||||
|
||||
if (notLFE) // write appropriate window_sequence
|
||||
{
|
||||
const USAC_WSEQ wsPrev0 = elData.icsInfoPrev[0].windowSequence;
|
||||
const uint8_t wsPreRoll = uint8_t (wsPrev0 == EIGHT_SHORT || wsPrev0 == STOP_START ? LONG_START : wsPrev0);
|
||||
// SCE/CPE: window_sequence @ offset 2/0, left-shifted by 2/0
|
||||
byteBuffer[2 - 2 * et] |= wsPreRoll << (2 - 2 * et);
|
||||
}
|
||||
}
|
||||
else // complete AU with only 1 non-zero MDCT line
|
||||
{
|
||||
OutputStream au;
|
||||
unsigned ci = 0;
|
||||
|
||||
byteCount = ((unsigned) ipfAuState[0] << 1) | (ipfAuState[1] >> 7);
|
||||
while (ci < byteCount) au.write (byteBuffer[ci++], 8);
|
||||
au.heldBitCount = ipfAuState[1] & SCHAR_MAX;
|
||||
au.heldBitChunk = ipfAuState[2];
|
||||
|
||||
if (ipfAuState[3] > 0)
|
||||
{
|
||||
const uint16_t li = ipfAuState[4]; // line idx
|
||||
const uint16_t lg = __min (li + 56, (uint16_t) ipfAuState[3] << 2);
|
||||
|
||||
memset (byteBuffer, 0, lg); // MDCT line coder
|
||||
byteBuffer[li] = ipfAuState[5] >> 1;
|
||||
entrCoder.initWindowCoding (true);
|
||||
entrCoder.arithCodeSigMagn (byteBuffer, 0, lg, true, &au);
|
||||
if (byteBuffer[li]) au.write (ipfAuState[5] & 1, 1); // sign
|
||||
}
|
||||
au.write (0, 1);// fac_data_present, no fac_data
|
||||
|
||||
if (useSbr) // UsacSbrData()
|
||||
{
|
||||
au.write (1, 7);// SbrInfo(), sbrUseDfltHeader
|
||||
if (et) au.write (1, 1); // sbr_data(), couple
|
||||
au.write (0, 7);
|
||||
au.write (0, et ? 31 : 17);
|
||||
#if ENABLE_INTERTES
|
||||
au.write (0, et + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (au.heldBitCount > 0) au.stream.push_back (au.heldBitChunk);
|
||||
byteCount = (unsigned) au.stream.size ();
|
||||
memcpy (byteBuffer, &au.stream.front (), byteCount);
|
||||
}
|
||||
|
||||
return byteCount;
|
||||
}
|
||||
#endif // !NO_PREROLL_DATA
|
||||
|
||||
static uint8_t getOptMsMaskModeValue (const uint8_t* const msUsed, const unsigned numWinGroups, const unsigned numSwbShort,
|
||||
const uint8_t msMaskMode, const unsigned maxSfbSte)
|
||||
{
|
||||
@ -176,8 +241,8 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC
|
||||
}
|
||||
|
||||
// sbr_invf(), assumes dflt_noise_bands < 3, i.e. 1-2 noise bands
|
||||
i = 6 * nb - 9;
|
||||
m_auBitStream.write (ch0 & i, nb); // 3 or 15-bit bs_invf_mode[0]
|
||||
i = (1 << nb) - 1;
|
||||
m_auBitStream.write (ch0 & i, nb); // 2- or 4-bit bs_invf_mode[0]
|
||||
if (stereo && !couple) m_auBitStream.write (ch1 & i, nb);
|
||||
|
||||
// sbr_envelope() for mono/left channel, assumes bs_df_env[] == 0
|
||||
@ -360,7 +425,7 @@ unsigned BitStreamWriter::writeChannelWiseTnsData (const TnsData& tnsData, const
|
||||
unsigned BitStreamWriter::writeFDChannelStream (const CoreCoderData& elData, EntropyCoder& entrCoder, const unsigned ch,
|
||||
const int32_t* const mdctSignal, const uint8_t* const mdctQuantMag,
|
||||
#if !RESTRICT_TO_AAC
|
||||
const bool timeWarping, const bool noiseFilling,
|
||||
const bool timeWarping, const bool noiseFilling, uint8_t* ipfAuState,
|
||||
#endif
|
||||
const bool indepFlag /*= false*/)
|
||||
{
|
||||
@ -444,6 +509,9 @@ unsigned BitStreamWriter::writeFDChannelStream (const CoreCoderData& elData, Ent
|
||||
entrCoder.initWindowCoding (!eightShorts /*reset*/, eightShorts);
|
||||
|
||||
if (!indepFlag) m_auBitStream.write (1, 1); // force reset
|
||||
#ifndef NO_PREROLL_DATA
|
||||
if (ipfAuState) memset (ipfAuState, 0, 4); // no spectrum
|
||||
#endif
|
||||
}
|
||||
else // not zeroed, nasty since SFB ungrouping may be needed
|
||||
{
|
||||
@ -491,6 +559,39 @@ unsigned BitStreamWriter::writeFDChannelStream (const CoreCoderData& elData, Ent
|
||||
}
|
||||
m_auBitStream.write (b, 1); // write adapted reset bit
|
||||
}
|
||||
#ifndef NO_PREROLL_DATA
|
||||
if (ipfAuState && (w == 0))
|
||||
{
|
||||
b = (unsigned) m_auBitStream.stream.size ();
|
||||
|
||||
if (eightShorts || (b > 511) || !indepFlag)
|
||||
{
|
||||
memset (ipfAuState, 0, 4); // grouped or no residual
|
||||
}
|
||||
else
|
||||
{
|
||||
const int32_t* const winSig = &mdctSignal[grpOff[0]];
|
||||
int32_t sigPk = 0;
|
||||
|
||||
ipfAuState[0] = uint8_t (b >> 1);
|
||||
ipfAuState[1] = uint8_t ((b & 1) << 7) | m_auBitStream.heldBitCount;
|
||||
ipfAuState[2] = m_auBitStream.heldBitChunk;
|
||||
ipfAuState[3] = CLIP_UCHAR (lg >> 2);
|
||||
|
||||
for (b = i = 0; i < __min (256u, lg); i++)
|
||||
{
|
||||
if ((winMag[i] != 0) && (abs (winSig[i]) > sigPk))
|
||||
{
|
||||
sigPk = abs (winSig[i]);
|
||||
b = i;
|
||||
}
|
||||
}
|
||||
ipfAuState[4] = (uint8_t) b;
|
||||
ipfAuState[5] = winMag[b] << 1;
|
||||
if (winSig[b] > 0) ipfAuState[5] |= 1; // store sign of single peak
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bitCount += entrCoder.arithCodeSigMagn (winMag, 0, lg, true, &m_auBitStream);
|
||||
|
||||
if (eightShorts && (grpLen > 1))
|
||||
@ -800,7 +901,7 @@ unsigned BitStreamWriter::createAudioConfig (const char samplingFrequencyIndex,
|
||||
const unsigned methodValueBits = (methodDefinition == 7 ? 5 : (methodDefinition == 8 ? 2 : 8));
|
||||
|
||||
m_auBitStream.write (0, 2); // numConfigExtensions
|
||||
m_auBitStream.write (ID_EXT_LOUDNESS_INFO, 4);
|
||||
m_auBitStream.write (2, 4); // ..EXT_LOUDNESS_INFO
|
||||
m_auBitStream.write (methodValueBits < 3 ? 7 : 8, 4); // usacConfigExtLength
|
||||
|
||||
m_auBitStream.write (1, 12);// loudnessInfoCount=1
|
||||
@ -838,10 +939,13 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
const uint32_t frameCount, const uint32_t indepPeriod,
|
||||
#endif
|
||||
const uint8_t sbrRatioShiftValue, int32_t** const sbrInfoAndData,
|
||||
unsigned char* const accessUnit, const unsigned nSamplesInFrame /*= 1024*/)
|
||||
unsigned char* const accessUnit, const unsigned nSamplesInFrame)
|
||||
{
|
||||
#ifndef NO_PREROLL_DATA
|
||||
const uint8_t ipf = (frameCount == 1 ? 2 : ((frameCount % (indepPeriod << 1)) == 1 ? 1 : 0));
|
||||
#endif
|
||||
#if !RESTRICT_TO_AAC
|
||||
uint8_t* ipfState = (frameCount > 0 && (frameCount % (indepPeriod << 1)) == 0 && numElements == 1 ? m_usacIpfState : nullptr);
|
||||
#endif
|
||||
unsigned bitCount = 1, ci = 0;
|
||||
|
||||
@ -858,9 +962,11 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
return 0; // invalid arguments error
|
||||
}
|
||||
#ifndef NO_PREROLL_DATA
|
||||
if ((ipf == 2) || (ipf == 1 && (numElements > 1 || !noiseFilling[0])))
|
||||
if (ipf)
|
||||
{
|
||||
bitCount = __min (nSamplesInFrame << 2, (uint32_t) m_auBitStream.stream.size ());
|
||||
bitCount = ((ipf == 2) || (ipf == 1 && (numElements > 1 || !noiseFilling[0]))
|
||||
? __min (nSamplesInFrame << 2, (unsigned) m_auBitStream.stream.size ())
|
||||
: ((unsigned) m_usacIpfState[0] << 1) | (m_usacIpfState[1] >> 7));
|
||||
memcpy (tempBuffer, &m_auBitStream.stream.front (), bitCount); // prev fr AU
|
||||
}
|
||||
#endif
|
||||
@ -874,11 +980,10 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
m_auBitStream.write (ipf ? 1 : 0, 1); // UsacExtElement, usacExtElementPresent
|
||||
if (ipf)
|
||||
{
|
||||
const uint16_t idxPreRollExt = elementData[0]->elementType & 1;
|
||||
const bool lowRatePreRollExt = (ipf == 1 && numElements == 1 && noiseFilling[0]);
|
||||
const unsigned extraLength = (m_usacConfigLen > 14 ? 4 : 3) + m_usacConfigLen;
|
||||
const unsigned payloadLength = (lowRatePreRollExt ? (8 + idxPreRollExt * 6) >> (sbrRatioShiftValue > 0 ? 0 : 1) : bitCount) + extraLength; // in bytes
|
||||
|
||||
const unsigned payloadLength = (lowRatePreRollExt ? getLowRatePreRollAU (tempBuffer, *elementData[0], entropyCoder[0],
|
||||
m_usacIpfState, sbrRatioShiftValue) : bitCount) + extraLength; // in bytes
|
||||
m_auBitStream.write (0, 1); // usacExtElementUseDefaultLength = 0 (variable)
|
||||
m_auBitStream.write (CLIP_UCHAR (payloadLength), 8);
|
||||
if (payloadLength > 254) m_auBitStream.write (payloadLength - 253, 16);
|
||||
@ -895,18 +1000,7 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
m_auBitStream.write (1, 2); // numPreRollFrames, only one supported for now!
|
||||
m_auBitStream.write (payloadLength - extraLength, 16); // auLen
|
||||
|
||||
if (lowRatePreRollExt)
|
||||
{
|
||||
bitCount = payloadLength - extraLength;
|
||||
memcpy (tempBuffer, zeroAu[idxPreRollExt], bitCount);
|
||||
if (elementData[0]->elementType < ID_USAC_LFE) // correct window_sequence
|
||||
{
|
||||
const USAC_WSEQ wsPrev0 = elementData[0]->icsInfoPrev[0].windowSequence;
|
||||
const uint8_t wsPreRoll = uint8_t (wsPrev0 == EIGHT_SHORT || wsPrev0 == STOP_START ? LONG_START : wsPrev0);
|
||||
// SCE/CPE: window_sequence at byte index 2/0, left-shifted by value 2/0
|
||||
tempBuffer[2 - 2 * idxPreRollExt] |= wsPreRoll << (2 - 2 * idxPreRollExt);
|
||||
}
|
||||
}
|
||||
if (lowRatePreRollExt) bitCount = payloadLength - extraLength;
|
||||
while (ci < bitCount) m_auBitStream.write (tempBuffer[ci++], 8); // write AU
|
||||
ci = 0;
|
||||
if (m_usacConfigLen > 14) m_auBitStream.write (0, 4); // pad end of ext data
|
||||
@ -933,7 +1027,7 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
bitCount += writeFDChannelStream (*elData, entropyCoder[ci], 0,
|
||||
mdctSignals[ci], mdctQuantMag[ci],
|
||||
#if !RESTRICT_TO_AAC
|
||||
tw_mdct[el], noiseFilling[el],
|
||||
tw_mdct[el], noiseFilling[el], ipfState,
|
||||
#endif
|
||||
usacIndependencyFlag);
|
||||
if (sbrRatioShiftValue > 0) // UsacSbrData()
|
||||
@ -968,14 +1062,14 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
bitCount += writeFDChannelStream (*elData, entropyCoder[ci], 0, // L
|
||||
mdctSignals[ci], mdctQuantMag[ci],
|
||||
#if !RESTRICT_TO_AAC
|
||||
tw_mdct[el], noiseFilling[el],
|
||||
tw_mdct[el], noiseFilling[el], nullptr,
|
||||
#endif
|
||||
usacIndependencyFlag);
|
||||
ci++;
|
||||
bitCount += writeFDChannelStream (*elData, entropyCoder[ci], 1, // R
|
||||
mdctSignals[ci], mdctQuantMag[ci],
|
||||
#if !RESTRICT_TO_AAC
|
||||
tw_mdct[el], noiseFilling[el],
|
||||
tw_mdct[el], noiseFilling[el], ipfState,
|
||||
#endif
|
||||
usacIndependencyFlag);
|
||||
if (sbrRatioShiftValue > 0) // UsacSbrData()
|
||||
@ -1002,7 +1096,7 @@ unsigned BitStreamWriter::createAudioFrame (CoreCoderData** const elementData,
|
||||
bitCount += writeFDChannelStream (*elData, entropyCoder[ci], 0,
|
||||
mdctSignals[ci], mdctQuantMag[ci],
|
||||
#if !RESTRICT_TO_AAC
|
||||
false, false,
|
||||
false, false, ipfState,
|
||||
#endif
|
||||
usacIndependencyFlag);
|
||||
ci++;
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
// constants, experimental macros
|
||||
#define CORE_MODE_FD 0
|
||||
#define ID_EXT_ELE_FILL 0
|
||||
#define ID_EXT_LOUDNESS_INFO 2
|
||||
#define SFB_PER_PRED_BAND 2
|
||||
|
||||
// output bit-stream writer class
|
||||
@ -27,12 +25,15 @@ private:
|
||||
|
||||
// member variables
|
||||
OutputStream m_auBitStream; // access unit bit-stream to write
|
||||
uint32_t m_frameLength; // number of samples in full frame
|
||||
uint32_t m_frameLength;
|
||||
uint8_t m_numSwbShort; // max. SFB count in short windows
|
||||
uint8_t* m_uCharBuffer; // temporary buffer for ungrouping
|
||||
#ifndef NO_PREROLL_DATA
|
||||
uint8_t m_usacConfig[20]; // buffer for UsacConfig in IPF
|
||||
uint16_t m_usacConfigLen;
|
||||
#endif
|
||||
#if !RESTRICT_TO_AAC
|
||||
uint8_t m_usacIpfState[6];
|
||||
#endif
|
||||
// helper functions
|
||||
void writeByteAlignment (); // write 0s for byte alignment
|
||||
@ -43,7 +44,7 @@ private:
|
||||
unsigned writeFDChannelStream (const CoreCoderData& elData, EntropyCoder& entrCoder, const unsigned ch,
|
||||
const int32_t* const mdctSignal, const uint8_t* const mdctQuantMag,
|
||||
#if !RESTRICT_TO_AAC
|
||||
const bool timeWarping, const bool noiseFilling,
|
||||
const bool timeWarping, const bool noiseFilling, uint8_t* ipfAuState,
|
||||
#endif
|
||||
const bool indepFlag = false);
|
||||
unsigned writeStereoCoreToolInfo (const CoreCoderData& elData, EntropyCoder& entrCoder,
|
||||
@ -55,9 +56,9 @@ private:
|
||||
public:
|
||||
|
||||
// constructor
|
||||
BitStreamWriter () { m_auBitStream.reset (); m_frameLength = 0; m_numSwbShort = 0; m_uCharBuffer = nullptr;
|
||||
BitStreamWriter () { m_auBitStream.reset (); m_frameLength = 0; m_numSwbShort = 0; m_uCharBuffer = nullptr;
|
||||
#ifndef NO_PREROLL_DATA
|
||||
memset (m_usacConfig, 0, 20); m_usacConfigLen = 0;
|
||||
memset (m_usacConfig, 0, 20); m_usacConfigLen = 0; memset (m_usacIpfState, 0, 4);
|
||||
#endif
|
||||
}
|
||||
// destructor
|
||||
@ -79,7 +80,7 @@ public:
|
||||
const uint32_t frameCount, const uint32_t indepPeriod,
|
||||
#endif
|
||||
const uint8_t sbrRatioShiftValue, int32_t** const sbrInfoAndData,
|
||||
unsigned char* const accessUnit, const unsigned nSamplesInFrame = 1024);
|
||||
unsigned char* const accessUnit, const unsigned nSamplesInFrame);
|
||||
}; // BitStreamWriter
|
||||
|
||||
#endif // _BIT_STREAM_WRITER_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user