Move Silk Frame Reconstruction into dedicated method

More closely matches RFC
This commit is contained in:
Sean DuBois 2022-09-16 22:45:37 -04:00
parent 0112ac2b3e
commit c9124c5c4e
2 changed files with 39 additions and 12 deletions

View file

@ -1357,12 +1357,9 @@ func (d *Decoder) ltpSynthesis(signalType frameSignalType, eQ23 []int32, i int,
// after either
//
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9.2
func (d *Decoder) lpcSynthesis(out []float64, bandwidth Bandwidth, currentSubframe, dLPC int, aQ12, res, gainQ16 []float64) {
func (d *Decoder) lpcSynthesis(out []float64, bandwidth Bandwidth, n, currentSubframe, dLPC int, aQ12, res, gainQ16 []float64) {
finalLPCValuesIndex := 0
// let n be the number of samples in a subframe
n := d.samplesInSubframe(bandwidth)
// j be the index of the first sample in the residual corresponding to
// the current subframe.
j := 0
@ -1414,6 +1411,35 @@ func (d *Decoder) lpcSynthesis(out []float64, bandwidth Bandwidth, currentSubfra
}
}
// The remainder of the reconstruction process for the frame does not
// need to be bit-exact, as small errors should only introduce
// proportionally small distortions. Although the reference
// implementation only includes a fixed-point version of the remaining
// steps, this section describes them in terms of a floating-point
// version for simplicity. This produces a signal with a nominal range
// of -1.0 to 1.0.
//
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9
func (d *Decoder) silkFrameReconstruction(
signalType frameSignalType, bandwidth Bandwidth,
dLPC int,
eQ23 []int32,
LTPscaleQ14 float64,
wQ2 int16,
aQ12, gainQ16, out []float64,
) {
// let n be the number of samples in a subframe
n := d.samplesInSubframe(bandwidth)
for i := 0; i < subframeCount; i++ {
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9.1
res := d.ltpSynthesis(signalType, eQ23, subframeCount, LTPscaleQ14, bandwidth, wQ2)
//https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9.2
d.lpcSynthesis(out[n*i:], bandwidth, n, i, dLPC, aQ12, res, gainQ16)
}
}
// Decode decodes many SILK subframes
//
// An overview of the decoder is given in Figure 14.
@ -1518,13 +1544,14 @@ func (d *Decoder) Decode(in []byte, out []float64, isStereo bool, nanoseconds in
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.8.6
eQ23 := d.decodeExcitation(signalType, quantizationOffsetType, lcgSeed, pulsecounts, lsbcounts)
for i := 0; i < subframeCount; i++ {
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9.1
res := d.ltpSynthesis(signalType, eQ23, subframeCount, LTPscaleQ14, bandwidth, wQ2)
//https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9.2
d.lpcSynthesis(out[subframeSize*i:], bandwidth, i, dLPC, aQ12, res, gainQ16)
}
// https://www.rfc-editor.org/rfc/rfc6716.html#section-4.2.7.9
d.silkFrameReconstruction(signalType, bandwidth,
dLPC,
eQ23,
LTPscaleQ14,
wQ2,
aQ12, gainQ16, out,
)
// n0Q15 is the LSF coefficients decoded for the prior frame
// see normalizeLSFInterpolation.

View file

@ -382,7 +382,7 @@ func TestLPCSynthesis(t *testing.T) {
for i := range expectedOut {
out := make([]float64, 80)
d.lpcSynthesis(out, bandwidth, i, dLPC, aQ12, res, gainQ16)
d.lpcSynthesis(out, bandwidth, d.samplesInSubframe(BandwidthWideband), i, dLPC, aQ12, res, gainQ16)
for j := range out {
if out[j]-expectedOut[i][j] > floatEqualityThreshold {
t.Fatalf("run(%d) index(%d) (%f) != (%f)", i, j, out[j], expectedOut[i][j])