github.com/noriah/catnip@v1.8.5/cmd/catnip/number_writer.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/noriah/catnip/dsp" 8 "github.com/noriah/catnip/util" 9 ) 10 11 // Constants 12 const ( 13 // ScalingWindow in seconds 14 ScalingWindow = 1.5 15 // PeakThreshold is the threshold to not draw if the peak is less. 16 PeakThreshold = 0.001 17 ) 18 19 // Writer handles drawing our visualizer. 20 type Writer struct { 21 Smoother dsp.Smoother 22 trackZero int 23 binCount int 24 invertDraw bool 25 window *util.MovingWindow 26 } 27 28 func NewWriter() *Writer { 29 return &Writer{ 30 binCount: 50, 31 } 32 } 33 34 // Init initializes the display. 35 // Should be called before any other display method. 36 func (d *Writer) Init(sampleRate float64, sampleSize int) error { 37 // make a large buffer as this could be as big as the screen width/height. 38 39 windowSize := ((int(ScalingWindow * sampleRate)) / sampleSize) * 2 40 d.window = util.NewMovingWindow(windowSize) 41 42 return nil 43 } 44 45 // Close will stop display and clean up the terminal. 46 func (d *Writer) Close() error { 47 return nil 48 } 49 50 func (d *Writer) SetBinCount(count int) { 51 d.binCount = count 52 } 53 54 func (d *Writer) SetInvertDraw(invert bool) { 55 d.invertDraw = invert 56 } 57 58 // Start display is bad. 59 func (d *Writer) Start(ctx context.Context) context.Context { 60 return ctx 61 } 62 63 // Stop display not work. 64 func (d *Writer) Stop() error { 65 return nil 66 } 67 68 // Draw takes data and draws. 69 func (d *Writer) Write(buffers [][]float64, channels int) error { 70 71 peak := 0.0 72 bins := d.Bins(channels) 73 74 for i := 0; i < channels; i++ { 75 for _, val := range buffers[i][:bins] { 76 if val > peak { 77 peak = val 78 } 79 } 80 } 81 82 scale := 1.0 83 84 if peak >= PeakThreshold { 85 d.trackZero = 0 86 87 // do some scaling if we are above the PeakThreshold 88 d.window.Update(peak) 89 90 } else { 91 if d.trackZero++; d.trackZero == 5 { 92 d.window.Recalculate() 93 } 94 } 95 96 vMean, vSD := d.window.Stats() 97 98 if t := vMean + (2.0 * vSD); t > 1.0 { 99 scale = t 100 } 101 102 scale = 100.0 / scale 103 104 for xSet, chBins := range buffers { 105 106 for xBar := 0; xBar < d.binCount; xBar++ { 107 108 xBin := (xBar * (1 - xSet)) + (((d.binCount - 1) - xBar) * xSet) 109 110 if d.invertDraw { 111 xBin = d.binCount - 1 - xBin 112 } 113 114 fmt.Printf("%6.3f ", chBins[xBin]*scale) 115 } 116 } 117 118 fmt.Println() 119 120 return nil 121 } 122 123 // Bins returns the number of bars we will draw. 124 func (d *Writer) Bins(chCount int) int { 125 return d.binCount 126 }