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