Files
AsminVoicechat/source/decompiled/de/maxhenkel/voicechat/concentus/CeltEncoder.java
T
asminme bbccd4a815
Build AsminVoicechat / prepare-release (push) Successful in 14s
Build AsminVoicechat / build-and-test (17) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (18) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (19) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (20) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (21) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (22) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (23) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (24) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (25) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (26) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (27-ea) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (16) (push) Canceled after 38s
first commit
2026-10-24 15:18:03 +02:00

889 lines
36 KiB
Java

/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.concentus;
import de.maxhenkel.voicechat.concentus.AnalysisInfo;
import de.maxhenkel.voicechat.concentus.Arrays;
import de.maxhenkel.voicechat.concentus.Bands;
import de.maxhenkel.voicechat.concentus.BoxedValueInt;
import de.maxhenkel.voicechat.concentus.CeltCommon;
import de.maxhenkel.voicechat.concentus.CeltMode;
import de.maxhenkel.voicechat.concentus.CeltTables;
import de.maxhenkel.voicechat.concentus.EntropyCoder;
import de.maxhenkel.voicechat.concentus.Inlines;
import de.maxhenkel.voicechat.concentus.OpusError;
import de.maxhenkel.voicechat.concentus.OpusFramesize;
import de.maxhenkel.voicechat.concentus.Pitch;
import de.maxhenkel.voicechat.concentus.QuantizeBands;
import de.maxhenkel.voicechat.concentus.Rate;
class CeltEncoder {
CeltMode mode = null;
int channels = 0;
int stream_channels = 0;
int force_intra = 0;
int clip = 0;
int disable_pf = 0;
int complexity = 0;
int upsample = 0;
int start = 0;
int end = 0;
int bitrate = 0;
int vbr = 0;
int signalling = 0;
int constrained_vbr = 0;
int loss_rate = 0;
int lsb_depth = 0;
OpusFramesize variable_duration = OpusFramesize.OPUS_FRAMESIZE_UNKNOWN;
int lfe = 0;
int rng = 0;
int spread_decision = 0;
int delayedIntra = 0;
int tonal_average = 0;
int lastCodedBands = 0;
int hf_average = 0;
int tapset_decision = 0;
int prefilter_period = 0;
int prefilter_gain = 0;
int prefilter_tapset = 0;
int consec_transient = 0;
AnalysisInfo analysis = new AnalysisInfo();
final int[] preemph_memE = new int[2];
final int[] preemph_memD = new int[2];
int vbr_reservoir = 0;
int vbr_drift = 0;
int vbr_offset = 0;
int vbr_count = 0;
int overlap_max = 0;
int stereo_saving = 0;
int intensity = 0;
int[] energy_mask = null;
int spec_avg = 0;
int[][] in_mem = null;
int[][] prefilter_mem = null;
int[][] oldBandE = null;
int[][] oldLogE = null;
int[][] oldLogE2 = null;
CeltEncoder() {
}
private void Reset() {
this.mode = null;
this.channels = 0;
this.stream_channels = 0;
this.force_intra = 0;
this.clip = 0;
this.disable_pf = 0;
this.complexity = 0;
this.upsample = 0;
this.start = 0;
this.end = 0;
this.bitrate = 0;
this.vbr = 0;
this.signalling = 0;
this.constrained_vbr = 0;
this.loss_rate = 0;
this.lsb_depth = 0;
this.variable_duration = OpusFramesize.OPUS_FRAMESIZE_UNKNOWN;
this.lfe = 0;
this.PartialReset();
}
private void PartialReset() {
this.rng = 0;
this.spread_decision = 0;
this.delayedIntra = 0;
this.tonal_average = 0;
this.lastCodedBands = 0;
this.hf_average = 0;
this.tapset_decision = 0;
this.prefilter_period = 0;
this.prefilter_gain = 0;
this.prefilter_tapset = 0;
this.consec_transient = 0;
this.analysis.Reset();
this.preemph_memE[0] = 0;
this.preemph_memE[1] = 0;
this.preemph_memD[0] = 0;
this.preemph_memD[1] = 0;
this.vbr_reservoir = 0;
this.vbr_drift = 0;
this.vbr_offset = 0;
this.vbr_count = 0;
this.overlap_max = 0;
this.stereo_saving = 0;
this.intensity = 0;
this.energy_mask = null;
this.spec_avg = 0;
this.in_mem = null;
this.prefilter_mem = null;
this.oldBandE = null;
this.oldLogE = null;
this.oldLogE2 = null;
}
void ResetState() {
int i;
this.PartialReset();
this.in_mem = Arrays.InitTwoDimensionalArrayInt(this.channels, this.mode.overlap);
this.prefilter_mem = Arrays.InitTwoDimensionalArrayInt(this.channels, 1024);
this.oldBandE = Arrays.InitTwoDimensionalArrayInt(this.channels, this.mode.nbEBands);
this.oldLogE = Arrays.InitTwoDimensionalArrayInt(this.channels, this.mode.nbEBands);
this.oldLogE2 = Arrays.InitTwoDimensionalArrayInt(this.channels, this.mode.nbEBands);
for (i = 0; i < this.mode.nbEBands; ++i) {
this.oldLogE2[0][i] = -28672;
this.oldLogE[0][i] = -28672;
}
if (this.channels == 2) {
for (i = 0; i < this.mode.nbEBands; ++i) {
this.oldLogE2[1][i] = -28672;
this.oldLogE[1][i] = -28672;
}
}
this.vbr_offset = 0;
this.delayedIntra = 1;
this.spread_decision = 2;
this.tonal_average = 256;
this.hf_average = 0;
this.tapset_decision = 0;
}
int opus_custom_encoder_init_arch(CeltMode mode, int channels) {
if (channels < 0 || channels > 2) {
return OpusError.OPUS_BAD_ARG;
}
if (this == null || mode == null) {
return OpusError.OPUS_ALLOC_FAIL;
}
this.Reset();
this.mode = mode;
this.stream_channels = this.channels = channels;
this.upsample = 1;
this.start = 0;
this.end = this.mode.effEBands;
this.signalling = 1;
this.constrained_vbr = 1;
this.clip = 1;
this.bitrate = -1;
this.vbr = 0;
this.force_intra = 0;
this.complexity = 5;
this.lsb_depth = 24;
this.ResetState();
return OpusError.OPUS_OK;
}
int celt_encoder_init(int sampling_rate, int channels) {
int ret = this.opus_custom_encoder_init_arch(CeltMode.mode48000_960_120, channels);
if (ret != OpusError.OPUS_OK) {
return ret;
}
this.upsample = CeltCommon.resampling_factor(sampling_rate);
return OpusError.OPUS_OK;
}
int run_prefilter(int[][] input, int[][] prefilter_mem, int CC, int N, int prefilter_tapset, BoxedValueInt pitch, BoxedValueInt gain, BoxedValueInt qgain, int enabled, int nbAvailableBytes) {
int qg;
int pf_on;
int gain1;
int[][] pre = new int[CC][];
BoxedValueInt pitch_index = new BoxedValueInt(0);
CeltMode mode = this.mode;
int overlap = mode.overlap;
for (int z = 0; z < CC; ++z) {
pre[z] = new int[N + 1024];
}
int c = 0;
do {
System.arraycopy(prefilter_mem[c], 0, pre[c], 0, 1024);
System.arraycopy(input[c], overlap, pre[c], 1024, N);
} while (++c < CC);
if (enabled != 0) {
int[] pitch_buf = new int[1024 + N >> 1];
Pitch.pitch_downsample(pre, pitch_buf, 1024 + N, CC);
Pitch.pitch_search(pitch_buf, 512, pitch_buf, N, 979, pitch_index);
pitch_index.Val = 1024 - pitch_index.Val;
gain1 = Pitch.remove_doubling(pitch_buf, 1024, 15, N, pitch_index, this.prefilter_period, this.prefilter_gain);
if (pitch_index.Val > 1022) {
pitch_index.Val = 1022;
}
gain1 = Inlines.MULT16_16_Q15(22938, gain1);
if (this.loss_rate > 2) {
gain1 = Inlines.HALF32(gain1);
}
if (this.loss_rate > 4) {
gain1 = Inlines.HALF32(gain1);
}
if (this.loss_rate > 8) {
gain1 = 0;
}
} else {
gain1 = 0;
pitch_index.Val = 15;
}
int pf_threshold = 6554;
if (Inlines.abs(pitch_index.Val - this.prefilter_period) * 10 > pitch_index.Val) {
pf_threshold += 6554;
}
if (nbAvailableBytes < 25) {
pf_threshold += 3277;
}
if (nbAvailableBytes < 35) {
pf_threshold += 3277;
}
if (this.prefilter_gain > 13107) {
pf_threshold -= 3277;
}
if (this.prefilter_gain > 18022) {
pf_threshold -= 3277;
}
if (gain1 < (pf_threshold = Inlines.MAX16(pf_threshold, 6554))) {
gain1 = 0;
pf_on = 0;
qg = 0;
} else {
if (Inlines.ABS32(gain1 - this.prefilter_gain) < 3277) {
gain1 = this.prefilter_gain;
}
qg = (gain1 + 1536 >> 10) / 3 - 1;
qg = Inlines.IMAX(0, Inlines.IMIN(7, qg));
gain1 = 3072 * (qg + 1);
pf_on = 1;
}
c = 0;
do {
int offset = mode.shortMdctSize - overlap;
this.prefilter_period = Inlines.IMAX(this.prefilter_period, 15);
System.arraycopy(this.in_mem[c], 0, input[c], 0, overlap);
if (offset != 0) {
CeltCommon.comb_filter(input[c], overlap, pre[c], 1024, this.prefilter_period, this.prefilter_period, offset, -this.prefilter_gain, -this.prefilter_gain, this.prefilter_tapset, this.prefilter_tapset, null, 0);
}
CeltCommon.comb_filter(input[c], overlap + offset, pre[c], 1024 + offset, this.prefilter_period, pitch_index.Val, N - offset, -this.prefilter_gain, -gain1, this.prefilter_tapset, prefilter_tapset, mode.window, overlap);
System.arraycopy(input[c], N, this.in_mem[c], 0, overlap);
if (N > 1024) {
System.arraycopy(pre[c], N, prefilter_mem[c], 0, 1024);
continue;
}
Arrays.MemMove(prefilter_mem[c], N, 0, 1024 - N);
System.arraycopy(pre[c], 1024, prefilter_mem[c], 1024 - N, N);
} while (++c < CC);
gain.Val = gain1;
pitch.Val = pitch_index.Val;
qgain.Val = qg;
return pf_on;
}
int celt_encode_with_ec(short[] pcm, int pcm_ptr, int frame_size, byte[] compressed, int compressed_ptr, int nbCompressedBytes, EntropyCoder enc) {
int tf_sum;
int tf_select;
int i;
int vbr_bound;
int max_allowed;
int effectiveBytes;
int vbr_rate;
int nbFilledBytes;
int tell;
int LM;
int shortBlocks = 0;
int isTransient = 0;
int CC = this.channels;
int C = this.stream_channels;
int pitch_index = 15;
int gain1 = 0;
int dual_stereo = 0;
int prefilter_tapset = 0;
int anti_collapse_on = 0;
int silence = 0;
int tf_chan = 0;
int pitch_change = 0;
boolean transient_got_disabled = false;
int surround_masking = 0;
int temporal_vbr = 0;
int surround_trim = 0;
int equiv_rate = 510000;
CeltMode mode = this.mode;
int nbEBands = mode.nbEBands;
int overlap = mode.overlap;
short[] eBands = mode.eBands;
int start = this.start;
int end = this.end;
int tf_estimate = 0;
if (nbCompressedBytes < 2 || pcm == null) {
return OpusError.OPUS_BAD_ARG;
}
frame_size *= this.upsample;
for (LM = 0; LM <= mode.maxLM && mode.shortMdctSize << LM != frame_size; ++LM) {
}
if (LM > mode.maxLM) {
return OpusError.OPUS_BAD_ARG;
}
int M = 1 << LM;
int N = M * mode.shortMdctSize;
if (enc == null) {
tell = 1;
nbFilledBytes = 0;
} else {
tell = enc.tell();
nbFilledBytes = tell + 4 >> 3;
}
Inlines.OpusAssert(this.signalling == 0);
nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, 1275);
int nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
if (this.vbr != 0 && this.bitrate != -1) {
int den = mode.Fs >> 3;
vbr_rate = (this.bitrate * frame_size + (den >> 1)) / den;
effectiveBytes = vbr_rate >> 6;
} else {
vbr_rate = 0;
int tmp = this.bitrate * frame_size;
if (tell > 1) {
tmp += tell;
}
if (this.bitrate != -1) {
nbCompressedBytes = Inlines.IMAX(2, Inlines.IMIN(nbCompressedBytes, (tmp + 4 * mode.Fs) / (8 * mode.Fs) - (this.signalling != 0 ? 1 : 0)));
}
effectiveBytes = nbCompressedBytes;
}
if (this.bitrate != -1) {
equiv_rate = this.bitrate - (40 * C + 20) * ((400 >> LM) - 50);
}
if (enc == null) {
enc = new EntropyCoder();
enc.enc_init(compressed, compressed_ptr, nbCompressedBytes);
}
if (vbr_rate > 0 && this.constrained_vbr != 0 && (max_allowed = Inlines.IMIN(Inlines.IMAX(tell == 1 ? 2 : 0, vbr_rate + (vbr_bound = vbr_rate) - this.vbr_reservoir >> 6), nbAvailableBytes)) < nbAvailableBytes) {
nbCompressedBytes = nbFilledBytes + max_allowed;
nbAvailableBytes = max_allowed;
enc.enc_shrink(nbCompressedBytes);
}
int total_bits = nbCompressedBytes * 8;
int effEnd = end;
if (effEnd > mode.effEBands) {
effEnd = mode.effEBands;
}
int[][] input = Arrays.InitTwoDimensionalArrayInt(CC, N + overlap);
int sample_max = Inlines.MAX32(this.overlap_max, Inlines.celt_maxabs32(pcm, pcm_ptr, C * (N - overlap) / this.upsample));
this.overlap_max = Inlines.celt_maxabs32(pcm, pcm_ptr + C * (N - overlap) / this.upsample, C * overlap / this.upsample);
int n = silence = (sample_max = Inlines.MAX32(sample_max, this.overlap_max)) == 0 ? 1 : 0;
if (tell == 1) {
enc.enc_bit_logp(silence, 15);
} else {
silence = 0;
}
if (silence != 0) {
if (vbr_rate > 0) {
effectiveBytes = nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, nbFilledBytes + 2);
total_bits = nbCompressedBytes * 8;
nbAvailableBytes = 2;
enc.enc_shrink(nbCompressedBytes);
}
tell = nbCompressedBytes * 8;
enc.nbits_total += tell - enc.tell();
}
int c = 0;
BoxedValueInt boxed_memE = new BoxedValueInt(0);
do {
int need_clip = 0;
boxed_memE.Val = this.preemph_memE[c];
CeltCommon.celt_preemphasis(pcm, pcm_ptr + c, input[c], overlap, N, CC, this.upsample, mode.preemph, boxed_memE, need_clip);
this.preemph_memE[c] = boxed_memE.Val;
} while (++c < CC);
int enabled = (this.lfe != 0 && nbAvailableBytes > 3 || nbAvailableBytes > 12 * C) && start == 0 && silence == 0 && this.disable_pf == 0 && this.complexity >= 5 && (this.consec_transient == 0 || LM == 3 || this.variable_duration != OpusFramesize.OPUS_FRAMESIZE_VARIABLE) ? 1 : 0;
prefilter_tapset = this.tapset_decision;
BoxedValueInt boxed_pitch_index = new BoxedValueInt(0);
BoxedValueInt boxed_gain1 = new BoxedValueInt(0);
BoxedValueInt boxed_qg = new BoxedValueInt(0);
int pf_on = this.run_prefilter(input, this.prefilter_mem, CC, N, prefilter_tapset, boxed_pitch_index, boxed_gain1, boxed_qg, enabled, nbAvailableBytes);
pitch_index = boxed_pitch_index.Val;
gain1 = boxed_gain1.Val;
int qg = boxed_qg.Val;
if (!(gain1 <= 13107 && this.prefilter_gain <= 13107 || this.analysis.valid != 0 && !((double)this.analysis.tonality > 0.3) || !((double)pitch_index > 1.26 * (double)this.prefilter_period) && !((double)pitch_index < 0.79 * (double)this.prefilter_period))) {
pitch_change = 1;
}
if (pf_on == 0) {
if (start == 0 && tell + 16 <= total_bits) {
enc.enc_bit_logp(0, 1);
}
} else {
enc.enc_bit_logp(1, 1);
int octave = Inlines.EC_ILOG(++pitch_index) - 5;
enc.enc_uint(octave, 6L);
enc.enc_bits(pitch_index - (16 << octave), 4 + octave);
--pitch_index;
enc.enc_bits(qg, 3);
enc.enc_icdf(prefilter_tapset, CeltTables.tapset_icdf, 2);
}
isTransient = 0;
shortBlocks = 0;
if (this.complexity >= 1 && this.lfe == 0) {
BoxedValueInt boxed_tf_estimate = new BoxedValueInt(0);
BoxedValueInt boxed_tf_chan = new BoxedValueInt(0);
isTransient = CeltCommon.transient_analysis(input, N + overlap, CC, boxed_tf_estimate, boxed_tf_chan);
tf_estimate = boxed_tf_estimate.Val;
tf_chan = boxed_tf_chan.Val;
}
if (LM > 0 && enc.tell() + 3 <= total_bits) {
if (isTransient != 0) {
shortBlocks = M;
}
} else {
isTransient = 0;
transient_got_disabled = true;
}
int[][] freq = Arrays.InitTwoDimensionalArrayInt(CC, N);
int[][] bandE = Arrays.InitTwoDimensionalArrayInt(CC, nbEBands);
int[][] bandLogE = Arrays.InitTwoDimensionalArrayInt(CC, nbEBands);
boolean secondMdct = shortBlocks != 0 && this.complexity >= 8;
int[][] bandLogE2 = Arrays.InitTwoDimensionalArrayInt(CC, nbEBands);
if (secondMdct) {
CeltCommon.compute_mdcts(mode, 0, input, freq, C, CC, LM, this.upsample);
Bands.compute_band_energies(mode, freq, bandE, effEnd, C, LM);
QuantizeBands.amp2Log2(mode, effEnd, end, bandE, bandLogE2, C);
i = 0;
while (i < nbEBands) {
int[] nArray = bandLogE2[0];
int n2 = i++;
nArray[n2] = nArray[n2] + Inlines.HALF16(Inlines.SHL16(LM, 10));
}
if (C == 2) {
i = 0;
while (i < nbEBands) {
int[] nArray = bandLogE2[1];
int n3 = i++;
nArray[n3] = nArray[n3] + Inlines.HALF16(Inlines.SHL16(LM, 10));
}
}
}
CeltCommon.compute_mdcts(mode, shortBlocks, input, freq, C, CC, LM, this.upsample);
if (CC == 2 && C == 1) {
tf_chan = 0;
}
Bands.compute_band_energies(mode, freq, bandE, effEnd, C, LM);
if (this.lfe != 0) {
for (i = 2; i < end; ++i) {
bandE[0][i] = Inlines.IMIN(bandE[0][i], Inlines.MULT16_32_Q15((short)3, bandE[0][0]));
bandE[0][i] = Inlines.MAX32(bandE[0][i], 1);
}
}
QuantizeBands.amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
int[] surround_dynalloc = new int[C * nbEBands];
if (start == 0 && this.energy_mask != null && this.lfe == 0) {
int mask_avg = 0;
int diff = 0;
int count = 0;
int mask_end = Inlines.IMAX(2, this.lastCodedBands);
for (c = 0; c < C; ++c) {
for (i = 0; i < mask_end; ++i) {
int mask = Inlines.MAX16(Inlines.MIN16(this.energy_mask[nbEBands * c + i], 256), -2048);
if (mask > 0) {
mask = Inlines.HALF16(mask);
}
mask_avg += Inlines.MULT16_16(mask, eBands[i + 1] - eBands[i]);
count += eBands[i + 1] - eBands[i];
diff += Inlines.MULT16_16(mask, 1 + 2 * i - mask_end);
}
}
Inlines.OpusAssert(count > 0);
mask_avg = Inlines.DIV32_16(mask_avg, count);
mask_avg += 205;
diff = diff * 6 / (C * (mask_end - 1) * (mask_end + 1) * mask_end);
diff = Inlines.HALF32(diff);
diff = Inlines.MAX32(Inlines.MIN32(diff, 32), -32);
int midband = 0;
while (eBands[midband + 1] < eBands[mask_end] / 2) {
++midband;
}
int count_dynalloc = 0;
for (i = 0; i < mask_end; ++i) {
int lin = mask_avg + diff * (i - midband);
int unmask = C == 2 ? Inlines.MAX16(this.energy_mask[i], this.energy_mask[nbEBands + i]) : this.energy_mask[i];
unmask = Inlines.MIN16(unmask, 0);
if ((unmask -= lin) <= 256) continue;
surround_dynalloc[i] = unmask - 256;
++count_dynalloc;
}
if (count_dynalloc >= 3) {
if ((mask_avg += 256) > 0) {
mask_avg = 0;
diff = 0;
Arrays.MemSet(surround_dynalloc, 0, mask_end);
} else {
for (i = 0; i < mask_end; ++i) {
surround_dynalloc[i] = Inlines.MAX16(0, surround_dynalloc[i] - 256);
}
}
}
surround_trim = 64 * diff;
surround_masking = mask_avg += 205;
}
if (this.lfe == 0) {
int follow = -10240;
int frame_avg = 0;
int offset = shortBlocks != 0 ? Inlines.HALF16(Inlines.SHL16(LM, 10)) : 0;
for (i = start; i < end; ++i) {
follow = Inlines.MAX16(follow - 1024, bandLogE[0][i] - offset);
if (C == 2) {
follow = Inlines.MAX16(follow, bandLogE[1][i] - offset);
}
frame_avg += follow;
}
temporal_vbr = Inlines.SUB16(frame_avg /= end - start, this.spec_avg);
temporal_vbr = Inlines.MIN16(3072, Inlines.MAX16(-1536, temporal_vbr));
this.spec_avg += (short)Inlines.MULT16_16_Q15(655, temporal_vbr);
}
if (!secondMdct) {
System.arraycopy(bandLogE[0], 0, bandLogE2[0], 0, nbEBands);
if (C == 2) {
System.arraycopy(bandLogE[1], 0, bandLogE2[1], 0, nbEBands);
}
}
if (LM > 0 && enc.tell() + 3 <= total_bits && isTransient == 0 && this.complexity >= 5 && this.lfe == 0 && CeltCommon.patch_transient_decision(bandLogE, this.oldBandE, nbEBands, start, end, C) != 0) {
isTransient = 1;
shortBlocks = M;
CeltCommon.compute_mdcts(mode, shortBlocks, input, freq, C, CC, LM, this.upsample);
Bands.compute_band_energies(mode, freq, bandE, effEnd, C, LM);
QuantizeBands.amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
i = 0;
while (i < nbEBands) {
int[] nArray = bandLogE2[0];
int n4 = i++;
nArray[n4] = nArray[n4] + Inlines.HALF16(Inlines.SHL16(LM, 10));
}
if (C == 2) {
i = 0;
while (i < nbEBands) {
int[] nArray = bandLogE2[1];
int n5 = i++;
nArray[n5] = nArray[n5] + Inlines.HALF16(Inlines.SHL16(LM, 10));
}
}
tf_estimate = 3277;
}
if (LM > 0 && enc.tell() + 3 <= total_bits) {
enc.enc_bit_logp(isTransient, 3);
}
int[][] X = Arrays.InitTwoDimensionalArrayInt(C, N);
Bands.normalise_bands(mode, freq, X, bandE, effEnd, C, M);
int[] tf_res = new int[nbEBands];
if (effectiveBytes >= 15 * C && start == 0 && this.complexity >= 2 && this.lfe == 0) {
int lambda = effectiveBytes < 40 ? 12 : (effectiveBytes < 60 ? 6 : (effectiveBytes < 100 ? 4 : 3));
BoxedValueInt boxed_tf_sum = new BoxedValueInt(0);
tf_select = CeltCommon.tf_analysis(mode, effEnd, isTransient, tf_res, lambda *= 2, X, N, LM, boxed_tf_sum, tf_estimate, tf_chan);
tf_sum = boxed_tf_sum.Val;
for (i = effEnd; i < end; ++i) {
tf_res[i] = tf_res[effEnd - 1];
}
} else {
tf_sum = 0;
for (i = 0; i < end; ++i) {
tf_res[i] = isTransient;
}
tf_select = 0;
}
int[][] error = Arrays.InitTwoDimensionalArrayInt(C, nbEBands);
BoxedValueInt boxed_delayedintra = new BoxedValueInt(this.delayedIntra);
QuantizeBands.quant_coarse_energy(mode, start, end, effEnd, bandLogE, this.oldBandE, total_bits, error, enc, C, LM, nbAvailableBytes, this.force_intra, boxed_delayedintra, this.complexity >= 4 ? 1 : 0, this.loss_rate, this.lfe);
this.delayedIntra = boxed_delayedintra.Val;
CeltCommon.tf_encode(start, end, isTransient, tf_res, LM, tf_select, enc);
if (enc.tell() + 4 <= total_bits) {
if (this.lfe != 0) {
this.tapset_decision = 0;
this.spread_decision = 2;
} else if (shortBlocks != 0 || this.complexity < 3 || nbAvailableBytes < 10 * C || start != 0) {
this.spread_decision = this.complexity == 0 ? 0 : 2;
} else {
BoxedValueInt boxed_tonal_average = new BoxedValueInt(this.tonal_average);
BoxedValueInt boxed_tapset_decision = new BoxedValueInt(this.tapset_decision);
BoxedValueInt boxed_hf_average = new BoxedValueInt(this.hf_average);
this.spread_decision = Bands.spreading_decision(mode, X, boxed_tonal_average, this.spread_decision, boxed_hf_average, boxed_tapset_decision, pf_on != 0 && shortBlocks == 0 ? 1 : 0, effEnd, C, M);
this.tonal_average = boxed_tonal_average.Val;
this.tapset_decision = boxed_tapset_decision.Val;
this.hf_average = boxed_hf_average.Val;
}
enc.enc_icdf(this.spread_decision, CeltTables.spread_icdf, 5);
}
int[] offsets = new int[nbEBands];
BoxedValueInt boxed_tot_boost = new BoxedValueInt(0);
int maxDepth = CeltCommon.dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, this.lsb_depth, mode.logN, isTransient, this.vbr, this.constrained_vbr, eBands, LM, effectiveBytes, boxed_tot_boost, this.lfe, surround_dynalloc);
int tot_boost = boxed_tot_boost.Val;
if (this.lfe != 0) {
offsets[0] = Inlines.IMIN(8, effectiveBytes / 3);
}
int[] cap = new int[nbEBands];
CeltCommon.init_caps(mode, cap, LM, C);
int dynalloc_logp = 6;
total_bits <<= 3;
int total_boost = 0;
tell = enc.tell_frac();
for (i = start; i < end; ++i) {
int width = C * (eBands[i + 1] - eBands[i]) << LM;
int quanta = Inlines.IMIN(width << 3, Inlines.IMAX(48, width));
int dynalloc_loop_logp = dynalloc_logp;
int boost = 0;
int j = 0;
while (tell + (dynalloc_loop_logp << 3) < total_bits - total_boost && boost < cap[i]) {
int flag = j < offsets[i] ? 1 : 0;
enc.enc_bit_logp(flag, dynalloc_loop_logp);
tell = enc.tell_frac();
if (flag == 0) break;
boost += quanta;
total_boost += quanta;
dynalloc_loop_logp = 1;
++j;
}
if (j != 0) {
dynalloc_logp = Inlines.IMAX(2, dynalloc_logp - 1);
}
offsets[i] = boost;
}
if (C == 2) {
if (LM != 0) {
dual_stereo = CeltCommon.stereo_analysis(mode, X, LM);
}
this.intensity = Bands.hysteresis_decision(equiv_rate / 1000, CeltTables.intensity_thresholds, CeltTables.intensity_histeresis, 21, this.intensity);
this.intensity = Inlines.IMIN(end, Inlines.IMAX(start, this.intensity));
}
int alloc_trim = 5;
if (tell + 48 <= total_bits - total_boost) {
if (this.lfe != 0) {
alloc_trim = 5;
} else {
BoxedValueInt boxed_stereo_saving = new BoxedValueInt(this.stereo_saving);
alloc_trim = CeltCommon.alloc_trim_analysis(mode, X, bandLogE, end, LM, C, this.analysis, boxed_stereo_saving, tf_estimate, this.intensity, surround_trim);
this.stereo_saving = boxed_stereo_saving.Val;
}
enc.enc_icdf(alloc_trim, CeltTables.trim_icdf, 7);
tell = enc.tell_frac();
}
if (vbr_rate > 0) {
int alpha;
int lm_diff = mode.maxLM - LM;
nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, 1275 >> 3 - LM);
int base_target = vbr_rate - (40 * C + 20 << 3);
if (this.constrained_vbr != 0) {
base_target += this.vbr_offset >> lm_diff;
}
int target = CeltCommon.compute_vbr(mode, this.analysis, base_target, LM, equiv_rate, this.lastCodedBands, C, this.intensity, this.constrained_vbr, this.stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, this.variable_duration, this.lfe, this.energy_mask != null ? 1 : 0, surround_masking, temporal_vbr);
int min_allowed = (tell + total_boost + 64 - 1 >> 6) + 2 - nbFilledBytes;
nbAvailableBytes = (target += tell) + 32 >> 6;
nbAvailableBytes = Inlines.IMAX(min_allowed, nbAvailableBytes);
nbAvailableBytes = Inlines.IMIN(nbCompressedBytes, nbAvailableBytes + nbFilledBytes) - nbFilledBytes;
int delta = target - vbr_rate;
target = nbAvailableBytes << 6;
if (silence != 0) {
nbAvailableBytes = 2;
target = 128;
delta = 0;
}
if (this.vbr_count < 970) {
++this.vbr_count;
alpha = Inlines.celt_rcp(Inlines.SHL32(this.vbr_count + 20, 16));
} else {
alpha = 33;
}
if (this.constrained_vbr != 0) {
this.vbr_reservoir += target - vbr_rate;
}
if (this.constrained_vbr != 0) {
this.vbr_drift += Inlines.MULT16_32_Q15(alpha, delta * (1 << lm_diff) - this.vbr_offset - this.vbr_drift);
this.vbr_offset = -this.vbr_drift;
}
if (this.constrained_vbr != 0 && this.vbr_reservoir < 0) {
int adjust = -this.vbr_reservoir / 64;
nbAvailableBytes += silence != 0 ? 0 : adjust;
this.vbr_reservoir = 0;
}
nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, nbAvailableBytes + nbFilledBytes);
enc.enc_shrink(nbCompressedBytes);
}
int[] fine_quant = new int[nbEBands];
int[] pulses = new int[nbEBands];
int[] fine_priority = new int[nbEBands];
int bits = (nbCompressedBytes * 8 << 3) - enc.tell_frac() - 1;
int anti_collapse_rsv = isTransient != 0 && LM >= 2 && bits >= LM + 2 << 3 ? 8 : 0;
bits -= anti_collapse_rsv;
int signalBandwidth = end - 1;
if (this.analysis.enabled && this.analysis.valid != 0) {
int min_bandwidth = equiv_rate < 32000 * C ? 13 : (equiv_rate < 48000 * C ? 16 : (equiv_rate < 60000 * C ? 18 : (equiv_rate < 80000 * C ? 19 : 20)));
signalBandwidth = Inlines.IMAX(this.analysis.bandwidth, min_bandwidth);
}
if (this.lfe != 0) {
signalBandwidth = 1;
}
BoxedValueInt boxed_intensity = new BoxedValueInt(this.intensity);
BoxedValueInt boxed_balance = new BoxedValueInt(0);
BoxedValueInt boxed_dual_stereo = new BoxedValueInt(dual_stereo);
int codedBands = Rate.compute_allocation(mode, start, end, offsets, cap, alloc_trim, boxed_intensity, boxed_dual_stereo, bits, boxed_balance, pulses, fine_quant, fine_priority, C, LM, enc, 1, this.lastCodedBands, signalBandwidth);
this.intensity = boxed_intensity.Val;
int balance = boxed_balance.Val;
dual_stereo = boxed_dual_stereo.Val;
this.lastCodedBands = this.lastCodedBands != 0 ? Inlines.IMIN(this.lastCodedBands + 1, Inlines.IMAX(this.lastCodedBands - 1, codedBands)) : codedBands;
QuantizeBands.quant_fine_energy(mode, start, end, this.oldBandE, error, fine_quant, enc, C);
short[] collapse_masks = new short[C * nbEBands];
BoxedValueInt boxed_rng = new BoxedValueInt(this.rng);
Bands.quant_all_bands(1, mode, start, end, X[0], C == 2 ? X[1] : null, collapse_masks, bandE, pulses, shortBlocks, this.spread_decision, dual_stereo, this.intensity, tf_res, nbCompressedBytes * 64 - anti_collapse_rsv, balance, enc, LM, codedBands, boxed_rng);
this.rng = boxed_rng.Val;
if (anti_collapse_rsv > 0) {
anti_collapse_on = this.consec_transient < 2 ? 1 : 0;
enc.enc_bits(anti_collapse_on, 1);
}
QuantizeBands.quant_energy_finalise(mode, start, end, this.oldBandE, error, fine_quant, fine_priority, nbCompressedBytes * 8 - enc.tell(), enc, C);
if (silence != 0) {
for (i = 0; i < nbEBands; ++i) {
this.oldBandE[0][i] = -28672;
}
if (C == 2) {
for (i = 0; i < nbEBands; ++i) {
this.oldBandE[1][i] = -28672;
}
}
}
this.prefilter_period = pitch_index;
this.prefilter_gain = gain1;
this.prefilter_tapset = prefilter_tapset;
if (CC == 2 && C == 1) {
System.arraycopy(this.oldBandE[0], 0, this.oldBandE[1], 0, nbEBands);
}
if (isTransient == 0) {
System.arraycopy(this.oldLogE[0], 0, this.oldLogE2[0], 0, nbEBands);
System.arraycopy(this.oldBandE[0], 0, this.oldLogE[0], 0, nbEBands);
if (CC == 2) {
System.arraycopy(this.oldLogE[1], 0, this.oldLogE2[1], 0, nbEBands);
System.arraycopy(this.oldBandE[1], 0, this.oldLogE[1], 0, nbEBands);
}
} else {
for (i = 0; i < nbEBands; ++i) {
this.oldLogE[0][i] = Inlines.MIN16(this.oldLogE[0][i], this.oldBandE[0][i]);
}
if (CC == 2) {
for (i = 0; i < nbEBands; ++i) {
this.oldLogE[1][i] = Inlines.MIN16(this.oldLogE[1][i], this.oldBandE[1][i]);
}
}
}
c = 0;
do {
for (i = 0; i < start; ++i) {
this.oldBandE[c][i] = 0;
this.oldLogE2[c][i] = -28672;
this.oldLogE[c][i] = -28672;
}
for (i = end; i < nbEBands; ++i) {
this.oldBandE[c][i] = 0;
this.oldLogE2[c][i] = -28672;
this.oldLogE[c][i] = -28672;
}
} while (++c < CC);
this.consec_transient = isTransient != 0 || transient_got_disabled ? ++this.consec_transient : 0;
this.rng = (int)enc.rng;
enc.enc_done();
if (enc.get_error() != 0) {
return OpusError.OPUS_INTERNAL_ERROR;
}
return nbCompressedBytes;
}
void SetComplexity(int value) {
if (value < 0 || value > 10) {
throw new IllegalArgumentException("Complexity must be between 0 and 10 inclusive");
}
this.complexity = value;
}
void SetStartBand(int value) {
if (value < 0 || value >= this.mode.nbEBands) {
throw new IllegalArgumentException("Start band above max number of ebands (or negative)");
}
this.start = value;
}
void SetEndBand(int value) {
if (value < 1 || value > this.mode.nbEBands) {
throw new IllegalArgumentException("End band above max number of ebands (or less than 1)");
}
this.end = value;
}
void SetPacketLossPercent(int value) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException("Packet loss must be between 0 and 100");
}
this.loss_rate = value;
}
void SetPrediction(int value) {
if (value < 0 || value > 2) {
throw new IllegalArgumentException("CELT prediction mode must be 0, 1, or 2");
}
this.disable_pf = value <= 1 ? 1 : 0;
this.force_intra = value == 0 ? 1 : 0;
}
void SetVBRConstraint(boolean value) {
this.constrained_vbr = value ? 1 : 0;
}
void SetVBR(boolean value) {
this.vbr = value ? 1 : 0;
}
void SetBitrate(int value) {
if (value <= 500 && value != -1) {
throw new IllegalArgumentException("Bitrate out of range");
}
this.bitrate = value = Inlines.IMIN(value, 260000 * this.channels);
}
void SetChannels(int value) {
if (value < 1 || value > 2) {
throw new IllegalArgumentException("Channel count must be 1 or 2");
}
this.stream_channels = value;
}
void SetLSBDepth(int value) {
if (value < 8 || value > 24) {
throw new IllegalArgumentException("Bit depth must be between 8 and 24");
}
this.lsb_depth = value;
}
int GetLSBDepth() {
return this.lsb_depth;
}
void SetExpertFrameDuration(OpusFramesize value) {
this.variable_duration = value;
}
void SetSignalling(int value) {
this.signalling = value;
}
void SetAnalysis(AnalysisInfo value) {
if (value == null) {
throw new IllegalArgumentException("AnalysisInfo");
}
this.analysis.Assign(value);
}
CeltMode GetMode() {
return this.mode;
}
int GetFinalRange() {
return this.rng;
}
void SetLFE(int value) {
this.lfe = value;
}
void SetEnergyMask(int[] value) {
this.energy_mask = value;
}
}