mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-27 04:08:53 +01:00
fe4f96e261
Updates #1779
135 lines
4.4 KiB
Go
135 lines
4.4 KiB
Go
// Copyright 2021 The Ebiten Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package readerdriver
|
|
|
|
import (
|
|
"io"
|
|
)
|
|
|
|
// Context is the main object in Oto. It interacts with the audio drivers.
|
|
//
|
|
// To play sound with Oto, first create a context. Then use the context to create
|
|
// an arbitrary number of players. Then use the players to play sound.
|
|
//
|
|
// There can only be one context at any time. Closing a context and opening a new one is allowed.
|
|
type Context struct {
|
|
context *context
|
|
}
|
|
|
|
// NewPlayer creates a new, ready-to-use Player belonging to the Context.
|
|
//
|
|
// The r's format is as follows:
|
|
// [data] = [sample 1] [sample 2] [sample 3] ...
|
|
// [sample *] = [channel 1] ...
|
|
// [channel *] = [byte 1] [byte 2] ...
|
|
// Byte ordering is little endian.
|
|
//
|
|
// A player has some amount of an underlying buffer.
|
|
// Read data from r is queued to the player's underlying buffer.
|
|
// The underlying buffer is consumed by its playing.
|
|
// Then, r's position and the current playing position don't necessarily match.
|
|
// If you want to clear the underlying buffer for some reasons e.g., you want to seek the position of r,
|
|
// call the player's Reset function.
|
|
//
|
|
// You cannot share r by multiple players.
|
|
func (c *Context) NewPlayer(r io.Reader) Player {
|
|
return c.context.NewPlayer(r)
|
|
}
|
|
|
|
// Suspend suspends the entire audio play.
|
|
func (c *Context) Suspend() error {
|
|
return c.context.Suspend()
|
|
}
|
|
|
|
// Resume resumes the entire audio play, which was suspended by Suspend.
|
|
func (c *Context) Resume() error {
|
|
return c.context.Resume()
|
|
}
|
|
|
|
// NewContext creates a new context, that creates and holds ready-to-use Player objects,
|
|
// and returns a context, a channel that is closed when the context is ready, and an error if it exists.
|
|
//
|
|
// The sampleRate argument specifies the number of samples that should be played during one second.
|
|
// Usual numbers are 44100 or 48000.
|
|
//
|
|
// The channelNum argument specifies the number of channels. One channel is mono playback. Two
|
|
// channels are stereo playback. No other values are supported.
|
|
//
|
|
// The bitDepthInBytes argument specifies the number of bytes per sample per channel. The usual value
|
|
// is 2. Only values 1 and 2 are supported.
|
|
func NewContext(sampleRate int, channelNum int, bitDepthInBytes int) (*Context, chan struct{}, error) {
|
|
ctx, ready, err := newContext(sampleRate, channelNum, bitDepthInBytes)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return &Context{context: ctx}, ready, nil
|
|
}
|
|
|
|
// Player is a PCM (pulse-code modulation) audio player.
|
|
type Player interface {
|
|
// Pause pauses its playing.
|
|
Pause()
|
|
|
|
// Play starts its playing if it doesn't play.
|
|
Play()
|
|
|
|
// IsPlaying reports whether this player is playing.
|
|
IsPlaying() bool
|
|
|
|
// Reset clears the underyling buffer and pauses its playing.
|
|
Reset()
|
|
|
|
// Volume returns the current volume in between [0, 1].
|
|
// The default volume is 1.
|
|
Volume() float64
|
|
|
|
// SetVolume sets the current volume in between [0, 1].
|
|
SetVolume(volume float64)
|
|
|
|
// UnplayedBufferSize returns the byte size in the underlying buffer that is not played yet.
|
|
UnplayedBufferSize() int
|
|
|
|
// Err returns an error if this player has an error.
|
|
Err() error
|
|
|
|
io.Closer
|
|
}
|
|
|
|
type playerState int
|
|
|
|
const (
|
|
playerPaused playerState = iota
|
|
playerPlay
|
|
playerClosed
|
|
)
|
|
|
|
// TODO: The term 'buffer' is confusing. Name each buffer with good terms.
|
|
|
|
// oneBufferSize returns the size of one buffer in the player implementation.
|
|
func (c *context) oneBufferSize() int {
|
|
bytesPerSample := c.channelNum * c.bitDepthInBytes
|
|
s := c.sampleRate * bytesPerSample / 4
|
|
|
|
// Align s in multiples of bytes per sample, or a buffer could have extra bytes.
|
|
return s / bytesPerSample * bytesPerSample
|
|
}
|
|
|
|
// maxBufferSize returns the maximum size of the buffer for the audio source.
|
|
// This buffer is used when unreading on pausing the player.
|
|
func (c *context) maxBufferSize() int {
|
|
// The number of underlying buffers should be 2.
|
|
return c.oneBufferSize() * 2
|
|
}
|