beep

package module
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2024 License: MIT Imports: 4 Imported by: 0

README

Beep

GoDoc Go build status Coverage Status Go Report Card Discord Chat

A little package that brings sound to any Go application. Suitable for playback and audio-processing.

go get -u github.com/Crystal303/beep

Features

Beep is built on top of its Streamer interface, which is like io.Reader, but for audio. It was one of the best design decisions I've ever made and it enabled all the rest of the features to naturally come together with not much code.

  • Decode and play WAV, MP3, OGG, and FLAC.
  • Encode and save WAV.
  • Very simple API. Limiting the support to stereo (two channel) audio made it possible to simplify the architecture and the API.
  • Rich library of compositors and effects. Loop, pause/resume, change volume, mix, sequence, change playback speed, and more.
  • Easily create new effects. With the Streamer interface, creating new effects is very easy.
  • Generate completely own artificial sounds. Again, the Streamer interface enables easy sound generation.
  • Very small codebase. The core is just ~1K LOC.

Tutorial

The Wiki contains a handful of tutorials for you to get started. They teach the fundamentals and advanced topics alike. Read them especially if you call speaker.Init every time you play something.

Examples

Speedy Player Doppler Stereo Room
Speedy Player Doppler Stereo Room

Dependencies

For playback, Beep uses Oto under the hood. Check its requirements to see what you need to install for building your application.

Running an already built application should work with no extra dependencies.

License

MIT

Projects using Beep

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

Buffer is a storage for audio data. You can think of it as a bytes.Buffer for audio samples.

func NewBuffer

func NewBuffer(f Format) *Buffer

NewBuffer creates a new empty Buffer which stores samples in the provided format.

func (*Buffer) Append

func (b *Buffer) Append(s Streamer)

Append adds all audio data from the given Streamer to the end of the Buffer.

The Streamer will be drained when this method finishes.

func (*Buffer) Format

func (b *Buffer) Format() Format

Format returns the format of the Buffer.

func (*Buffer) Len

func (b *Buffer) Len() int

Len returns the number of samples currently in the Buffer.

func (*Buffer) Pop

func (b *Buffer) Pop(n int)

Pop removes n samples from the beginning of the Buffer.

Existing Streamers are not affected.

func (*Buffer) Streamer

func (b *Buffer) Streamer(from, to int) StreamSeeker

Streamer returns a StreamSeeker which streams samples in the given interval (including from, excluding to). If from<0 or to>b.Len() or to<from, this method panics.

When using multiple goroutines, synchronization of Streamers with the Buffer is not required, as Buffer is persistent (but efficient and garbage collected).

type Ctrl

type Ctrl struct {
	Streamer Streamer
	Paused   bool
}

Ctrl allows for pausing a Streamer.

Wrap a Streamer in a Ctrl.

ctrl := &beep.Ctrl{Streamer: s}

Then, we can pause the streaming (this will cause Ctrl to stream silence).

ctrl.Paused = true

To completely stop a Ctrl before the wrapped Streamer is drained, just set the wrapped Streamer to nil.

ctrl.Streamer = nil

If you're playing a Streamer wrapped in a Ctrl through the speaker, you need to lock and unlock the speaker when modifying the Ctrl to avoid race conditions.

speaker.Play(ctrl)
// ...
speaker.Lock()
ctrl.Paused = true
speaker.Unlock()

func (*Ctrl) Err

func (c *Ctrl) Err() error

Err returns the error of the wrapped Streamer, if not nil.

func (*Ctrl) Stream

func (c *Ctrl) Stream(samples [][2]float64) (n int, ok bool)

Stream streams the wrapped Streamer, if not nil. If the Streamer is nil, Ctrl acts as drained. When paused, Ctrl streams silence.

type Format

type Format struct {
	// SampleRate is the number of samples per second.
	SampleRate SampleRate

	// NumChannels is the number of channels. The value of 1 is mono, the value of 2 is stereo.
	// The samples should always be interleaved.
	NumChannels int

	// Precision is the number of bytes used to encode a single sample. Only values up to 6 work
	// well, higher values loose precision due to floating point numbers.
	Precision int
}

Format is the format of a Buffer or another audio source.

func (Format) DecodeSigned

func (f Format) DecodeSigned(p []byte) (sample [2]float64, n int)

DecodeSigned decodes a single sample encoded in f.Width() bytes from p in signed format.

func (Format) DecodeUnsigned

func (f Format) DecodeUnsigned(p []byte) (sample [2]float64, n int)

DecodeUnsigned decodes a single sample encoded in f.Width() bytes from p in unsigned format.

func (Format) EncodeSigned

func (f Format) EncodeSigned(p []byte, sample [2]float64) (n int)

EncodeSigned encodes a single sample in f.Width() bytes to p in signed format.

func (Format) EncodeUnsigned

func (f Format) EncodeUnsigned(p []byte, sample [2]float64) (n int)

EncodeUnsigned encodes a single sample in f.Width() bytes to p in unsigned format.

func (Format) Width

func (f Format) Width() int

Width returns the number of bytes per one frame (samples in all channels).

This is equal to f.NumChannels * f.Precision.

type Mixer

type Mixer struct {
	// contains filtered or unexported fields
}

Mixer allows for dynamic mixing of arbitrary number of Streamers. Mixer automatically removes drained Streamers. Mixer's stream never drains, when empty, Mixer streams silence.

func (*Mixer) Add

func (m *Mixer) Add(s ...Streamer)

Add adds Streamers to the Mixer.

func (*Mixer) Clear

func (m *Mixer) Clear()

Clear removes all Streamers from the mixer.

func (*Mixer) Err

func (m *Mixer) Err() error

Err always returns nil for Mixer.

There are two reasons. The first one is that erroring Streamers are immediately drained and removed from the Mixer. The second one is that one Streamer shouldn't break the whole Mixer and you should handle the errors right where they can happen.

func (*Mixer) Len

func (m *Mixer) Len() int

Len returns the number of Streamers currently playing in the Mixer.

func (*Mixer) Stream

func (m *Mixer) Stream(samples [][2]float64) (n int, ok bool)

Stream streams all Streamers currently in the Mixer mixed together. This method always returns len(samples), true. If there are no Streamers available, this methods streams silence.

type Resampler

type Resampler struct {
	// contains filtered or unexported fields
}

Resampler is a Streamer created by Resample and ResampleRatio functions. It allows dynamic changing of the resampling ratio, which can be useful for dynamically changing the speed of streaming.

func Resample

func Resample(quality int, old, new SampleRate, s Streamer) *Resampler

Resample takes a Streamer which is assumed to stream at the old sample rate and returns a Streamer, which streams the data from the original Streamer resampled to the new sample rate.

This is, for example, useful when mixing multiple Streamer with different sample rates, either through a beep.Mixer, or through a speaker. Speaker has a constant sample rate. Thus, playing Streamer which stream at a different sample rate will lead to a changed speed and pitch of the playback.

sr := beep.SampleRate(48000)
speaker.Init(sr, sr.N(time.Second/2))
speaker.Play(beep.Resample(3, format.SampleRate, sr, s))

In the example above, the original sample rate of the source is format.SampleRate. We want to play it at the speaker's native sample rate and thus we need to resample.

The quality argument specifies the quality of the resampling process. Higher quality implies worse performance. Values below 1 or above 64 are invalid and Resample will panic. Here's a table for deciding which quality to pick.

quality | use case
--------|---------
1       | very high performance, on-the-fly resampling, low quality
3-4     | good performance, on-the-fly resampling, good quality
6       | higher CPU usage, usually not suitable for on-the-fly resampling, very good quality
>6      | even higher CPU usage, for offline resampling, very good quality

Sane quality values are usually below 16. Higher values will consume too much CPU, giving negligible quality improvements.

Resample propagates errors from s.

func ResampleRatio

func ResampleRatio(quality int, ratio float64, s Streamer) *Resampler

ResampleRatio is same as Resample, except it takes the ratio of the old and the new sample rate, specifically, the old sample rate divided by the new sample rate. Aside from correcting the sample rate, this can be used to change the speed of the audio. For example, resampling at the ratio of 2 and playing at the original sample rate will cause doubled speed in playback.

func (*Resampler) Err

func (r *Resampler) Err() error

Err propagates the original Streamer's errors.

func (*Resampler) Ratio

func (r *Resampler) Ratio() float64

Ratio returns the current resampling ratio.

func (*Resampler) SetRatio

func (r *Resampler) SetRatio(ratio float64)

SetRatio sets the resampling ratio. This does not cause any glitches in the stream.

func (*Resampler) Stream

func (r *Resampler) Stream(samples [][2]float64) (n int, ok bool)

Stream streams the original audio resampled according to the current ratio.

type SampleRate

type SampleRate int

SampleRate is the number of samples per second.

func (SampleRate) D

func (sr SampleRate) D(n int) time.Duration

D returns the duration of n samples.

func (SampleRate) N

func (sr SampleRate) N(d time.Duration) int

N returns the number of samples that last for d duration.

type StreamCloser

type StreamCloser interface {
	Streamer

	// Close closes the Streamer and releases it's resources. Streamer will no longer stream any
	// samples.
	Close() error
}

StreamCloser is a Streamer streaming from a resource which needs to be released, such as a file or a network connection.

type StreamSeekCloser

type StreamSeekCloser interface {
	Streamer
	Len() int
	Position() int
	Seek(p int) error
	Close() error
}

StreamSeekCloser is a union of StreamSeeker and StreamCloser.

type StreamSeeker

type StreamSeeker interface {
	Streamer

	// Duration returns the total number of samples of the Streamer.
	Len() int

	// Position returns the current position of the Streamer. This value is between 0 and the
	// total length.
	Position() int

	// Seek sets the position of the Streamer to the provided value.
	//
	// If an error occurs during seeking, the position remains unchanged. This error will not be
	// returned through the Streamer's Err method.
	Seek(p int) error
}

StreamSeeker is a finite duration Streamer which supports seeking to an arbitrary position.

type Streamer

type Streamer interface {
	// Stream copies at most len(samples) next audio samples to the samples slice.
	//
	// The sample rate of the samples is unspecified in general, but should be specified for
	// each concrete Streamer.
	//
	// The value at samples[i][0] is the value of the left channel of the i-th sample.
	// Similarly, samples[i][1] is the value of the right channel of the i-th sample.
	//
	// Stream returns the number of streamed samples. If the Streamer is drained and no more
	// samples will be produced, it returns 0 and false. Stream must not touch any samples
	// outside samples[:n].
	//
	// There are 3 valid return patterns of the Stream method:
	//
	//   1. n == len(samples) && ok
	//
	// Stream streamed all the requested samples. Cases 1, 2 and 3 may occur in the following
	// calls.
	//
	//   2. 0 < n && n < len(samples) && ok
	//
	// Stream streamed n samples and drained the Streamer. Only case 3 may occur in the
	// following calls.
	//
	//   3. n == 0 && !ok
	//
	// The Streamer is drained and no more samples will come. If Err returns a non-nil error, only
	// this case is valid. Only this case may occur in the following calls.
	Stream(samples [][2]float64) (n int, ok bool)

	// Err returns an error which occurred during streaming. If no error occurred, nil is
	// returned.
	//
	// When an error occurs, Streamer must become drained and Stream must return 0, false
	// forever.
	//
	// The reason why Stream doesn't return an error is that it dramatically simplifies
	// programming with Streamer. It's not very important to catch the error right when it
	// happens.
	Err() error
}

Streamer is able to stream a finite or infinite sequence of audio samples.

func Callback

func Callback(f func()) Streamer

Callback returns a Streamer, which does not stream any samples, but instead calls f the first time its Stream method is called. The speaker is locked while f is called.

func Dup

func Dup(s Streamer) (t, u Streamer)

Dup returns two Streamers which both stream the same data as the original s. The two Streamers can't be used concurrently without synchronization.

func Iterate

func Iterate(g func() Streamer) Streamer

Iterate returns a Streamer which successively streams Streamers obtains by calling the provided g function. The streaming stops when g returns nil.

Iterate does not propagate errors from the generated Streamers.

func Loop

func Loop(count int, s StreamSeeker) Streamer

Loop takes a StreamSeeker and plays it count times. If count is negative, s is looped infinitely.

The returned Streamer propagates s's errors.

func Mix

func Mix(s ...Streamer) Streamer

Mix takes zero or more Streamers and returns a Streamer which streams them mixed together.

Mix does not propagate errors from the Streamers.

func Seq

func Seq(s ...Streamer) Streamer

Seq takes zero or more Streamers and returns a Streamer which streams them one by one without pauses.

Seq does not propagate errors from the Streamers.

func Silence deprecated

func Silence(num int) Streamer

Silence returns a Streamer which streams num samples of silence. If num is negative, silence is streamed forever.

Deprecated: beep.Silence has been moved to generators.Silence

func Take

func Take(num int, s Streamer) Streamer

Take returns a Streamer which streams at most num samples from s.

The returned Streamer propagates s's errors through Err.

type StreamerFunc

type StreamerFunc func(samples [][2]float64) (n int, ok bool)

StreamerFunc is a Streamer created by simply wrapping a streaming function (usually a closure, which encloses a time tracking variable). This sometimes simplifies creating new streamers.

Example:

noise := StreamerFunc(func(samples [][2]float64) (n int, ok bool) {
    for i := range samples {
        samples[i][0] = rand.Float64()*2 - 1
        samples[i][1] = rand.Float64()*2 - 1
    }
    return len(samples), true
})

func (StreamerFunc) Err

func (sf StreamerFunc) Err() error

Err always returns nil.

func (StreamerFunc) Stream

func (sf StreamerFunc) Stream(samples [][2]float64) (n int, ok bool)

Stream calls the wrapped streaming function.

Directories

Path Synopsis
Package effects provides additional audio effects for the Beep library.
Package effects provides additional audio effects for the Beep library.
examples
Package flac implements audio data decoding in FLAC format.
Package flac implements audio data decoding in FLAC format.
internal
Package midi implements audio data decoding in MIDI format.
Package midi implements audio data decoding in MIDI format.
Package mp3 implements audio data decoding in MP3 format.
Package mp3 implements audio data decoding in MP3 format.
Package speaker implements playback of beep.Streamer values through physical speakers.
Package speaker implements playback of beep.Streamer values through physical speakers.
Package vorbis implements audio data decoding in oggvorbis format.
Package vorbis implements audio data decoding in oggvorbis format.
Package wav implements audio data decoding and encoding in WAVE format.
Package wav implements audio data decoding and encoding in WAVE format.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL