diff options
| author | Nathan Perry <avaglir@gmail.com> | 2017-07-28 23:15:43 -0400 |
|---|---|---|
| committer | Nathan Perry <avaglir@gmail.com> | 2017-07-28 23:15:43 -0400 |
| commit | 2d867f0e32ec8eacdd0c9bb51094cd38707e4d88 (patch) | |
| tree | d8a137166ed1e278aa4028092839b5cfcb5ac265 /wav | |
| parent | 85d19683f6619150ff949822e1bb118472241d13 (diff) | |
just working with downloader
Diffstat (limited to 'wav')
| -rw-r--r-- | wav/wav.go | 95 |
1 files changed, 78 insertions, 17 deletions
@@ -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) { |
