package sine import ( "bytes" "encoding/binary" "math" "time" ) type SineStream struct { Frequency float64 Samplerate int State uint64 Beep bool Timestamp time.Time } func makeSample(channelValues ...float64) (ret []byte) { // target format: s16le buf := new(bytes.Buffer) for _, value := range channelValues { intValue := int16(value * math.MaxInt16) binary.Write(buf, binary.LittleEndian, intValue) } return buf.Bytes() } func (stream *SineStream) Read(data []byte) (n int, err error) { n = 0 for (len(data) - n) >= 4 { // at least 2 bytes per channel need to be available var sampleValue float64 if stream.Beep && stream.State%uint64(stream.Samplerate) > uint64(float64(stream.Samplerate)*0.15) { sampleValue = 0 } else { sampleValue = math.Sin(stream.Frequency * 2. * math.Pi * (float64(stream.State) / float64(stream.Samplerate))) } b := makeSample(sampleValue, sampleValue) copy(data[n:], b) n += len(b) targetTime := stream.Timestamp. Add(time.Duration(float64(time.Second) * float64(stream.State) / float64(stream.Samplerate))) delay := targetTime.Sub(time.Now()) /*log.Println("state", stream.State, "value", sampleValue, "time", targetTime, "delay", delay) time.Sleep(time.Second)*/ if delay > 0 { <-time.After(delay) } /*if stream.State%uint64(stream.Samplerate) == 0 { log.Println("state", stream.State, "value", sampleValue, "time", targetTime, "delay", delay) }*/ stream.State++ } return }