uplink/plugins/test/sine/sine_stream.go

61 lines
1.5 KiB
Go

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
}