cloud-game/pkg/resampler/simple.go
2025-12-22 15:08:50 +03:00

62 lines
1.4 KiB
Go

package resampler
func Linear(dst, src []int16) {
nSrc, nDst := len(src), len(dst)
if nSrc < 2 || nDst < 2 {
return
}
srcPairs, dstPairs := nSrc>>1, nDst>>1
// replicate single pair input or output
if srcPairs == 1 || dstPairs == 1 {
for i := range dstPairs {
dst[i*2], dst[i*2+1] = src[0], src[1]
}
return
}
ratio := ((srcPairs - 1) << 16) / (dstPairs - 1)
lastSrc := nSrc - 2
// interpolate all pairs except the last
for i, pos := 0, 0; i < dstPairs-1; i, pos = i+1, pos+ratio {
idx := (pos >> 16) << 1
di := i << 1
frac := int32(pos & 0xFFFF)
l0, r0 := int32(src[idx]), int32(src[idx+1])
// L = L0 + (L1-L0)*frac
dst[di] = int16(l0 + ((int32(src[idx+2])-l0)*frac)>>16)
// R = R0 + (R1-R0)*frac
dst[di+1] = int16(r0 + ((int32(src[idx+3])-r0)*frac)>>16)
}
// last output pair = last input pair (avoids precision loss at the edge)
lastDst := (dstPairs - 1) << 1
dst[lastDst], dst[lastDst+1] = src[lastSrc], src[lastSrc+1]
}
func Nearest(dst, src []int16) {
nSrc, nDst := len(src), len(dst)
if nSrc < 2 || nDst < 2 {
return
}
srcPairs, dstPairs := nSrc>>1, nDst>>1
if srcPairs == 1 || dstPairs == 1 {
for i := range dstPairs {
dst[i*2], dst[i*2+1] = src[0], src[1]
}
return
}
ratio := (srcPairs << 16) / dstPairs
for i, pos := 0, 0; i < dstPairs; i, pos = i+1, pos+ratio {
si := (pos >> 16) << 1
di := i << 1
dst[di], dst[di+1] = src[si], src[si+1]
}
}