From 42d5eb94ff1a63d21312e633d621ca49b8ee68c6 Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Wed, 9 Apr 2025 14:03:33 -0400 Subject: [PATCH] audio player basics complete --- backend/player/player.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/backend/player/player.go b/backend/player/player.go index 9044e26..356902b 100644 --- a/backend/player/player.go +++ b/backend/player/player.go @@ -3,6 +3,7 @@ package player import ( "context" "fmt" + "math" "os" "time" @@ -19,6 +20,7 @@ type Player struct { currentFile *os.File format beep.Format baseStreamer beep.Streamer + seeker beep.StreamSeeker resampled beep.Streamer control *beep.Ctrl volume *effects.Volume @@ -54,14 +56,14 @@ func (p *Player) Init(ctx context.Context) error { if err != nil { return fmt.Errorf("failed to initialize speaker %w", err) } - p.updateStreamers(p.baseStreamer, p.format.SampleRate) return nil } -func (p *Player) updateStreamers(newBaseStreamer beep.Streamer, sr beep.SampleRate) error { +func (p *Player) updateStreamers(newBaseStreamer beep.StreamSeeker, sr beep.SampleRate) error { // set base streamer p.baseStreamer = newBaseStreamer + p.seeker = newBaseStreamer // resample file stream to match speaker // TODO: variable resample quality @@ -103,6 +105,8 @@ func (p *Player) LoadFile(filePath string) error { return fmt.Errorf("failed to decode mp3 %w", err) } + p.currentFile = f + p.updateStreamers(streamer, format.SampleRate) return nil @@ -145,12 +149,14 @@ Positive Volume value means increasing volume Negative Volume value means decreasing volume */ func (p *Player) SetVolume(desiredVolume UserVolume) error { + speaker.Lock() // clamp value between 1 and 100 volume := clampVolume(desiredVolume) // Apply the volume settings p.volume.Volume = float64(volume.ToPlayerVolume()) p.volume.Silent = volume == MinUserVol + speaker.Unlock() return nil } @@ -166,3 +172,23 @@ func (p *Player) MuteToggle() error { p.volume.Silent = !p.volume.Silent return nil } + +// return the current position as an int between 0 and 100 to work with progress bar easily. +func (p *Player) CurrentPosition() (float64, error) { + pos := 100.0 * float64(p.seeker.Position()) / float64(p.seeker.Len()) + return pos, nil +} + +// TODO: double check best type for percentage parameter +// percentage comes from the progress bar as a value between 0 and 100 +func (p *Player) Seek(percentage int) error { + //take percentage value (0-100), make 0-1, multiply by total number of samples in stream + samples := int(math.Round((float64(percentage) / 100.0) * float64(p.seeker.Len()))) + p.seeker.Seek(samples) + return nil +} + +func (p *Player) TrackLengthInSeconds() (int, error) { + len := p.seeker.Len() / int(p.format.SampleRate) + return len, nil +}