Documentation
¶
Index ¶
Constants ¶
const ChunkBytes = WindowSize * 2 * 2
ChunkBytes is the number of raw bytes per FFT frame (stereo, 16-bit). 2048 samples × 2 channels × 2 bytes = 8192.
const NumBands = 64
NumBands is the number of frequency bands in FFT output.
const WindowSize = 2048
WindowSize is the number of mono samples per FFT frame. 2048 at 44100 Hz = ~46 ms, a good latency/resolution tradeoff.
Variables ¶
var DefaultFormat = PCMFormat{SampleRate: 44100, Channels: 2, BitDepth: 16}
DefaultFormat is librespot's default output: 44100 Hz, stereo, 16-bit signed LE.
Functions ¶
This section is empty.
Types ¶
type Analyzer ¶
type Analyzer struct {
// contains filtered or unexported fields
}
Analyzer performs FFT analysis on PCM audio chunks and produces FrequencyData.
func NewAnalyzer ¶
NewAnalyzer creates an Analyzer with a precomputed Hann window of the given size.
func (*Analyzer) Analyze ¶
func (a *Analyzer) Analyze(samples []int16) FrequencyData
Analyze takes interleaved stereo int16 PCM samples and returns FrequencyData. The samples slice must contain at least WindowSize*2 values (stereo pairs).
type FrequencyData ¶
type FrequencyData struct {
Bands [NumBands]float32 // log-spaced frequency bands, normalized 0.0–1.0
Peak float32 // overall peak amplitude this frame
Bass float32 // average of bands 0–7
Mid float32 // average of bands 8–31
High float32 // average of bands 32–63
ProgressMs int32 // playback progress derived from PCM sample count
}
FrequencyData holds FFT output mapped to visualization-friendly bands.
func (*FrequencyData) ComputeConvenienceFields ¶
func (fd *FrequencyData) ComputeConvenienceFields()
ComputeConvenienceFields fills Bass, Mid, and High from Bands.
type PipeReader ¶ added in v0.2.0
type PipeReader struct {
// NewPlayer creates an audio player. Defaults to oto. Override in tests.
NewPlayer playerFactory
// contains filtered or unexported fields
}
PipeReader reads raw PCM from librespot's stdout pipe, plays it via oto, runs FFT analysis, and stores the latest FrequencyData atomically.
func NewPipeReader ¶ added in v0.2.0
func NewPipeReader() *PipeReader
NewPipeReader creates a PipeReader ready to accept pipes via Start().
func (*PipeReader) Latest ¶ added in v0.2.0
func (pr *PipeReader) Latest() *FrequencyData
Latest returns the most recent FrequencyData, or nil if no fresh data. Returns nil if the last frame is older than 150ms (e.g., paused or between restarts). Thread-safe; called from the Bubble Tea goroutine.
func (*PipeReader) Start ¶ added in v0.2.0
func (pr *PipeReader) Start(pipe io.ReadCloser)
Start begins reading PCM from pipe, playing audio and running FFT analysis. Safe to call multiple times — each call cancels the previous read loop. This handles librespot restarts which create a new stdout pipe each time.
func (*PipeReader) Stop ¶ added in v0.2.0
func (pr *PipeReader) Stop()
Stop cancels any active read loop. Safe to call multiple times.