github.com/noriah/catnip@v1.8.5/dsp/window/window.go (about)

     1  // Package window provides Window Functions for singnal analysis
     2  //
     3  // See https://wikipedia.org/wiki/Window_function
     4  package window
     5  
     6  import "math"
     7  
     8  // Function is a function that will do window things for you on a slice
     9  type Function func(buf []float64)
    10  
    11  // Rectangle is just do nothing
    12  func Rectangle() Function {
    13  	return func(buf []float64) {
    14  		// do nothing
    15  	}
    16  }
    17  
    18  // CosSum modifies the buffer to conform to a cosine sum window following a0
    19  func CosSum(a0 float64) Function {
    20  	return func(buf []float64) {
    21  		size := len(buf)
    22  		a1 := 1.0 - a0
    23  		coef := 2.0 * math.Pi / float64(size)
    24  		for n := 0; n < size; n++ {
    25  			buf[n] *= (a0 - (a1 * math.Cos(coef*float64(n))))
    26  		}
    27  	}
    28  }
    29  
    30  // sinc(x) = sin(pi * x) / (pi * x)
    31  func sinc(x float64) float64 {
    32  	if x == 0.0 {
    33  		return 0.0
    34  	}
    35  	piX := math.Pi * x
    36  	return math.Sin(piX) / piX
    37  }
    38  
    39  // Lanczos modifies the buffer to a Lanczos window
    40  //
    41  // w[n] = sinc((2n / N) - 1)
    42  //
    43  // N = size
    44  // n = element
    45  // k = 2 / N
    46  //
    47  // buf[n] = sinc(kn - 1)
    48  //
    49  // https://www.wikiwand.com/en/Window_function#/Other_windows
    50  func Lanczos() Function {
    51  	return func(buf []float64) {
    52  		k := 2.0 / float64(len(buf))
    53  		for n := range buf {
    54  			buf[n] *= sinc((k * float64(n)) - 1.0)
    55  		}
    56  	}
    57  }
    58  
    59  // HammingConst is the hamming window constant
    60  const HammingConst = 25.0 / 46.0
    61  
    62  // Hamming modifies the buffer to a Hamming window
    63  func Hamming() Function {
    64  	return CosSum(HammingConst)
    65  }
    66  
    67  // Hann modifies the buffer to a Hann window
    68  func Hann() Function {
    69  	return CosSum(0.5)
    70  }
    71  
    72  // Bartlett modifies the buffer to a Bartlett window
    73  func Bartlett() Function {
    74  	return func(buf []float64) {
    75  		N := float64(len(buf))
    76  		for n := range buf {
    77  			buf[n] *= (1.0 - (math.Abs(((2.0 * float64(n)) - N) / N)))
    78  		}
    79  	}
    80  }
    81  
    82  // Blackman modifies the buffer to a Blackman window
    83  //
    84  // N = size
    85  // n = element
    86  // a = 0.16
    87  // a_0 = (1 - a) / 2
    88  // a_1 = 1 / 2
    89  // a_2 = a / 2
    90  // w[n] = a_0 - a_1 * cos((2 * pi * n) / N) + a_2 * cos((4 * pi * n) / N)
    91  func Blackman() Function {
    92  	return func(buf []float64) {
    93  		N := float64(len(buf))
    94  		twoPi := 2.0 * math.Pi
    95  
    96  		for n := range buf {
    97  			twoPiX := twoPi * (float64(n) / N)
    98  			buf[n] *= 0.42 - (0.5 * math.Cos(twoPiX)) + (0.08 * math.Cos(2.0*twoPiX))
    99  		}
   100  	}
   101  }
   102  
   103  // PlanckTaper modifies the buffer to a Planck-taper window
   104  //
   105  // not sure how i got this
   106  func PlanckTaper(e float64) Function {
   107  	return func(buf []float64) {
   108  		size := len(buf)
   109  		eN := e * float64(size)
   110  
   111  		buf[0] *= 0
   112  		for n := 1; n < int(eN); n++ {
   113  			buf[n] *= 1.0 / (1.0 + math.Exp((eN/float64(n))-(eN/(eN-float64(n)))))
   114  		}
   115  
   116  		for n := 1; n <= size/2; n++ {
   117  			buf[size-n] *= buf[n-1]
   118  		}
   119  	}
   120  }