ebiten 学习(5)-播放一段音频

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 文件

使用流程

  1. 使用 git 或者直接下载小工具源码
git clone https://github.com/hajimehoshi/file2byteslice

目录

在这里插入图片描述

  1. 在命令行中 cd 到当前目录下,使用 go build 编译
    生成名为 file2byteslice.exe 的可执行文件
go build -o file2byteslice.exe

在这里插入图片描述

  1. 下载一个 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 为什么显示不了中文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值