您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

113 行
2.9KB

  1. package dsp
  2. // StatefulFIRReal is a real-valued FIR filter that preserves its delay line
  3. // between calls to Process(). This eliminates click/pop artifacts at frame
  4. // boundaries in streaming audio pipelines.
  5. type StatefulFIRReal struct {
  6. taps []float64
  7. delay []float64
  8. pos int // write position in circular delay buffer
  9. }
  10. // NewStatefulFIRReal creates a stateful FIR filter with the given taps.
  11. func NewStatefulFIRReal(taps []float64) *StatefulFIRReal {
  12. t := make([]float64, len(taps))
  13. copy(t, taps)
  14. return &StatefulFIRReal{
  15. taps: t,
  16. delay: make([]float64, len(taps)),
  17. }
  18. }
  19. // Process filters the input through the FIR with persistent state.
  20. // Allocates a new output slice. For zero-alloc hot paths, use ProcessInto.
  21. func (f *StatefulFIRReal) Process(x []float32) []float32 {
  22. out := make([]float32, len(x))
  23. f.ProcessInto(x, out)
  24. return out
  25. }
  26. // ProcessInto filters into a pre-allocated output buffer.
  27. func (f *StatefulFIRReal) ProcessInto(x []float32, out []float32) []float32 {
  28. if len(x) == 0 || len(f.taps) == 0 {
  29. return out[:0]
  30. }
  31. n := len(f.taps)
  32. for i := 0; i < len(x); i++ {
  33. copy(f.delay[1:], f.delay[:n-1])
  34. f.delay[0] = float64(x[i])
  35. var acc float64
  36. for k := 0; k < n; k++ {
  37. acc += f.delay[k] * f.taps[k]
  38. }
  39. out[i] = float32(acc)
  40. }
  41. return out[:len(x)]
  42. }
  43. // Reset clears the delay line.
  44. func (f *StatefulFIRReal) Reset() {
  45. for i := range f.delay {
  46. f.delay[i] = 0
  47. }
  48. }
  49. // StatefulFIRComplex is a complex-valued FIR filter with persistent state.
  50. type StatefulFIRComplex struct {
  51. taps []float64
  52. delayR []float64
  53. delayI []float64
  54. }
  55. // NewStatefulFIRComplex creates a stateful complex FIR filter.
  56. func NewStatefulFIRComplex(taps []float64) *StatefulFIRComplex {
  57. t := make([]float64, len(taps))
  58. copy(t, taps)
  59. return &StatefulFIRComplex{
  60. taps: t,
  61. delayR: make([]float64, len(taps)),
  62. delayI: make([]float64, len(taps)),
  63. }
  64. }
  65. // Process filters complex IQ through the FIR with persistent state.
  66. // Allocates a new output slice. For zero-alloc hot paths, use ProcessInto.
  67. func (f *StatefulFIRComplex) Process(iq []complex64) []complex64 {
  68. out := make([]complex64, len(iq))
  69. f.ProcessInto(iq, out)
  70. return out
  71. }
  72. // ProcessInto filters complex IQ into a pre-allocated output buffer.
  73. // out must be at least len(iq) long. Returns the used portion of out.
  74. func (f *StatefulFIRComplex) ProcessInto(iq []complex64, out []complex64) []complex64 {
  75. if len(iq) == 0 || len(f.taps) == 0 {
  76. return out[:0]
  77. }
  78. n := len(f.taps)
  79. for i := 0; i < len(iq); i++ {
  80. copy(f.delayR[1:], f.delayR[:n-1])
  81. copy(f.delayI[1:], f.delayI[:n-1])
  82. f.delayR[0] = float64(real(iq[i]))
  83. f.delayI[0] = float64(imag(iq[i]))
  84. var accR, accI float64
  85. for k := 0; k < n; k++ {
  86. w := f.taps[k]
  87. accR += f.delayR[k] * w
  88. accI += f.delayI[k] * w
  89. }
  90. out[i] = complex(float32(accR), float32(accI))
  91. }
  92. return out[:len(iq)]
  93. }
  94. // Reset clears the delay line.
  95. func (f *StatefulFIRComplex) Reset() {
  96. for i := range f.delayR {
  97. f.delayR[i] = 0
  98. f.delayI[i] = 0
  99. }
  100. }