package subsync import "math/bits" // signal is "somebody is speaking" as one bit per time bin. // // A bitset rather than a []bool because the search is the whole cost of this feature: a // two-hour film at 50ms is around 144,000 bins, and every one of ~2,400 shifts has to // compare all of them against every stretch candidate. Packed into words, one comparison // is an AND and a population count over 2,250 words instead of 144,000 byte reads, which // is the difference between a button that answers while somebody is still looking at the // menu and one they wait on. math/bits.OnesCount64 compiles to a single instruction on // every architecture this runs on. type signal struct { words []uint64 bins int on int } func newSignal(bins int) *signal { if bins < 1 { bins = 1 } return &signal{words: make([]uint64, (bins+63)/64), bins: bins} } // set marks the half-open bin range [from, to) as speech. func (s *signal) set(from, to int) { if from < 0 { from = 0 } if to > s.bins { to = s.bins } for i := from; i < to; i++ { word, bit := i/64, uint(i%64) if s.words[word]&(1<= len(other.words) { break } theirs := other.words[j] >> bitShift // Go defines a shift of 64 or more as zero, so this term vanishes when bitShift // is zero rather than needing a branch of its own. if j+1 < len(other.words) { theirs |= other.words[j+1] << (64 - bitShift) } total += bits.OnesCount64(mine & theirs) } return total }