// Performs a 'best guess' as to which beat number corresponds to which estimated beat,by fitting the
// beats to a line, adjusting the beats and calculating the variance between the beats and adjusted
// beats. Returns when the average variance is sufficiently low.
Performs a 'best guess' as to which beat number corresponds to which estimated beat,by fitting the
beats to a line, adjusting the beats and calculating the variance between the beats and adjusted
beats. Returns when the average variance is sufficiently low.
// Performs a ' best guess ' as to which beat number corresponds to which estimated beat by fitting the // beats to a line adjusting the beats and calculating the variance between the beats and adjusted // beats . Returns when the average variance is sufficiently low .
func reindex(beats []Beat) error {
	sort.SliceStable(beats, func(i, j int) bool { return beats[i].At < beats[j].At })
	at := make([]float64, len(beats))
	for i, b := range beats {
		at[i] = b.At.Seconds()
	}
	N := len(at)
	index := make([]int, N)
	for i := range index {
		index[i] = i + 1
	}
	if N <= 2 {
		for i := range beats {
			beats[i].beat = index[i]
		}
		return nil
	}
	x0 := at[0]
	xn := at[N-1]
	y0 := 1.0
	dt := Seconds(xn - x0).Minutes()
	bmax := int(math.Ceil(dt * float64(MaxBPM*MinSubdivision/4)))
	variance := math.MaxFloat64
loop:
	for i := N; i <= bmax; i++ {
		yn := float64(i)
		m := (yn - y0) / (xn - x0)
		c := yn - m*xn
		x := at[0]
		y := m*x + c
		b0 := math.Round(y)
		index[0] = int(b0)
		sumsq := y*y - 2*y*b0 + b0*b0
		for j := 1; j < N; j++ {
			x := at[j]
			y := m*x + c
			bn := math.Round(y)
			index[j] = int(bn)
			if index[j] <= index[j-1] {
				continue loop
			}
			sumsq += y*y - 2*y*bn + bn*bn
		}
		sigmasq := sumsq / float64(N-1)
		if sigmasq < variance {
			for i := range beats {
				beats[i].beat = index[i]
			}
			variance = sigmasq
		}
		if variance < 0.001 {
			break
		}
	}
	if variance > 0.05 {
		return fmt.Errorf("Error mapping taps to beats: %v", beats)
	}
	return nil
}
func reindex ( beats [ ] Beat ) error { sort . SliceStable ( beats , func ( i , j int ) bool { return beats [ i ] . At < beats [ j ] . At } ) at := make ( [ ] float64 , len ( beats ) ) for i , b := range beats { at [ i ] = b . At . Seconds ( ) } N := len ( at ) index := make ( [ ] int , N ) for i := range index { index [ i ] = i + 1 } if N <= 2 { for i := range beats { beats [ i ] . beat = index [ i ] } return nil } x0 := at [ 0 ] xn := at [ N - 1 ] y0 := 1.0 dt := Seconds ( xn - x0 ) . Minutes ( ) bmax := int ( math . Ceil ( dt * float64 ( MaxBPM * MinSubdivision / 4 ) ) ) variance := math . MaxFloat64 loop : for i := N ; i <= bmax ; i ++ { yn := float64 ( i ) m := ( yn - y0 ) / ( xn - x0 ) c := yn - m * xn x := at [ 0 ] y := m * x + c b0 := math . Round ( y ) index [ 0 ] = int ( b0 ) sumsq := y * y - 2 * y * b0 + b0 * b0 for j := 1 ; j < N ; j ++ { x := at [ j ] y := m * x + c bn := math . Round ( y ) index [ j ] = int ( bn ) if index [ j ] <= index [ j - 1 ] { continue loop } sumsq += y * y - 2 * y * bn + bn * bn } sigmasq := sumsq / float64 ( N - 1 ) if sigmasq < variance { for i := range beats { beats [ i ] . beat = index [ i ] } variance = sigmasq } if variance < 0.001 { break } } if variance > 0.05 { return fmt . Errorf ( " " , beats ) } return nil }
Performs a 'best guess' as to which beat number corresponds to which estimated beat,by fitting the
beats to a line, adjusting the beats and calculating the variance between the beats and adjusted
beats.
Performs a ' best guess ' as to which beat number corresponds to which estimated beat by fitting the beats to a line adjusting the beats and calculating the variance between the beats and adjusted beats .
// ... trivial cases // ... 3+ intervals