-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
101 lines (94 loc) · 2.26 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"time"
"github.com/faiface/beep"
"github.com/faiface/beep/speaker"
"github.com/faiface/beep/wav"
"github.com/pkg/errors"
)
func usage() {
fmt.Fprintln(os.Stderr, "Usage: foo FILE.wav...")
flag.PrintDefaults()
}
func main() {
flag.Usage = usage
flag.Parse()
if flag.NArg() < 1 {
flag.Usage()
os.Exit(1)
}
// Init speaker.
initStart := time.Now()
const sampleRate beep.SampleRate = 22050
if err := initSpeaker(sampleRate); err != nil {
log.Fatalf("%+v", err)
}
log.Printf("initializing speakers took %v", time.Since(initStart))
for _, wavPath := range flag.Args() {
// Decode WAV file.
decodeStart := time.Now()
audioBuf, err := decode(wavPath)
if err != nil {
log.Fatalf("%+v", err)
}
log.Printf("decoding %q took %v", wavPath, time.Since(decodeStart))
fmt.Println()
for i := 0; i < 10; i++ {
// Add playback control to audio buffer.
ctrlStart := time.Now()
ctrl := &beep.Ctrl{
Streamer: audioBuf.Streamer(0, audioBuf.Len()),
}
log.Printf("creating ctrl took %v", time.Since(ctrlStart))
// Play sound.
playStart := time.Now()
done := play(ctrl)
<-done
log.Printf("playing sound of length %v took %v", audioBuf.Len(), time.Since(playStart))
fmt.Println()
}
}
}
func initSpeaker(sampleRate beep.SampleRate) error {
bufferSize := sampleRate.N(time.Second / 10)
if err := speaker.Init(sampleRate, bufferSize); err != nil {
return errors.WithStack(err)
}
return nil
}
func play(ctrl *beep.Ctrl) <-chan struct{} {
playStart := time.Now()
first := beep.Callback(func() {
log.Printf("time taken until first sound: %v", time.Since(playStart))
})
done := make(chan struct{})
last := beep.Callback(func() {
done <- struct{}{}
})
streamer := beep.Seq(first, ctrl, last)
speaker.Play(streamer)
return done
}
func decode(wavPath string) (*beep.Buffer, error) {
buf, err := ioutil.ReadFile(wavPath)
if err != nil {
return nil, errors.WithStack(err)
}
r := bytes.NewReader(buf)
streamer, format, err := wav.Decode(r)
if err != nil {
return nil, errors.WithStack(err)
}
audioBuf := beep.NewBuffer(format)
audioBuf.Append(streamer)
if err := streamer.Close(); err != nil {
return nil, errors.WithStack(err)
}
return audioBuf, nil
}