36 lines
1.1 KiB
Go
36 lines
1.1 KiB
Go
// Package audio contains small, shared PCM16 transformations used by media and AI adapters.
|
|
package audio
|
|
|
|
import "encoding/binary"
|
|
|
|
// ResamplePCM16 linearly resamples mono signed little-endian PCM16.
|
|
// It preserves an empty input and returns a copy when the rates match.
|
|
func ResamplePCM16(src []byte, sourceRate, targetRate int) []byte {
|
|
if sourceRate <= 0 || targetRate <= 0 || len(src) < 2 || sourceRate == targetRate {
|
|
return append([]byte(nil), src...)
|
|
}
|
|
samples := len(src) / 2
|
|
outSamples := samples * targetRate / sourceRate
|
|
if outSamples < 1 {
|
|
return nil
|
|
}
|
|
out := make([]byte, outSamples*2)
|
|
for i := 0; i < outSamples; i++ {
|
|
position := float64(i) * float64(sourceRate) / float64(targetRate)
|
|
left := int(position)
|
|
if left >= samples {
|
|
left = samples - 1
|
|
}
|
|
right := left + 1
|
|
if right >= samples {
|
|
right = left
|
|
}
|
|
frac := position - float64(left)
|
|
lv := int16(binary.LittleEndian.Uint16(src[left*2 : left*2+2]))
|
|
rv := int16(binary.LittleEndian.Uint16(src[right*2 : right*2+2]))
|
|
value := int16(float64(lv)*(1-frac) + float64(rv)*frac)
|
|
binary.LittleEndian.PutUint16(out[i*2:i*2+2], uint16(value))
|
|
}
|
|
return out
|
|
}
|