From 1ffaf99c1a10b829382d3ad1505aeb2499e7af34 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Mon, 12 Aug 2019 21:47:18 +0200 Subject: [PATCH] Add more geiger While the current implementation does well for emulating an avant-garde synthesizer theme the name does sound a bit misleading. Other than that, this also adds a baseline to sort of account for the allocations by the application itself. "Test" added. --- geiger.go | 27 ++++++++++++++------- geiger_test.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 geiger_test.go diff --git a/geiger.go b/geiger.go index e239b19..73c9e5c 100644 --- a/geiger.go +++ b/geiger.go @@ -2,6 +2,7 @@ package geiger // import "lukechampine.com/geiger" import ( "math" + "math/rand" "runtime" "time" @@ -10,17 +11,22 @@ import ( ) const sr = beep.SampleRate(44100) -const memSampleRate = 100 * time.Millisecond +const memSampleRate = 500 * time.Millisecond +const baseline = 160 func Count() { - var freq, t float64 - step := sr.D(1).Seconds() - speaker.Init(sr, sr.N(memSampleRate)) + var p int + speaker.Init(sr, sr.N(memSampleRate)/5) + rng := rand.New(rand.NewSource(0x1337)) + sign := 1.0 speaker.Play(beep.StreamerFunc(func(samples [][2]float64) (int, bool) { for i := range samples { - t += step - a := math.Sin(2 * math.Pi * freq * t) - samples[i] = [2]float64{a, a} + if rng.Intn(int(sr)) < p { + samples[i] = [2]float64{sign, sign} + sign *= -1 + } else { + samples[i] = [2]float64{0, 0} + } } return len(samples), true })) @@ -32,8 +38,13 @@ func Count() { runtime.ReadMemStats(&ms) diff := ms.Mallocs - prevAllocs prevAllocs = ms.Mallocs + // Allocs per second + rate := float64(diff)/memSampleRate.Seconds() - baseline + // If it becomes too high it becomes inaudible. + // Limit at 3.6 Roentgen. + rate = math.Min(rate, float64(sr)/3.6) speaker.Lock() - freq = float64(diff) / memSampleRate.Seconds() + p = int(rate) speaker.Unlock() } } diff --git a/geiger_test.go b/geiger_test.go new file mode 100644 index 0000000..7bd3bd4 --- /dev/null +++ b/geiger_test.go @@ -0,0 +1,65 @@ +package geiger + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + "time" +) + +// TestCount requires human ears. +func TestCount(t *testing.T) { + go Count() + tests := []struct { + name string + hz int + per int + }{ + { + name: "baseline", + hz: 1, + per: 0, + }, + { + name: "5hz", + hz: 5, + per: 1, + }, { + name: "50hz", + hz: 50, + per: 1, + }, { + name: "500hz", + hz: 50, + per: 10, + }, { + name: "5000hz", + hz: 50, + per: 100, + }, { + name: "50000hz", + hz: 50, + per: 1000, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + done := time.After(5 * time.Second) + every := time.NewTicker(time.Second / time.Duration(tt.hz)) + for { + select { + case <-done: + return + case <-every.C: + for i := 0; i < tt.per; i++ { + // alloc tmp + tmp := bytes.Buffer{} + io.Copy(ioutil.Discard, &tmp) + } + } + } + }) + } +}