2021SC@SDUSC
Catalog
1. Preface
1. Description
audio description document address
audio package - github.com/hajimehoshi/ebiten/v2/audio - pkg.go.dev
All screenshots and code in this article are from Description Documentation Or ebiten source file
The author is responsible for audio Audio-related code analysis
2.ebiten package directory
3. Summary
Analysis audioinfiniteloop An implementation of an infinite audio loop (example in ebiten source)
file location
Code Appearance
This "game" inherits run.go Game Structures and Methods in
// game's Update function is called every tick to update the game logic.
Update method is invoked for each frame, default 60 frames TPS = 60
// game's Draw function is called every frame to draw the screen.
The Draw method draws interface elements, and ebiten sees everything as a picture
// game's Layout function is called when necessary, and you can specify the logical screen size by the function.
A proportional relationship between the size of a program box and the size of an internal screen
* From run.go File Method Comments
2. Infinite Loop Audio
1. Package
package main
Represents that this file belongs to the main package, the main method can only be in the main package
2. Introducing packages
The next few rows use the relative path of the package because the go mod package management is used
The compiler looks for packages in GOPATH and GOROOT
The last line is renamed raudio
Similar
import ( _ " " )
Introduce no-use methods only (go must be used by default)
import ( . " " )
Method full copy introduction (less common, risk of duplication)
3. Start with main()
func main() { ebiten.SetWindowSize(screenWidth, screenHeight) ebiten.SetWindowTitle("Audio Infinite Loop (Ebiten Demo)") if err := ebiten.RunGame(&Game{}); err != nil { log.Fatal(err) } }
The first is to call the SetWindowSize(,) method in ebiten to set the window size
The parameter passed in is a global constant
Then the SetWindowTitle() method sets the title of the window
The effect is shown in the diagram
Last run this game". RunGame() method has only one process
If an error occurs, it terminates and logs
(Methods such as RunGame() will be specifically analyzed later)
4.Layout method
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { return screenWidth, screenHeight }
Layout method to set the window size, specific operations not found, next week and analysis of ui students to exchange
5.Update logic
func (g *Game) Update() error {
//This program only needs one player, which is a restriction statement and passes only once at the beginning
if g.player != nil { return nil }
//Create an audio environment (audioContext) at the sampling frequency (constant sampleRate = 22050)
//Audio environment to create a Player
if g.audioContext == nil { g.audioContext = audio.NewContext(sampleRate) }
//Decode the Ogg file (raudio.Ragtime_ogg) according to the sampling frequency of the audio environment
//oggs is both a decoded stream reader and a stream shutdown as well as a stream locator
// Decode an Ogg file. // oggS is a decoded io.ReadCloser and io.Seeker. oggS, err := vorbis.Decode(g.audioContext, bytes.NewReader(raudio.Ragtime_ogg)) if err != nil { return err }
//Create an infinite loop with decoded oggs
//Incoming Parameter Introduction Length and Loop Length, Seconds is Constant, *4 Cause: 16 bits Dual Channel /> 2 bytes * 2 Channels
// Create an infinite loop stream from the decoded bytes. // s is still an io.ReadCloser and io.Seeker. s := audio.NewInfiniteLoopWithIntro(oggS, introLengthInSecond*4*sampleRate, loopLengthInSecond*4*sampleRate)
//New Player
//Start the player
g.player, err = g.audioContext.NewPlayer(s) if err != nil { return err } // Play the infinite-length stream. This never ends. g.player.Play() return nil }
6.Draw drawing interface
Figure
//Get the effect after the Current decimal point in the figure above
func (g *Game) Draw(screen *ebiten.Image) { pos := g.player.Current() if pos > 5*time.Second { pos = (g.player.Current()-5*time.Second)%(4*time.Second) + 5*time.Second }
//Format String
msg := fmt.Sprintf(`TPS: %0.2f This is an example using audio.NewInfiniteLoopWithIntro. Intro: 0[s] - %[2]d[s] Loop: %[2]d[s] - %[3]d[s] Current: %0.2[4]f[s]`, ebiten.CurrentTPS(), introLengthInSecond, introLengthInSecond+loopLengthInSecond, float64(pos)/float64(time.Second)) // DebugPrint draws the string str on the image on left top corner. ebitenutil.DebugPrint(screen, msg) }
7. Running results
Audio for 9 seconds
Play first 5 seconds, then 4 seconds after infinite loop
Set lines 2 to 3 to the bottom of the figure below
Current from 0.00 //> 8.99
Current Loops Infinitely from 5.00 /> 8.99
8. Summary
- The core method in this example is the overridden Update() method
- Play Step 1: Generate an audio environment based on the sampling frequency
g.audioContext = audio.NewContext(sampleRate)
- Step 2: Decode and name the audio file in the above audio environment
oggS, err := vorbis.Decode(g.audioContext, bytes.NewReader(raudio.Ragtime_ogg)) if err != nil { return err }
- Step 3: Create an infinite loop io.Reader with the decoded variables, the length of the introduction, and the length of the loop
s := audio.NewInfiniteLoopWithIntro(oggS, introLengthInSecond*4*sampleRate, loopLengthInSecond*4*sampleRate)
- Step 4: Create a player with step 3 io.Reader in the above audio environment
g.player, err = g.audioContext.NewPlayer(s) if err != nil { return err }
- Step 5: Play() method is called by the player
g.player.Play()
3. Ending
1. Difficulties
This is the initial understanding of audio and a simple process to get familiar with ebiten.
Some of them are not easy to analyze. The methods used in the example dig in one layer at a time, involving the structure, inheritance, overloading, etc. in the go language. Others are not clear, such as
What is &Game{}?
When is the Layout() method called?
What does bitDepthInBytes = 2 mean?
Audio environment, what is the logic behind the player?
2. Next time
Next week, learn the logic behind it, learn how go inherits, and write a few demo implementations.