// Estimates beats that are not in the provided list by using least squares regression to fit the beats
// to a straight line (assumes the BPM is reasonably constant).
Estimates beats that are not in the provided list by using least squares regression to fit the beats
to a straight line (assumes the BPM is reasonably constant).
// Estimates beats that are not in the provided list by using least squares regression to fit the beats // to a straight line ( assumes the BPM is reasonably constant ) .
func (beats *Beats) Interpolate(start, end time.Duration) error {
	switch {
	case beats == nil:
		return nil
	case len(beats.Beats) == 0:
		return fmt.Errorf("Insufficient data")
	case len(beats.Beats) == 1 && beats.BPM == 0:
		return fmt.Errorf("Insufficient data")
	case len(beats.Beats) == 1:
		m := 60.0 / float64(beats.BPM)
		c := beats.Beats[0].At.Seconds() - m
		bmin := int(math.Floor((start.Seconds() - c) / m))
		bmax := int(math.Ceil((end.Seconds() - c) / m))
		interpolated := []Beat{}
		for b := bmin; b <= bmax; b++ {
			tt := float64(b)*m + c
			if tt >= start.Seconds() && tt <= end.Seconds() {
				if b == 1 {
					interpolated = append(interpolated, beats.Beats[0])
				} else {
					interpolated = append(interpolated, Beat{At: Seconds(tt)})
				}
			}
		}
		beats.BPM, beats.Offset = bpm(interpolated)
		beats.Beats = interpolated
		return nil
	default:
		m, c, err := fit(beats.Beats)
		if err != nil {
			return err
		}
		index := map[int]Beat{}
		for _, b := range beats.Beats {
			index[b.beat] = b
		}
		bmin := int(math.Floor((start.Seconds() - c) / m))
		bmax := int(math.Ceil((end.Seconds() - c) / m))
		interpolated := []Beat{}
		for b := bmin; b <= bmax; b++ {
			tt := float64(b)*m + c
			if tt >= start.Seconds() && tt <= end.Seconds() {
				if beat, ok := index[b]; ok {
					interpolated = append(interpolated, beat)
				} else {
					interpolated = append(interpolated, Beat{At: Seconds(tt)})
				}
			}
		}
		beats.BPM, beats.Offset = bpm(interpolated)
		beats.Beats = interpolated
		return nil
	}
}
func ( beats * Beats ) Interpolate ( start , end time . Duration ) error { switch { case beats == nil : return nil case len ( beats . Beats ) == 0 : return fmt . Errorf ( " " ) case len ( beats . Beats ) == 1 && beats . BPM == 0 : return fmt . Errorf ( " " ) case len ( beats . Beats ) == 1 : m := 60.0 / float64 ( beats . BPM ) c := beats . Beats [ 0 ] . At . Seconds ( ) - m bmin := int ( math . Floor ( ( start . Seconds ( ) - c ) / m ) ) bmax := int ( math . Ceil ( ( end . Seconds ( ) - c ) / m ) ) interpolated := [ ] Beat { } for b := bmin ; b <= bmax ; b ++ { tt := float64 ( b ) * m + c if tt >= start . Seconds ( ) && tt <= end . Seconds ( ) { if b == 1 { interpolated = append ( interpolated , beats . Beats [ 0 ] ) } else { interpolated = append ( interpolated , Beat { At : Seconds ( tt ) } ) } } } beats . BPM , beats . Offset = bpm ( interpolated ) beats . Beats = interpolated return nil default : m , c , err := fit ( beats . Beats ) if err != nil { return err } index := map [ int ] Beat { } for _ , b := range beats . Beats { index [ b . beat ] = b } bmin := int ( math . Floor ( ( start . Seconds ( ) - c ) / m ) ) bmax := int ( math . Ceil ( ( end . Seconds ( ) - c ) / m ) ) interpolated := [ ] Beat { } for b := bmin ; b <= bmax ; b ++ { tt := float64 ( b ) * m + c if tt >= start . Seconds ( ) && tt <= end . Seconds ( ) { if beat , ok := index [ b ] ; ok { interpolated = append ( interpolated , beat ) } else { interpolated = append ( interpolated , Beat { At : Seconds ( tt ) } ) } } } beats . BPM , beats . Offset = bpm ( interpolated ) beats . Beats = interpolated return nil } }
Estimates beats that are not in the provided list by using least squares regression to fit the beats
to a straight line (assumes the BPM is reasonably constant).
Estimates beats that are not in the provided list by using least squares regression to fit the beats to a straight line ( assumes the BPM is reasonably constant ) .