func addNote() { size := audio.SampleRate() / 60 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] for note == ' ' { scoreIndex++ scoreIndex %= len(score) 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) audio.Play(0, toBytes(l, r)) }
func init() { s := float64(audio.SampleRate()) amp := []float64{1.0, 0.8, 0.6, 0.4, 0.2} x := []float64{4.0, 2.0, 1.0, 0.5, 0.25} for i := 0; i < len(pcm); i++ { v := 0.0 twoPiF := 2.0 * math.Pi * baseFreq for j := 0; j < len(amp); j++ { a := amp[j] * math.Exp(-5*float64(i)/(x[j]*s)) v += a * math.Sin(float64(i)*twoPiF*float64(j+1)/s) } pcm[i] = v / 5.0 } }
func square(out []int16, volume float64, freq float64, sequence float64) { if freq == 0 { for i := 0; i < len(out); i++ { out[i] = 0 } return } length := int(float64(audio.SampleRate()) / freq) if length == 0 { panic("invalid freq") } for i := 0; i < len(out); i++ { a := int16(volume * math.MaxInt16) if i%length < int(float64(length)*sequence) { a = -a } out[i] = a } }
"image/color" "log" "math" "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" "github.com/hajimehoshi/ebiten/example/common" "github.com/hajimehoshi/ebiten/exp/audio" ) const ( screenWidth = 320 screenHeight = 240 ) var pcm = make([]float64, 4*audio.SampleRate()) const baseFreq = 220 func init() { s := float64(audio.SampleRate()) amp := []float64{1.0, 0.8, 0.6, 0.4, 0.2} x := []float64{4.0, 2.0, 1.0, 0.5, 0.25} for i := 0; i < len(pcm); i++ { v := 0.0 twoPiF := 2.0 * math.Pi * baseFreq for j := 0; j < len(amp); j++ { a := amp[j] * math.Exp(-5*float64(i)/(x[j]*s)) v += a * math.Sin(float64(i)*twoPiF*float64(j+1)/s) } pcm[i] = v / 5.0