audio.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. // Copyright 2015 Hajime Hoshi
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package audio provides audio players.
  15. //
  16. // The stream format must be 16-bit little endian or 32-bit float little endian, and 2 channels. The format is as follows:
  17. //
  18. // [data] = [sample 1] [sample 2] [sample 3] ...
  19. // [sample *] = [channel 1] ...
  20. // [channel *] = [byte 1] [byte 2] ...
  21. //
  22. // An audio context (audio.Context object) has a sample rate you can specify
  23. // and all streams you want to play must have the same sample rate.
  24. //
  25. // An audio context can generate 'players' (audio.Player objects),
  26. // and you can play sound by calling Play function of players.
  27. // When multiple players play, mixing is automatically done.
  28. // Note that too many players may cause distortion.
  29. //
  30. // For the simplest example to play sound, see wav package in the examples.
  31. package audio
  32. import (
  33. "bytes"
  34. "errors"
  35. "fmt"
  36. "io"
  37. "reflect"
  38. "runtime"
  39. "sync"
  40. "time"
  41. "github.com/hajimehoshi/ebiten/v2/audio/internal/convert"
  42. "github.com/hajimehoshi/ebiten/v2/internal/hook"
  43. )
  44. const (
  45. channelCount = 2
  46. bitDepthInBytesInt16 = 2
  47. bitDepthInBytesFloat32 = 4
  48. )
  49. // A Context represents a current state of audio.
  50. //
  51. // At most one Context object can exist in one process.
  52. // This means only one constant sample rate is valid in your one application.
  53. //
  54. // For a typical usage example, see examples/wav/main.go.
  55. type Context struct {
  56. playerFactory *playerFactory
  57. sampleRate int
  58. err error
  59. ready bool
  60. playingPlayers map[*playerImpl]struct{}
  61. m sync.Mutex
  62. semaphore chan struct{}
  63. }
  64. var (
  65. theContext *Context
  66. theContextLock sync.Mutex
  67. )
  68. // NewContext creates a new audio context with the given sample rate.
  69. //
  70. // sampleRate specifies the number of samples that should be played during one second.
  71. // Usual numbers are 44100 or 48000. One context has only one sample rate. You cannot play multiple audio
  72. // sources with different sample rates at the same time.
  73. //
  74. // NewContext panics when an audio context is already created.
  75. func NewContext(sampleRate int) *Context {
  76. theContextLock.Lock()
  77. defer theContextLock.Unlock()
  78. if theContext != nil {
  79. panic("audio: context is already created")
  80. }
  81. c := &Context{
  82. sampleRate: sampleRate,
  83. playerFactory: newPlayerFactory(sampleRate),
  84. playingPlayers: map[*playerImpl]struct{}{},
  85. semaphore: make(chan struct{}, 1),
  86. }
  87. theContext = c
  88. h := getHook()
  89. h.OnSuspendAudio(func() error {
  90. c.semaphore <- struct{}{}
  91. if err := c.playerFactory.suspend(); err != nil {
  92. return err
  93. }
  94. if err := c.onSuspend(); err != nil {
  95. return err
  96. }
  97. return nil
  98. })
  99. h.OnResumeAudio(func() error {
  100. <-c.semaphore
  101. if err := c.playerFactory.resume(); err != nil {
  102. return err
  103. }
  104. if err := c.onResume(); err != nil {
  105. return err
  106. }
  107. return nil
  108. })
  109. h.AppendHookOnBeforeUpdate(func() error {
  110. var err error
  111. theContextLock.Lock()
  112. if theContext != nil {
  113. err = theContext.error()
  114. }
  115. theContextLock.Unlock()
  116. if err != nil {
  117. return err
  118. }
  119. // Initialize the context here in the case when there is no player and
  120. // the program waits for IsReady() to be true (#969, #970, #2715).
  121. ready, err := c.playerFactory.initContextIfNeeded()
  122. if err != nil {
  123. return err
  124. }
  125. if ready != nil {
  126. go func() {
  127. <-ready
  128. c.setReady()
  129. }()
  130. }
  131. if err := c.updatePlayers(); err != nil {
  132. return err
  133. }
  134. return nil
  135. })
  136. return c
  137. }
  138. // CurrentContext returns the current context or nil if there is no context.
  139. func CurrentContext() *Context {
  140. theContextLock.Lock()
  141. c := theContext
  142. theContextLock.Unlock()
  143. return c
  144. }
  145. func (c *Context) setError(err error) {
  146. // TODO: What if c.err already exists?
  147. c.m.Lock()
  148. c.err = err
  149. c.m.Unlock()
  150. }
  151. func (c *Context) error() error {
  152. c.m.Lock()
  153. defer c.m.Unlock()
  154. if c.err != nil {
  155. return c.err
  156. }
  157. return c.playerFactory.error()
  158. }
  159. func (c *Context) setReady() {
  160. c.m.Lock()
  161. c.ready = true
  162. c.m.Unlock()
  163. }
  164. func (c *Context) addPlayingPlayer(p *playerImpl) {
  165. c.m.Lock()
  166. defer c.m.Unlock()
  167. c.playingPlayers[p] = struct{}{}
  168. if !reflect.ValueOf(p.sourceIdent()).Comparable() {
  169. return
  170. }
  171. // Check the source duplication
  172. srcs := map[any]struct{}{}
  173. for p := range c.playingPlayers {
  174. if _, ok := srcs[p.sourceIdent()]; ok {
  175. c.err = errors.New("audio: the same source must not be used by multiple Player objects")
  176. return
  177. }
  178. srcs[p.sourceIdent()] = struct{}{}
  179. }
  180. }
  181. func (c *Context) removePlayingPlayer(p *playerImpl) {
  182. c.m.Lock()
  183. delete(c.playingPlayers, p)
  184. c.m.Unlock()
  185. }
  186. func (c *Context) onSuspend() error {
  187. // A Context must not call playerImpl's functions with a lock, or this causes a deadlock (#2737).
  188. // Copy the playerImpls and iterate them without a lock.
  189. var players []*playerImpl
  190. c.m.Lock()
  191. players = make([]*playerImpl, 0, len(c.playingPlayers))
  192. for p := range c.playingPlayers {
  193. players = append(players, p)
  194. }
  195. c.m.Unlock()
  196. for _, p := range players {
  197. if err := p.Err(); err != nil {
  198. return err
  199. }
  200. p.onContextSuspended()
  201. }
  202. return nil
  203. }
  204. func (c *Context) onResume() error {
  205. // A Context must not call playerImpl's functions with a lock, or this causes a deadlock (#2737).
  206. // Copy the playerImpls and iterate them without a lock.
  207. var players []*playerImpl
  208. c.m.Lock()
  209. players = make([]*playerImpl, 0, len(c.playingPlayers))
  210. for p := range c.playingPlayers {
  211. players = append(players, p)
  212. }
  213. c.m.Unlock()
  214. for _, p := range players {
  215. if err := p.Err(); err != nil {
  216. return err
  217. }
  218. p.onContextResumed()
  219. }
  220. return nil
  221. }
  222. func (c *Context) updatePlayers() error {
  223. // A Context must not call playerImpl's functions with a lock, or this causes a deadlock (#2737).
  224. // Copy the playerImpls and iterate them without a lock.
  225. var players []*playerImpl
  226. c.m.Lock()
  227. players = make([]*playerImpl, 0, len(c.playingPlayers))
  228. for p := range c.playingPlayers {
  229. players = append(players, p)
  230. }
  231. c.m.Unlock()
  232. var playersToRemove []*playerImpl
  233. // Now reader players cannot call removePlayers from themselves in the current implementation.
  234. // Underlying playering can be the pause state after fishing its playing,
  235. // but there is no way to notify this to players so far.
  236. // Instead, let's check the states proactively every frame.
  237. for _, p := range players {
  238. if err := p.Err(); err != nil {
  239. return err
  240. }
  241. p.updatePosition()
  242. if !p.IsPlaying() {
  243. playersToRemove = append(playersToRemove, p)
  244. }
  245. }
  246. c.m.Lock()
  247. for _, p := range playersToRemove {
  248. delete(c.playingPlayers, p)
  249. }
  250. c.m.Unlock()
  251. return nil
  252. }
  253. // IsReady returns a boolean value indicating whether the audio is ready or not.
  254. //
  255. // On some browsers, user interaction like click or pressing keys is required to start audio.
  256. func (c *Context) IsReady() bool {
  257. c.m.Lock()
  258. defer c.m.Unlock()
  259. return c.ready
  260. }
  261. // SampleRate returns the sample rate.
  262. func (c *Context) SampleRate() int {
  263. return c.sampleRate
  264. }
  265. // Player is an audio player which has one stream.
  266. //
  267. // Even when all references to a Player object is gone,
  268. // the object is not GCed until the player finishes playing.
  269. // This means that if a Player plays an infinite stream,
  270. // the object is never GCed unless Close is called.
  271. type Player struct {
  272. p *playerImpl
  273. }
  274. // NewPlayer creates a new player with the given stream.
  275. //
  276. // src's format must be linear PCM (signed 16bits little endian, 2 channel stereo)
  277. // without a header (e.g. RIFF header).
  278. // The sample rate must be same as that of the audio context.
  279. //
  280. // The player is seekable when src is io.Seeker.
  281. // Attempt to seek the player that is not io.Seeker causes panic.
  282. //
  283. // Note that the given src can't be shared with other Player objects.
  284. //
  285. // NewPlayer tries to call Seek of src to get the current position.
  286. // NewPlayer returns error when the Seek returns error.
  287. //
  288. // A Player doesn't close src even if src implements io.Closer.
  289. // Closing the source is src owner's responsibility.
  290. //
  291. // For new code, NewPlayerF32 is preferrable to NewPlayer, since Ebitengine will treat only 32bit float audio internally in the future.
  292. //
  293. // A Player for 16bit integer must be used with 16bit integer version of audio APIs, like vorbis.DecodeWithoutResampling or audio.NewInfiniteLoop, not or vorbis.DecodeF32 or audio.NewInfiniteLoopF32.
  294. func (c *Context) NewPlayer(src io.Reader) (*Player, error) {
  295. _, seekable := src.(io.Seeker)
  296. f32Src := convert.NewFloat32BytesReaderFromInt16BytesReader(src)
  297. pi, err := c.playerFactory.newPlayer(c, f32Src, seekable, src, bitDepthInBytesFloat32)
  298. if err != nil {
  299. return nil, err
  300. }
  301. p := &Player{pi}
  302. runtime.SetFinalizer(p, (*Player).finalize)
  303. return p, nil
  304. }
  305. // NewPlayerF32 creates a new player with the given stream.
  306. //
  307. // src's format must be linear PCM (32bit float, little endian, 2 channel stereo)
  308. // without a header (e.g. RIFF header).
  309. // The sample rate must be same as that of the audio context.
  310. //
  311. // The player is seekable when src is io.Seeker.
  312. // Attempt to seek the player that is not io.Seeker causes panic.
  313. //
  314. // Note that the given src can't be shared with other Player objects.
  315. //
  316. // NewPlayerF32 tries to call Seek of src to get the current position.
  317. // NewPlayerF32 returns error when the Seek returns error.
  318. //
  319. // A Player doesn't close src even if src implements io.Closer.
  320. // Closing the source is src owner's responsibility.
  321. //
  322. // For new code, NewPlayerF32 is preferrable to NewPlayer, since Ebitengine will treat only 32bit float audio internally in the future.
  323. //
  324. // A Player for 32bit float must be used with 32bit float version of audio APIs, like vorbis.DecodeF32 or audio.NewInfiniteLoopF32, not vorbis.DecodeWithoutResampling or audio.NewInfiniteLoop.
  325. func (c *Context) NewPlayerF32(src io.Reader) (*Player, error) {
  326. _, seekable := src.(io.Seeker)
  327. pi, err := c.playerFactory.newPlayer(c, src, seekable, src, bitDepthInBytesFloat32)
  328. if err != nil {
  329. return nil, err
  330. }
  331. p := &Player{pi}
  332. runtime.SetFinalizer(p, (*Player).finalize)
  333. return p, nil
  334. }
  335. // NewPlayer creates a new player with the given stream.
  336. //
  337. // Deprecated: as of v2.2. Use (*Context).NewPlayer instead.
  338. func NewPlayer(context *Context, src io.Reader) (*Player, error) {
  339. return context.NewPlayer(src)
  340. }
  341. // NewPlayerFromBytes creates a new player with the given bytes.
  342. //
  343. // As opposed to NewPlayer, you don't have to care if src is already used by another player or not.
  344. // src can be shared by multiple players.
  345. //
  346. // The format of src should be same as noted at NewPlayer.
  347. func (c *Context) NewPlayerFromBytes(src []byte) *Player {
  348. p, err := c.NewPlayer(bytes.NewReader(src))
  349. if err != nil {
  350. // Errors should never happen.
  351. panic(fmt.Sprintf("audio: %v at NewPlayerFromBytes", err))
  352. }
  353. return p
  354. }
  355. // NewPlayerF32FromBytes creates a new player with the given bytes.
  356. //
  357. // As opposed to NewPlayerF32, you don't have to care if src is already used by another player or not.
  358. // src can be shared by multiple players.
  359. //
  360. // The format of src should be same as noted at NewPlayerF32.
  361. func (c *Context) NewPlayerF32FromBytes(src []byte) *Player {
  362. p, err := c.NewPlayerF32(bytes.NewReader(src))
  363. if err != nil {
  364. // Errors should never happen.
  365. panic(fmt.Sprintf("audio: %v at NewPlayerFromBytesF32", err))
  366. }
  367. return p
  368. }
  369. // NewPlayerFromBytes creates a new player with the given bytes.
  370. //
  371. // Deprecated: as of v2.2. Use (*Context).NewPlayerFromBytes instead.
  372. func NewPlayerFromBytes(context *Context, src []byte) *Player {
  373. return context.NewPlayerFromBytes(src)
  374. }
  375. func (p *Player) finalize() {
  376. runtime.SetFinalizer(p, nil)
  377. if !p.IsPlaying() {
  378. _ = p.Close()
  379. }
  380. }
  381. // Close closes the stream.
  382. //
  383. // When Close is called, the stream owned by the player is NOT closed,
  384. // even if the stream implements io.Closer.
  385. //
  386. // Close returns error when the player is already closed.
  387. func (p *Player) Close() error {
  388. return p.p.Close()
  389. }
  390. // Play plays the stream.
  391. func (p *Player) Play() {
  392. p.p.Play()
  393. }
  394. // IsPlaying returns boolean indicating whether the player is playing.
  395. func (p *Player) IsPlaying() bool {
  396. return p.p.IsPlaying()
  397. }
  398. // Rewind rewinds the current position to the start.
  399. //
  400. // The passed source to NewPlayer must be io.Seeker, or Rewind panics.
  401. //
  402. // Rewind returns error when seeking the source stream returns error.
  403. func (p *Player) Rewind() error {
  404. return p.p.Rewind()
  405. }
  406. // SetPosition sets the position with the given offset.
  407. //
  408. // The passed source to NewPlayer must be io.Seeker, or SetPosition panics.
  409. //
  410. // SetPosition returns error when seeking the source stream returns an error.
  411. func (p *Player) SetPosition(offset time.Duration) error {
  412. return p.p.SetPosition(offset)
  413. }
  414. // Seek seeks the position with the given offset.
  415. //
  416. // Deprecated: as of v2.6. Use SetPosition instead.
  417. func (p *Player) Seek(offset time.Duration) error {
  418. return p.SetPosition(offset)
  419. }
  420. // Pause pauses the playing.
  421. func (p *Player) Pause() {
  422. p.p.Pause()
  423. }
  424. // Position returns the current position in time.
  425. //
  426. // As long as the player continues to play, Position's returning value is increased monotonically,
  427. // even though the source stream loops and its position goes back.
  428. func (p *Player) Position() time.Duration {
  429. return p.p.Position()
  430. }
  431. // Current returns the current position in time.
  432. //
  433. // Deprecated: as of v2.6. Use Position instead.
  434. func (p *Player) Current() time.Duration {
  435. return p.Position()
  436. }
  437. // Volume returns the current volume of this player [0-1].
  438. func (p *Player) Volume() float64 {
  439. return p.p.Volume()
  440. }
  441. // SetVolume sets the volume of this player.
  442. // volume must be in between 0 and 1. SetVolume panics otherwise.
  443. func (p *Player) SetVolume(volume float64) {
  444. p.p.SetVolume(volume)
  445. }
  446. // SetBufferSize adjusts the buffer size of the player.
  447. // If 0 is specified, the default buffer size is used.
  448. // A small buffer size is useful if you want to play a real-time PCM for example.
  449. // Note that the audio quality might be affected if you modify the buffer size.
  450. func (p *Player) SetBufferSize(bufferSize time.Duration) {
  451. p.p.SetBufferSize(bufferSize)
  452. }
  453. type hooker interface {
  454. OnSuspendAudio(f func() error)
  455. OnResumeAudio(f func() error)
  456. AppendHookOnBeforeUpdate(f func() error)
  457. }
  458. var hookerForTesting hooker
  459. func getHook() hooker {
  460. if hookerForTesting != nil {
  461. return hookerForTesting
  462. }
  463. return &hookerImpl{}
  464. }
  465. type hookerImpl struct{}
  466. func (h *hookerImpl) OnSuspendAudio(f func() error) {
  467. hook.OnSuspendAudio(f)
  468. }
  469. func (h *hookerImpl) OnResumeAudio(f func() error) {
  470. hook.OnResumeAudio(f)
  471. }
  472. func (h *hookerImpl) AppendHookOnBeforeUpdate(f func() error) {
  473. hook.AppendHookOnBeforeUpdate(f)
  474. }
  475. // Resample converts the sample rate of the given singed 16bit integer, little-endian, 2 channels (stereo) stream.
  476. // size is the length of the source stream in bytes.
  477. // from is the original sample rate.
  478. // to is the target sample rate.
  479. //
  480. // If the original sample rate equals to the new one, Resample returns source as it is.
  481. func Resample(source io.ReadSeeker, size int64, from, to int) io.ReadSeeker {
  482. if from == to {
  483. return source
  484. }
  485. return convert.NewResampling(source, size, from, to, bitDepthInBytesInt16)
  486. }
  487. // ResampleF32 converts the sample rate of the given 32bit float, little-endian, 2 channels (stereo) stream.
  488. // size is the length of the source stream in bytes.
  489. // from is the original sample rate.
  490. // to is the target sample rate.
  491. //
  492. // If the original sample rate equals to the new one, Resample returns source as it is.
  493. func ResampleF32(source io.ReadSeeker, size int64, from, to int) io.ReadSeeker {
  494. if from == to {
  495. return source
  496. }
  497. return convert.NewResampling(source, size, from, to, bitDepthInBytesFloat32)
  498. }