From 4a4621a1267fb5c88668bab2549840a3aa3cb5a1 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 20 Mar 2016 01:40:10 +0900 Subject: [PATCH] examples/audio: Implement seeking --- examples/audio/main.go | 49 +++++++++++++++++++++++++++++++++++------- exp/audio/audio.go | 8 ++++--- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/examples/audio/main.go b/examples/audio/main.go index f5480218f..81c3c91e7 100644 --- a/examples/audio/main.go +++ b/examples/audio/main.go @@ -57,8 +57,40 @@ var ( audioLoaded bool audioPlayer *audio.Player total time.Duration + mouseButtonState = map[ebiten.MouseButton]int{} ) +func playerBarRect() (x, y, w, h int) { + w, h = playerBarImage.Size() + x = (screenWidth - w) / 2 + y = screenHeight - h - 16 + return +} + +func updatePlayerBar() error { + if !audioLoaded { + return nil + } + if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + mouseButtonState[ebiten.MouseButtonLeft] = 0 + return nil + } + mouseButtonState[ebiten.MouseButtonLeft]++ + if mouseButtonState[ebiten.MouseButtonLeft] != 1 { + return nil + } + x, y := ebiten.CursorPosition() + bx, by, bw, bh := playerBarRect() + if y < by || by+bh <= y { + return nil + } + if x < bx || bx+bw <= x { + return nil + } + p := time.Duration(x-bx) * total / time.Duration(bw) + return audioPlayer.Seek(p) +} + func update(screen *ebiten.Image) error { audioContext.Update() if !audioLoaded { @@ -69,11 +101,13 @@ func update(screen *ebiten.Image) error { } } + if err := updatePlayerBar(); err != nil { + return err + } + op := &ebiten.DrawImageOptions{} - w, h := playerBarImage.Size() - x := float64(screenWidth-w) / 2 - y := float64(screenHeight - h - 16) - op.GeoM.Translate(x, y) + x, y, w, h := playerBarRect() + op.GeoM.Translate(float64(x), float64(y)) screen.DrawImage(playerBarImage, op) currentTimeStr := "" if audioLoaded && audioPlayer.IsPlaying() { @@ -85,12 +119,11 @@ func update(screen *ebiten.Image) error { currentTimeStr = fmt.Sprintf("%02d:%02d", m, s) // Bar - w, _ := playerBarImage.Size() cw, ch := playerCurrentImage.Size() - cx := float64(w)*float64(c)/float64(total) + x - float64(cw)/2 - cy := y - float64(ch-h)/2 + cx := int(time.Duration(w)*c/total) + x - cw/2 + cy := y - (ch-h)/2 op := &ebiten.DrawImageOptions{} - op.GeoM.Translate(cx, cy) + op.GeoM.Translate(float64(cx), float64(cy)) screen.DrawImage(playerCurrentImage, op) } diff --git a/exp/audio/audio.go b/exp/audio/audio.go index eccd69e04..69c6f14d3 100644 --- a/exp/audio/audio.go +++ b/exp/audio/audio.go @@ -39,6 +39,9 @@ const ( channelNum = 2 bytesPerSample = 2 bitsPerSample = bytesPerSample * 8 + + // TODO: This assumes that channelNum is a power of 2. + mask = ^(channelNum*bytesPerSample - 1) ) func (s *mixedPlayersStream) Read(b []byte) (int, error) { @@ -51,8 +54,6 @@ func (s *mixedPlayersStream) Read(b []byte) (int, error) { return 0, nil } - // TODO: This assumes that channelNum is a power of 2. - const mask = ^(channelNum*bytesPerSample - 1) if len(s.context.players) == 0 { l := min(len(b), x-s.writtenBytes) l &= mask @@ -222,7 +223,8 @@ func (p *Player) Rewind() error { func (p *Player) Seek(offset time.Duration) error { p.buf = []byte{} - o := int64(offset) * int64(p.context.sampleRate) / int64(time.Second) + o := int64(offset) * bytesPerSample * channelNum * int64(p.context.sampleRate) / int64(time.Second) + o &= mask pos, err := p.src.Seek(o, 0) if err != nil { return err