Documentation ¶
Index ¶
- Variables
- func GetSampleAsF64(buffer []byte) (float64, float64)
- func GetSampleAsI16(buffer []byte) (int16, int16)
- func InterpHermite4Pt3Ord(samples []float64, x float64) float64
- func InterpHermite6Pt3Ord(samples []float64, x float64) float64
- func InterpLagrange4Pt3Ord(samples []float64, x float64) float64
- func InterpLagrange6Pt5Ord(samples []float64, x float64) float64
- func InterpLagrangeN(samples []float64, targetPosition float64) float64
- func NormalizeF64(value float64) float64
- func StoreF64SampleAsL16(buffer []byte, left, right float64)
- func StoreL16Sample(buffer []byte, left int16, right int16)
- func StoreNormF64SampleAsL16(buffer []byte, left, right float64)
- type InterpolatorFunc
- type Looper
- func (self *Looper) AdjustLoop(loopStart, loopEnd int64)
- func (self *Looper) GetLoopEnd() int64
- func (self *Looper) GetLoopPoints() (int64, int64)
- func (self *Looper) GetLoopStart() int64
- func (self *Looper) GetPosition() int64
- func (self *Looper) Length() int64
- func (self *Looper) Read(buffer []byte) (int, error)
- func (self *Looper) Seek(offset int64, whence int) (int64, error)
- type SpeedShifter
- type StdAudioStream
Constants ¶
This section is empty.
Variables ¶
var ErrAudioContextUninitialized = errors.New("Ebitengine's audio context not initialized")
Returned by functions that require Ebitengine's audio.NewContext to have already been created, typically so the sample rate can be directly obtained from it with audio.CurrentContext().SampleRate().
Functions ¶
func GetSampleAsF64 ¶
Reads the first 4 bytes from the given slice and converts them from L16, 2 channel, little-endian format to 2 channel float64 values in the [-1, 1] range. Will panic if len(buffer) < 4.
func GetSampleAsI16 ¶
Reads the first 4 bytes from the given slice (the first sample) and returns the left and right channel values. Results fall in the [-32768, 32767] range. Will panic if len(buffer) < 4.
func InterpHermite4Pt3Ord ¶
4-point, 3rd-order Hermite interpolation. Samples are considered to start at zero. x is the position at which we want to interpolate. For best results, x should be between 1.0 and 2.0.
len(samples) must be at least 4.
func InterpHermite6Pt3Ord ¶
6-point, 3rd-order Hermite interpolation. Samples are considered to start at zero. x is the position at which we want to interpolate. For best results, x should be between 2.0 and 3.0.
len(samples) must be at least 6.
func InterpLagrange4Pt3Ord ¶
4-point, 3rd-order Lagrange interpolation. Samples are considered to start at zero. x is the position at which we want to interpolate. For best results, x should be between 1.0 and 2.0.
len(samples) must be at least 4.
func InterpLagrange6Pt5Ord ¶
6-point, 5th-order Lagrange interpolation. Samples are considered to start at zero. x is the position at which we want to interpolate. For best results, x should be between 2.0 and 3.0.
len(samples) must be at least 6.
func InterpLagrangeN ¶
Lagrange interpolation for N samples. Samples are considered to start at zero, and targetPosition must be an index near the middle of samples' slice length for best results. This function is slow; for faster interpolation use one of the fixed-N functions instead.
func NormalizeF64 ¶
Normalize a float64 value from [-32768, 32767] to [-1, 1].
func StoreF64SampleAsL16 ¶
Stores the given unnormalized ([-32768, 32767]) values as a L16, 2 channel, little-endian sample right at the start of the given slice. Values out of range will be clipped. Will panic if len(buffer) < 4.
func StoreL16Sample ¶
Stores the given values as a L16, 2 channel, little-endian sample right at the start of the given slice. Will panic if len(buffer) < 4.
func StoreNormF64SampleAsL16 ¶
Stores the given normalized ([-1, 1]) values as a L16, 2 channel, little-endian sample right at the start of the given slice. Values out of range will be clipped. Will panic if len(buffer) < 4.
Types ¶
type InterpolatorFunc ¶
An interpolator function receives a slice of values, the position at which we want to interpolate, and returns the interpolated value.
Positions to interpolate must always be within 0 <= position <= len(samples) - 1. Responsible callers will try to keep it as close to (len(samples) - 1)/2 as possible.
Interpolation functions are mainly used for resampling processes. See InterpLagrangeN, InterpLagrange4Pt3Ord, InterpLagrange6Pt5Ord, InterpHermite4Pt3Ord, InterpHermite6Pt3Ord.
type Looper ¶
type Looper struct {
// contains filtered or unexported fields
}
A tight audio looper. Unlike Ebitengine's infinite looper, this looper doesn't require padding after the end point because it doesn't perform any blending during the transition. Additionally, the start and end points can be changed at any time with Looper.AdjustLoop.
func NewLooper ¶
func NewLooper(stream io.ReadSeeker, loopStart int64, loopEnd int64) *Looper
Creates a new tight Looper.
The stream must be a L16 little-endian stream with two channels (Ebitengine's default audio format). loopStart and loopEnd must be multiples of 4, and loopStart must be strictly smaller than loopEnd. This method will panic if any of those are not respected.
The loopEnd point is not itself included in the loop. For example, to play a full audio stream in a loop, you would use NewLooper(stream, 0, stream.Length()).
If you need help to determine the loop start and end points, see apps/loop_finder.
func (*Looper) AdjustLoop ¶
Sets new values for the loop starting and ending points. The values are []byte indices. Therefore, since Ebitengine audio samples require 4 bytes each, the passed start and end points must also be multiples of 4.
If the new loop end is set before the current playback position, the loop will continue playing until the previously configured end point before the new loop comes into effect.
func (*Looper) GetLoopEnd ¶
Returns the currently configured loop ending point (in bytes, not samples).
func (*Looper) GetLoopPoints ¶
Like Looper.GetLoopStart and Looper.GetLoopEnd, but both at once.
func (*Looper) GetLoopStart ¶
Returns the currently configured loop starting point (in bytes, not samples).
func (*Looper) GetPosition ¶
Returns the current playback position. The value will always be multiple of 4, as in Ebitengine each sample is composed of 4 bytes.
func (*Looper) Length ¶
Returns the underlying stream's length. The underlying stream must have a Length() int64 method or be a bytes.Reader. This method will panic otherwise.
type SpeedShifter ¶
type SpeedShifter struct {
// contains filtered or unexported fields
}
A SpeedShifter wraps an audio stream and allows playing it at a different speed than the original by resampling in real-time.
Valid speed shifters can only be created through NewDefaultSpeedShifter or NewSpeedShifter.
func NewDefaultSpeedShifter ¶
func NewDefaultSpeedShifter(source io.Reader) *SpeedShifter
Creates a default SpeedShifter, which uses a 6-point Hermite interpolator for the resampling. For custom interpolators, see NewSpeedShifter instead.
The initial playback speed is 1.0.
func NewSpeedShifter ¶
func NewSpeedShifter(source io.Reader, speed float64, windowSize int, interpolator InterpolatorFunc) *SpeedShifter
Creates a new SpeedShifter with a custom speed, window size and interpolator. If you do not want to worry about interpolators and resampling, see NewDefaultSpeedShifter instead.
The interpolator's windowSize must be multiple of 2.
func (*SpeedShifter) Read ¶
func (self *SpeedShifter) Read(buffer []byte) (int, error)
Implements io.Reader. This function will always try to fill the buffer as much as possible, even if this requires multiple reads on the underlying stream.
The returned read length will always also be multiple of 4, aligning to Ebitengine's sample size.
func (*SpeedShifter) Seek ¶
func (self *SpeedShifter) Seek(offset int64, whence int) (int64, error)
Implements io.Seeker, with the limitation that io.SeekCurrent seeks are not supported (unless the seek has an offset of 0, which is sometimes used to get the current playback position).
You may use Seek to rewind and start playing after stoping, but not to loop or do seamless seeking with the resampled stream itself. Seamless seeking could only be done correctly if notifying the seek in advance of the interpolation window. That's not something anyone sane wants to figure out, so seeking will seek on the underlying buffer but reset the internal interpolation window of the speed shifter.
This method panics if the underlying source doesn't implement io.Seeker.
func (*SpeedShifter) SetSpeed ¶
func (self *SpeedShifter) SetSpeed(speed float64)
Sets the playback speed. Notice that the Ebitengine's player buffer size can cause the change to take a while to become audible. See Ebitengine's Player.SetBufferSize if you want to reduce latency. 20 milliseconds are reasonable for most desktop environments, while browsers often have trouble when pushed below 50 milliseconds. It also depends a lot on how much processing and effects you are adding to the audio.
func (*SpeedShifter) Speed ¶
func (self *SpeedShifter) Speed() float64
Returns the currently configured playback speed.
type StdAudioStream ¶
type StdAudioStream interface { io.ReadSeeker Length() int64 }
A common interface that all Ebitengine audio streams conform to.
func LoadAudioFileAsStream ¶
func LoadAudioFileAsStream(filename string) (StdAudioStream, error)
Loads an .ogg, .mp3 or .wav file as a StdAudioStream. Additionally, the returned interface also implements io.Closer, which can be used to close the file associated to the stream, e.g.:
err := audioStream.(io.Closer).Close()
The sample rate used is taken from Ebitengine's audio.CurrentContext(). If no audio context has been initialized, ErrAudioContextUninitialized will be returned.