2021SC@SDUSC
一、前言
1.说明
audio 说明文档地址
audio package - github.com/hajimehoshi/ebiten/v2/audio - pkg.go.dev
本文中所有截图和代码均来自说明文档或 ebiten 源文件
笔者负责 audio 音频相关的代码分析
2.梗概
复现一下 odd audioinfiniteloop
二、实现
题外话:有空学一下 go 包管理
0.file2byteslice
在 2021 年 8 月,go 发布了一个文件转字节的小工具
file2byteslice GitHub 地址
源代码
// file2byteslice is a dead simple tool to embed a file to Go.
package main
import (
"flag"
"io"
"os"
"github.com/hajimehoshi/file2byteslice"
)
var (
// 输入文件名
inputFilename = flag.String("input", "", "input filename")
// 输出文件名
outputFilename = flag.String("output", "", "output filename")
// 包名
packageName = flag.String("package", "main", "package name")
// 变量名
varName = flag.String("var", "_", "variable name")
// 使用gzip压缩
compress = flag.Bool("compress", false, "use gzip compression")
buildTags = flag.String("buildtags", "", "build tags")
)
func run() error {
var out io.Writer
if *outputFilename != "" {
f, err := os.Create(*outputFilename)
if err != nil {
return err
}
defer f.Close()
out = f
} else {
out = os.Stdout
}
var in io.Reader
if *inputFilename != "" {
f, err := os.Open(*inputFilename)
if err != nil {
return err
}
defer f.Close()
in = f
} else {
in = os.Stdin
}
if err := file2byteslice.Write(out, in, *compress, *buildTags, *packageName, *varName); err != nil {
return err
}
return nil
}
func main() {
flag.Parse()
if err := run(); err != nil {
panic(err)
}
}
1.获得字节形式的 ogg 文件
使用流程
- 使用 git 或者直接下载小工具源码
git clone https://github.com/hajimehoshi/file2byteslice
目录
- 在命令行中 cd 到当前目录下,使用 go build 编译
生成名为 file2byteslice.exe 的可执行文件
go build -o file2byteslice.exe
- 下载一个 ogg 音频,使用小工具转换
我使用在线 MP3 转 ogg
转换了一段汤家凤老师的”圣经“《你怎么睡得着的》
总长度 15 秒
然后在刚才的目录下使用下面的语句生成包含字节的文件
./file2byteslice -input ./res/tjf.ogg -output ./res/tjf.ogg.go -package myogg -var TJF
tjf.ogg 是 ogg 文件,tjf.ogg.go 是包含字节的生成文件
因为我 go 导包还没有弄懂,所以直接复制了一份
2.源代码
//go:build linux || darwin || windows
// +build linux darwin windows
package main
import (
"bytes"
"fmt"
"log"
"time"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/v2/audio/vorbis"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
const (
screenWidth = 640
screenHeight = 480
sampleRate = 22050
introLengthInSecond = 5
loopLengthInSecond = 10
)
type Game struct {
player *audio.Player
audioContext *audio.Context
}
func (g *Game) Update() error {
if g.player != nil {
return nil
}
if g.audioContext == nil {
g.audioContext = audio.NewContext(sampleRate)
}
// 解码ogg
oggS, err := vorbis.Decode(g.audioContext, bytes.NewReader(TJF))
if err != nil {
return err
}
// 套一层无限循环的壳
s := audio.NewInfiniteLoopWithIntro(oggS, introLengthInSecond*4*sampleRate, loopLengthInSecond*4*sampleRate)
g.player, err = g.audioContext.NewPlayer(s)
if err != nil {
return err
}
// 播放
g.player.Play()
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
pos := g.player.Current()
if pos > 5*time.Second {
pos = (g.player.Current()-5*time.Second)%(10*time.Second) + 5*time.Second
}
msg := fmt.Sprintf(`TPS: %0.2f
汤家凤老师倾情巨献
前言: 0[s] - %[2]d[s]
循环: %[2]d[s] - %[3]d[s]
当前: %0.2[4]f[s]`, ebiten.CurrentTPS(), introLengthInSecond, introLengthInSecond+loopLengthInSecond, float64(pos)/float64(time.Second))
ebitenutil.DebugPrint(screen, msg)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("MyOggDemo1")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}
3.效果
播放成功,一共15秒,前5秒只播放一次,然后循环后10秒
但是中文显示失败了,待解决
三、问题
@ TODO
整理 GOPATH 和 GOROOT
整理 Git
使用 Git 克隆 ebiten 项目,并且整理项目包的导入
检查 VSCode 配置,为什么搜索不到包
掌握 go 提供的包管理工具
看一下 Sprintf 为什么显示不了中文