github.com/gopherd/gonum@v0.0.4/dsp/window/window.go (about)

     1  // Copyright ©2020 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package window
     6  
     7  import "math"
     8  
     9  // Rectangular modifies seq in place by the Rectangular window and returns
    10  // the result.
    11  // See https://en.wikipedia.org/wiki/Window_function#Rectangular_window and
    12  // https://www.recordingblogs.com/wiki/rectangular-window for details.
    13  //
    14  // The rectangular window has the lowest width of the main lobe and largest
    15  // level of the side lobes. The result corresponds to a selection of
    16  // limited length sequence of values without any modification.
    17  //
    18  // The sequence weights are
    19  //  w[k] = 1,
    20  // for k=0,1,...,N-1 where N is the length of the window.
    21  //
    22  // Spectral leakage parameters: ΔF_0 = 2, ΔF_0.5 = 0.89, K = 1, ɣ_max = -13, β = 0.
    23  func Rectangular(seq []float64) []float64 {
    24  	return seq
    25  }
    26  
    27  // Sine modifies seq in place by the Sine window and returns the result.
    28  // See https://en.wikipedia.org/wiki/Window_function#Sine_window and
    29  // https://www.recordingblogs.com/wiki/sine-window for details.
    30  //
    31  // Sine window is a high-resolution window.
    32  //
    33  // The sequence weights are
    34  //  w[k] = sin(π*k/(N-1)),
    35  // for k=0,1,...,N-1 where N is the length of the window.
    36  //
    37  // Spectral leakage parameters: ΔF_0 = 3, ΔF_0.5 = 1.23, K = 1.5, ɣ_max = -23, β = -3.93.
    38  func Sine(seq []float64) []float64 {
    39  	k := math.Pi / float64(len(seq)-1)
    40  	for i := range seq {
    41  		seq[i] *= math.Sin(k * float64(i))
    42  	}
    43  	return seq
    44  }
    45  
    46  // Lanczos modifies seq in place by the Lanczos window and returns the result.
    47  // See https://en.wikipedia.org/wiki/Window_function#Lanczos_window and
    48  // https://www.recordingblogs.com/wiki/lanczos-window for details.
    49  //
    50  // The Lanczos window is a high-resolution window.
    51  //
    52  // The sequence weights are
    53  //  w[k] = sinc(2*k/(N-1) - 1),
    54  // for k=0,1,...,N-1 where N is the length of the window.
    55  //
    56  // Spectral leakage parameters: ΔF_0 = 3.24, ΔF_0.5 = 1.3, K = 1.62, ɣ_max = -26.4, β = -4.6.
    57  func Lanczos(seq []float64) []float64 {
    58  	k := 2 / float64(len(seq)-1)
    59  	for i := range seq {
    60  		x := math.Pi * (k*float64(i) - 1)
    61  		if x == 0 {
    62  			// Avoid NaN.
    63  			continue
    64  		}
    65  		seq[i] *= math.Sin(x) / x
    66  	}
    67  	return seq
    68  }
    69  
    70  // Triangular modifies seq in place by the Triangular window and returns
    71  // the result.
    72  // See https://en.wikipedia.org/wiki/Window_function#Triangular_window and
    73  // https://www.recordingblogs.com/wiki/triangular-window for details.
    74  //
    75  // The Triangular window is a high-resolution window.
    76  //
    77  // The sequence weights are
    78  //  w[k] = 1 - |k/A -1|, A=(N-1)/2,
    79  // for k=0,1,...,N-1 where N is the length of the window.
    80  //
    81  // Spectral leakage parameters: ΔF_0 = 4, ΔF_0.5 = 1.33, K = 2, ɣ_max = -26.5, β = -6.
    82  func Triangular(seq []float64) []float64 {
    83  	a := float64(len(seq)-1) / 2
    84  	for i := range seq {
    85  		seq[i] *= 1 - math.Abs(float64(i)/a-1)
    86  	}
    87  	return seq
    88  }
    89  
    90  // Hann modifies seq in place by the Hann window and returns the result.
    91  // See https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
    92  // and https://www.recordingblogs.com/wiki/hann-window for details.
    93  //
    94  // The Hann window is a high-resolution window.
    95  //
    96  // The sequence weights are
    97  //  w[k] = 0.5*(1 - cos(2*π*k/(N-1))),
    98  // for k=0,1,...,N-1 where N is the length of the window.
    99  //
   100  // Spectral leakage parameters: ΔF_0 = 4, ΔF_0.5 = 1.5, K = 2, ɣ_max = -31.5, β = -6.
   101  func Hann(seq []float64) []float64 {
   102  	k := 2 * math.Pi / float64(len(seq)-1)
   103  	for i := range seq {
   104  		seq[i] *= 0.5 * (1 - math.Cos(k*float64(i)))
   105  	}
   106  	return seq
   107  }
   108  
   109  // BartlettHann modifies seq in place by the Bartlett-Hann window and returns
   110  // result.
   111  // See https://en.wikipedia.org/wiki/Window_function#Bartlett%E2%80%93Hann_window
   112  // and https://www.recordingblogs.com/wiki/bartlett-hann-window for details.
   113  //
   114  // The Bartlett-Hann window is a high-resolution window.
   115  //
   116  // The sequence weights are
   117  //  w[k] = 0.62 - 0.48*|k/(N-1)-0.5| - 0.38*cos(2*π*k/(N-1)),
   118  // for k=0,1,...,N-1 where N is the length of the window.
   119  //
   120  // Spectral leakage parameters: ΔF_0 = 4, ΔF_0.5 = 1.45, K = 2, ɣ_max = -35.9, β = -6.
   121  func BartlettHann(seq []float64) []float64 {
   122  	const (
   123  		a0 = 0.62
   124  		a1 = 0.48
   125  		a2 = 0.38
   126  	)
   127  
   128  	k := 2 * math.Pi / float64(len(seq)-1)
   129  	for i := range seq {
   130  		seq[i] *= a0 - a1*math.Abs(float64(i)/float64(len(seq)-1)-0.5) - a2*math.Cos(k*float64(i))
   131  	}
   132  	return seq
   133  }
   134  
   135  // Hamming modifies seq in place by the Hamming window and returns the result.
   136  // See https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
   137  // and https://www.recordingblogs.com/wiki/hamming-window for details.
   138  //
   139  // The Hamming window is a high-resolution window. Among K=2 windows it has
   140  // the highest ɣ_max.
   141  //
   142  // The sequence weights are
   143  //  w[k] = 25/46 - 21/46 * cos(2*π*k/(N-1)),
   144  // for k=0,1,...,N-1 where N is the length of the window.
   145  //
   146  // Spectral leakage parameters: ΔF_0 = 4, ΔF_0.5 = 1.33, K = 2, ɣ_max = -42, β = -5.37.
   147  func Hamming(seq []float64) []float64 {
   148  	const (
   149  		a0 = 0.54
   150  		a1 = 0.46
   151  	)
   152  
   153  	k := 2 * math.Pi / float64(len(seq)-1)
   154  	for i := range seq {
   155  		seq[i] *= a0 - a1*math.Cos(k*float64(i))
   156  	}
   157  	return seq
   158  }
   159  
   160  // Blackman modifies seq in place by the Blackman window and returns the
   161  // result.
   162  // See https://en.wikipedia.org/wiki/Window_function#Blackman_window and
   163  // https://www.recordingblogs.com/wiki/blackman-window for details.
   164  //
   165  // The Blackman window is a high-resolution window.
   166  //
   167  // The sequence weights are
   168  //  w[k] = 0.42 - 0.5*cos(2*π*k/(N-1)) + 0.08*cos(4*π*k/(N-1)),
   169  // for k=0,1,...,N-1 where N is the length of the window.
   170  //
   171  // Spectral leakage parameters: ΔF_0 = 6, ΔF_0.5 = 1.7, K = 3, ɣ_max = -58, β = -7.54.
   172  func Blackman(seq []float64) []float64 {
   173  	const (
   174  		a0 = 0.42
   175  		a1 = 0.5
   176  		a2 = 0.08
   177  	)
   178  
   179  	k := 2 * math.Pi / float64(len(seq)-1)
   180  	for i := range seq {
   181  		x := k * float64(i)
   182  		seq[i] *= a0 - a1*math.Cos(x) + a2*math.Cos(2*x)
   183  	}
   184  	return seq
   185  }
   186  
   187  // BlackmanHarris modifies seq in place by the Blackman-Harris window and
   188  // returns the result.
   189  // See https://en.wikipedia.org/wiki/Window_function#Blackman%E2%80%93Harris_window
   190  // and https://www.recordingblogs.com/wiki/blackman-harris-window for details.
   191  //
   192  // The Blackman-Harris window is a low-resolution window.
   193  //
   194  // The sequence weights are
   195  //  w[k] = 0.35875 - 0.48829*cos(2*π*k/(N-1)) +
   196  //         0.14128*cos(4*π*k/(N-1)) - 0.01168*cos(6*π*k/(N-1)),
   197  // for k=0,1,...,N-1 where N is the length of the window.
   198  //
   199  // Spectral leakage parameters:  ΔF_0 = 8, ΔF_0.5 = 1.97, K = 4, ɣ_max = -92, β = -8.91.
   200  func BlackmanHarris(seq []float64) []float64 {
   201  	const (
   202  		a0 = 0.35875
   203  		a1 = 0.48829
   204  		a2 = 0.14128
   205  		a3 = 0.01168
   206  	)
   207  
   208  	k := 2 * math.Pi / float64(len(seq)-1)
   209  	for i := range seq {
   210  		x := k * float64(i)
   211  		seq[i] *= a0 - a1*math.Cos(x) + a2*math.Cos(2*x) - a3*math.Cos(3*x)
   212  	}
   213  	return seq
   214  }
   215  
   216  // Nuttall modifies seq in place by the Nuttall window and returns the result.
   217  // See https://en.wikipedia.org/wiki/Window_function#Nuttall_window,_continuous_first_derivative
   218  // and https://www.recordingblogs.com/wiki/nuttall-window for details.
   219  //
   220  // The Nuttall window is a low-resolution window.
   221  //
   222  // The sequence weights are
   223  //  w[k] = 0.355768 - 0.487396*cos(2*π*k/(N-1)) + 0.144232*cos(4*π*k/(N-1)) -
   224  //         0.012604*cos(6*π*k/(N-1)),
   225  // for k=0,1,...,N-1 where N is the length of the window.
   226  //
   227  // Spectral leakage parameters: ΔF_0 = 8, ΔF_0.5 = 1.98, K = 4, ɣ_max = -93, β = -9.
   228  func Nuttall(seq []float64) []float64 {
   229  	const (
   230  		a0 = 0.355768
   231  		a1 = 0.487396
   232  		a2 = 0.144232
   233  		a3 = 0.012604
   234  	)
   235  
   236  	k := 2 * math.Pi / float64(len(seq)-1)
   237  	for i := range seq {
   238  		x := k * float64(i)
   239  		seq[i] *= a0 - a1*math.Cos(x) + a2*math.Cos(2*x) - a3*math.Cos(3*x)
   240  	}
   241  	return seq
   242  }
   243  
   244  // BlackmanNuttall modifies seq in place by the Blackman-Nuttall window and
   245  // returns the result.
   246  // See https://en.wikipedia.org/wiki/Window_function#Blackman%E2%80%93Nuttall_window
   247  // and https://www.recordingblogs.com/wiki/blackman-nuttall-window for details.
   248  //
   249  // The Blackman-Nuttall window is a low-resolution window.
   250  //
   251  // The sequence weights are
   252  //  w[k] = 0.3635819 - 0.4891775*cos(2*π*k/(N-1)) + 0.1365995*cos(4*π*k/(N-1)) -
   253  //         0.0106411*cos(6*π*k/(N-1)),
   254  // for k=0,1,...,N-1 where N is the length of the window.
   255  //
   256  // Spectral leakage parameters: ΔF_0 = 8, ΔF_0.5 = 1.94, K = 4, ɣ_max = -98, β = -8.8.
   257  func BlackmanNuttall(seq []float64) []float64 {
   258  	const (
   259  		a0 = 0.3635819
   260  		a1 = 0.4891775
   261  		a2 = 0.1365995
   262  		a3 = 0.0106411
   263  	)
   264  
   265  	k := 2 * math.Pi / float64(len(seq)-1)
   266  	for i := range seq {
   267  		x := k * float64(i)
   268  		seq[i] *= a0 - a1*math.Cos(x) + a2*math.Cos(2*x) - a3*math.Cos(3*x)
   269  	}
   270  	return seq
   271  }
   272  
   273  // FlatTop modifies seq in place by the Flat Top window and returns the
   274  // result.
   275  // See https://en.wikipedia.org/wiki/Window_function#Flat_top_window and
   276  // https://www.recordingblogs.com/wiki/flat-top-window for details.
   277  //
   278  // The Flat Top window is a low-resolution window.
   279  //
   280  // The sequence weights are
   281  //  w[k] = 0.21557895 - 0.41663158*cos(2*π*k/(N-1)) +
   282  //         0.277263158*cos(4*π*k/(N-1)) - 0.083578947*cos(6*π*k/(N-1)) +
   283  //         0.006947368*cos(4*π*k/(N-1)),
   284  // for k=0,1,...,N-1 where N is the length of the window.
   285  //
   286  // Spectral leakage parameters: ΔF_0 = 10, ΔF_0.5 = 3.72, K = 5, ɣ_max = -93.0, β = -13.34.
   287  func FlatTop(seq []float64) []float64 {
   288  	const (
   289  		a0 = 0.21557895
   290  		a1 = 0.41663158
   291  		a2 = 0.277263158
   292  		a3 = 0.083578947
   293  		a4 = 0.006947368
   294  	)
   295  
   296  	k := 2 * math.Pi / float64(len(seq)-1)
   297  	for i := range seq {
   298  		x := k * float64(i)
   299  		seq[i] *= a0 - a1*math.Cos(x) + a2*math.Cos(2*x) - a3*math.Cos(3*x) + a4*math.Cos(4*x)
   300  	}
   301  	return seq
   302  }