Skip to content

Commit

Permalink
Merge pull request #127 from ilyapashuk/master
Browse files Browse the repository at this point in the history
add sinusoid tone generation
  • Loading branch information
dusk125 committed Aug 31, 2021
2 parents 00d0eee + 1a05c2c commit e62bf86
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
36 changes: 36 additions & 0 deletions examples/tone-player/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"fmt"
"github.com/faiface/beep"
"github.com/faiface/beep/generators"
"github.com/faiface/beep/speaker"
"os"
"strconv"
)

func usage() {
fmt.Printf("usage: %s freq\n", os.Args[0])
fmt.Println("where freq must be an integer from 1 to 24000")
fmt.Println("24000 because samplerate of 48000 is hardcoded")
}
func main() {
if len(os.Args) < 2 {
usage()
return
}
f, err := strconv.Atoi(os.Args[1])
if err != nil {
usage()
return
}
speaker.Init(beep.SampleRate(48000), 4800)
s, err := generators.SinTone(beep.SampleRate(48000), f)
if err != nil {
panic(err)
}
speaker.Play(s)
for {

}
}
48 changes: 48 additions & 0 deletions generators/toner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// tones generator

package generators

import (
"math"
"errors"
. "github.com/faiface/beep"
)

// simple sinusoid tone generator
type toneStreamer struct {
stat float64
delta float64
}

// create streamer which will produce infinite sinusoid tone with the given frequency
// use other wrappers of this package to change amplitude or add time limit
// sampleRate must be at least two times grater then frequency, otherwise this function will return an error
func SinTone(sr SampleRate, freq int) (Streamer, error) {
if int(sr)/freq < 2 {
return nil, errors.New("faiface beep tone generator: samplerate must be at least 2 times grater then frequency")
}
r := new(toneStreamer)
r.stat = 0.0
srf := float64(sr)
ff := float64(freq)
steps := srf / ff
r.delta = 1.0 / steps
return r, nil
}

func (c *toneStreamer) nextSample() float64 {
r := math.Sin(c.stat * 2.0 * math.Pi)
_, c.stat = math.Modf(c.stat + c.delta)
return r
}

func (c *toneStreamer) Stream(buf [][2]float64) (int, bool) {
for i := 0; i < len(buf); i++ {
s := c.nextSample()
buf[i] = [2]float64{s, s}
}
return len(buf), true
}
func (_ *toneStreamer) Err() error {
return nil
}

0 comments on commit e62bf86

Please sign in to comment.