mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
examples/pcm: Refactoring
This commit is contained in:
parent
35b7375e69
commit
c4faf5b12c
@ -19,6 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
"github.com/hajimehoshi/ebiten/audio"
|
"github.com/hajimehoshi/ebiten/audio"
|
||||||
@ -41,8 +42,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var frames = 0
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
freqA = 440.0
|
freqA = 440.0
|
||||||
freqAS = 466.2
|
freqAS = 466.2
|
||||||
@ -59,10 +58,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Twinkle, Twinkle, Little Star
|
// Twinkle, Twinkle, Little Star
|
||||||
const score = `CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR`
|
var score = strings.Replace(
|
||||||
|
`CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR`,
|
||||||
var scoreIndex = 0
|
" ", "", -1)
|
||||||
|
|
||||||
|
// square fills out with square wave values with the specified volume, frequency and sequence.
|
||||||
func square(out []int16, volume float64, freq float64, sequence float64) {
|
func square(out []int16, volume float64, freq float64, sequence float64) {
|
||||||
if freq == 0 {
|
if freq == 0 {
|
||||||
for i := 0; i < len(out); i++ {
|
for i := 0; i < len(out); i++ {
|
||||||
@ -83,6 +83,7 @@ func square(out []int16, volume float64, freq float64, sequence float64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toBytes returns the 2ch little endian 16bit byte sequence with the given left/right sequence.
|
||||||
func toBytes(l, r []int16) []byte {
|
func toBytes(l, r []int16) []byte {
|
||||||
if len(l) != len(r) {
|
if len(l) != len(r) {
|
||||||
panic("len(l) must equal to len(r)")
|
panic("len(l) must equal to len(r)")
|
||||||
@ -97,50 +98,60 @@ func toBytes(l, r []int16) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func addNote() rune {
|
// playNote plays the note at scoreIndex of the score.
|
||||||
size := sampleRate / ebiten.FPS
|
func playNote(scoreIndex int) rune {
|
||||||
notes := []float64{freqC, freqD, freqE, freqF, freqG, freqA * 2, freqB * 2}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
scoreIndex++
|
|
||||||
scoreIndex %= len(score)
|
|
||||||
}()
|
|
||||||
l := make([]int16, size*30)
|
|
||||||
r := make([]int16, size*30)
|
|
||||||
note := score[scoreIndex]
|
note := score[scoreIndex]
|
||||||
for note == ' ' {
|
|
||||||
scoreIndex++
|
// If the note is 'rest', play nothing.
|
||||||
scoreIndex %= len(score)
|
if note == 'R' {
|
||||||
note = score[scoreIndex]
|
|
||||||
}
|
|
||||||
freq := 0.0
|
|
||||||
switch {
|
|
||||||
case note == 'R':
|
|
||||||
freq = 0
|
|
||||||
case note <= 'B':
|
|
||||||
freq = notes[int(note)+len(notes)-int('C')]
|
|
||||||
default:
|
|
||||||
freq = notes[note-'C']
|
|
||||||
}
|
|
||||||
vol := 1.0 / 16.0
|
|
||||||
square(l, vol, freq, 0.25)
|
|
||||||
square(r, vol, freq, 0.25)
|
|
||||||
b := toBytes(l, r)
|
|
||||||
p, _ := audio.NewPlayerFromBytes(audioContext, b)
|
|
||||||
p.Play()
|
|
||||||
return rune(note)
|
return rune(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentNote rune
|
freqs := []float64{freqC, freqD, freqE, freqF, freqG, freqA * 2, freqB * 2}
|
||||||
|
freq := 0.0
|
||||||
|
switch {
|
||||||
|
case 'A' <= note && note <= 'B':
|
||||||
|
freq = freqs[int(note)+len(freqs)-int('C')]
|
||||||
|
case 'C' <= note && note <= 'G':
|
||||||
|
freq = freqs[note-'C']
|
||||||
|
default:
|
||||||
|
panic("note out of range")
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
vol = 1.0 / 16.0
|
||||||
|
size = 30 * sampleRate / ebiten.FPS
|
||||||
|
)
|
||||||
|
l := make([]int16, size)
|
||||||
|
r := make([]int16, size)
|
||||||
|
square(l, vol, freq, 0.25)
|
||||||
|
square(r, vol, freq, 0.25)
|
||||||
|
|
||||||
|
p, _ := audio.NewPlayerFromBytes(audioContext, toBytes(l, r))
|
||||||
|
p.Play()
|
||||||
|
|
||||||
|
return rune(note)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
scoreIndex = 0
|
||||||
|
frames = 0
|
||||||
|
currentNote rune
|
||||||
|
)
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
func update(screen *ebiten.Image) error {
|
||||||
|
// Play notes for each half second.
|
||||||
if frames%30 == 0 {
|
if frames%30 == 0 {
|
||||||
currentNote = addNote()
|
currentNote = playNote(scoreIndex)
|
||||||
|
scoreIndex++
|
||||||
|
scoreIndex %= len(score)
|
||||||
}
|
}
|
||||||
frames++
|
frames++
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
if ebiten.IsRunningSlowly() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := "Note: "
|
msg := "Note: "
|
||||||
if currentNote == 'R' {
|
if currentNote == 'R' {
|
||||||
msg += "-"
|
msg += "-"
|
||||||
|
Loading…
Reference in New Issue
Block a user