aboutsummaryrefslogtreecommitdiff
path: root/wav/wav.go
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2017-07-28 23:15:43 -0400
committerNathan Perry <avaglir@gmail.com>2017-07-28 23:15:43 -0400
commit2d867f0e32ec8eacdd0c9bb51094cd38707e4d88 (patch)
treed8a137166ed1e278aa4028092839b5cfcb5ac265 /wav/wav.go
parent85d19683f6619150ff949822e1bb118472241d13 (diff)
just working with downloader
Diffstat (limited to 'wav/wav.go')
-rw-r--r--wav/wav.go95
1 files changed, 78 insertions, 17 deletions
diff --git a/wav/wav.go b/wav/wav.go
index 8556d60..c505a32 100644
--- a/wav/wav.go
+++ b/wav/wav.go
@@ -6,63 +6,126 @@ import "C"
import (
"fmt"
+ "sync"
+
"github.com/op/go-logging"
"layeh.com/gopus"
)
+type State int
+
+const (
+ Pause State = iota
+ Resume
+)
+
// number of individual samples per channel per batch
const samplesPerChannelPerBatch = 1920
var log = logging.MustGetLogger("wav")
-func Load(filename string, ch chan<- []byte) (<-chan struct{}, error) {
+type Wav struct {
+ filename *C.char
+ enc *gopus.Encoder
+ wav *C.drwav
+
+ PlayState chan State
+ curState State
+
+ once sync.Once
+ Done <-chan struct{}
+ done chan<- struct{}
+}
+
+func New(filename string) (*Wav, error) {
cfname := C.CString(filename)
wav := C.drwav_open_file(cfname)
if wav == nil {
- close(ch)
+ C.drwav_close(wav)
return nil, fmt.Errorf("Unable to initialize drwav.")
}
if int(wav.channels) != 2 {
C.drwav_close(wav)
- close(ch)
return nil, fmt.Errorf("Wrong number of channels!")
}
if int(wav.sampleRate) != 48000 {
C.drwav_close(wav)
- close(ch)
return nil, fmt.Errorf("Wrong sample rate.")
}
enc, err := gopus.NewEncoder(int(wav.sampleRate), int(wav.channels), gopus.Audio)
if err != nil {
- close(ch)
+ C.drwav_close(wav)
return nil, err
}
done := make(chan struct{}, 1)
- go func(wav *C.drwav) {
- defer close(done)
- defer close(ch)
+ return &Wav{
+ filename: C.CString(filename),
+ enc: enc,
+ wav: wav,
+
+ PlayState: make(chan State),
+ curState: Resume,
- samplesPerBatch := samplesPerChannelPerBatch * int(wav.channels)
- batchSize := samplesPerBatch * int(wav.bytesPerSample)
+ done: done,
+ Done: done,
+ }, nil
+}
+
+func (w *Wav) Stop() {
+ w.once.Do(func() {
+ close(w.done)
+ })
+}
+
+func (w *Wav) Start(ch chan<- []byte) {
+ go func() {
+ defer w.Stop()
+
+ samplesPerBatch := samplesPerChannelPerBatch * int(w.wav.channels)
+ batchSize := samplesPerBatch * int(w.wav.bytesPerSample)
buf := C.malloc(C.size_t(batchSize))
defer C.free(buf)
- defer C.drwav_close(wav)
+ defer C.drwav_close(w.wav)
elems := make([]int16, samplesPerBatch)
idx := 0
- for i := 0; i*samplesPerBatch <= int(wav.totalSampleCount); i += 1 {
- readSamples := C.drwav_read_s16(wav, C.dr_uint64(samplesPerBatch), (*C.dr_int16)(buf))
+ for i := 0; i*samplesPerBatch <= int(w.wav.totalSampleCount); i += 1 {
+ readSamples := C.drwav_read_s16(w.wav, C.dr_uint64(samplesPerBatch), (*C.dr_int16)(buf))
slc := (*[1 << 30]int16)(buf)[:readSamples:readSamples]
readIdx := 0
+ inner:
for {
+ // check to see if we should die or pause
+ if w.curState == Pause { // if paused wait to die or get resumed
+ select {
+ case st := <-w.PlayState:
+ w.curState = st
+ continue inner
+
+ case <-w.Done:
+ return
+ }
+
+ } else {
+ select {
+ case st := <-w.PlayState:
+ w.curState = st
+ continue inner
+
+ case <-w.Done:
+ return
+ default:
+ }
+ }
+
batchSamplesToFill := samplesPerBatch - idx
readSamplesRemaining := int(readSamples) - readIdx
@@ -75,7 +138,7 @@ func Load(filename string, ch chan<- []byte) (<-chan struct{}, error) {
idx = 0
readIdx += batchSamplesToFill
- b, err := processPCM(wav, enc, elems[:])
+ b, err := processPCM(w.wav, w.enc, elems[:])
if err != nil {
log.Errorf("error encoding pcm: %q", err)
continue
@@ -96,9 +159,7 @@ func Load(filename string, ch chan<- []byte) (<-chan struct{}, error) {
break
}
}
- }(wav)
-
- return done, nil
+ }()
}
func processPCM(wav *C.drwav, enc *gopus.Encoder, data []int16) ([]byte, error) {