annotate service/audioInputLevels/audioInputLevelsPulse.py @ 1449:a2bc6602a0db

dockerfile deps Ignore-this: b12d406bc1fee7c07092d273904b8b3d darcs-hash:8b40b2634a6df26e0de4f6ef31c6ef2aabf14c31
author drewp <drewp@bigasterisk.com>
date Wed, 25 Sep 2019 17:25:19 -0700
parents 61ce2830dea7
children 4fa5c6a61282
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
1 # based on http://freshfoo.com/blog/pulseaudio_monitoring
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
2 #
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
3 # https://github.com/swharden/Python-GUI-examples/blob/master/2016-07-37_qt_audio_monitor/SWHear.py is similar
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
4 from __future__ import division
1282
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
5 import socket, time, logging, os, subprocess
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
6 from Queue import Queue
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
7 from ctypes import c_void_p, c_ulong, string_at
1161
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
8 from docopt import docopt
1112
03b4882517dd audiolevels output to influxdb
drewp <drewp@bigasterisk.com>
parents: 887
diff changeset
9 from influxdb import InfluxDBClient
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
10 import numpy
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
11
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
12 from pulseaudio import lib_pulseaudio as P
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
13
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
14 logging.basicConfig(level=logging.INFO)
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
15 log = logging.getLogger()
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
16
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
17
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
18 class PeakMonitor(object):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
19
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
20 def __init__(self, source_name, rate):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
21 self.source_name = source_name
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
22 self.rate = rate
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
23
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
24 self.bufs = []
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
25 self.buf_samples = 0
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
26
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
27 # Wrap callback methods in appropriate ctypefunc instances so
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
28 # that the Pulseaudio C API can call them
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
29 self._context_notify_cb = P.pa_context_notify_cb_t(self.context_notify_cb)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
30 self._source_info_cb = P.pa_source_info_cb_t(self.source_info_cb)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
31 self._stream_read_cb = P.pa_stream_request_cb_t(self.stream_read_cb)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
32
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
33 # stream_read_cb() puts peak samples into this Queue instance
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
34 self._samples = Queue()
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
35
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
36 # Create the mainloop thread and set our context_notify_cb
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
37 # method to be called when there's updates relating to the
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
38 # connection to Pulseaudio
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
39 _mainloop = P.pa_threaded_mainloop_new()
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
40 _mainloop_api = P.pa_threaded_mainloop_get_api(_mainloop)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
41 context = P.pa_context_new(_mainloop_api, 'peak_demo')
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
42 P.pa_context_set_state_callback(context, self._context_notify_cb, None)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
43 P.pa_context_connect(context, None, 0, None)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
44 P.pa_threaded_mainloop_start(_mainloop)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
45
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
46 def __iter__(self):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
47 while True:
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
48 yield self._samples.get()
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
49
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
50 def context_notify_cb(self, context, _):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
51 state = P.pa_context_get_state(context)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
52
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
53 if state == P.PA_CONTEXT_READY:
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
54 log.info("Pulseaudio connection ready...")
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
55 # Connected to Pulseaudio. Now request that source_info_cb
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
56 # be called with information about the available sources.
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
57 o = P.pa_context_get_source_info_list(context, self._source_info_cb, None)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
58 P.pa_operation_unref(o)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
59
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
60 elif state == P.PA_CONTEXT_FAILED :
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
61 log.error("Connection failed")
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
62 os.abort()
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
63
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
64 elif state == P.PA_CONTEXT_TERMINATED:
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
65 log.error("Connection terminated")
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
66 os.abort()
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
67
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
68 else:
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
69 log.info('context_notify_cb state=%r', state)
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
70
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
71 def source_info_cb(self, context, source_info_p, _, __):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
72 if not source_info_p:
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
73 return
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
74
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
75 source_info = source_info_p.contents
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
76
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
77 if source_info.name == self.source_name:
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
78 # Found the source we want to monitor for peak levels.
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
79 # Tell PA to call stream_read_cb with peak samples.
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
80 log.info('setting up peak recording using %s', source_info.name)
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
81 log.info('description: %r', source_info.description)
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
82
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
83 samplespec = P.pa_sample_spec()
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
84 samplespec.channels = 1
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
85 samplespec.format = P.PA_SAMPLE_S32LE
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
86 samplespec.rate = self.rate
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
87 pa_stream = P.pa_stream_new(context, "audioInputLevels", samplespec, None)
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
88
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
89 P.pa_stream_set_read_callback(pa_stream,
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
90 self._stream_read_cb,
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
91 source_info.index)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
92 P.pa_stream_connect_record(pa_stream,
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
93 source_info.name,
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
94 None,
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
95 P.PA_STREAM_PEAK_DETECT)
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
96
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
97 def stream_read_cb(self, stream, length, index_incr):
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
98 data = c_void_p()
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
99 P.pa_stream_peek(stream, data, c_ulong(length))
1144
b9981f50b82d audioInputLevels robustness and cleanup
drewp <drewp@bigasterisk.com>
parents: 1112
diff changeset
100 try:
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
101 buf = string_at(data, length)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
102 arr = numpy.fromstring(buf, dtype=numpy.dtype('<i4'))
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
103 self.bufs.append(arr)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
104 self.buf_samples += arr.shape[0]
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
105
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
106 if self.buf_samples > self.rate * 1.0:
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
107 self.onChunk(numpy.concatenate(self.bufs))
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
108 self.bufs = []
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
109 self.buf_samples = 0
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
110 finally:
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
111 P.pa_stream_drop(stream)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
112
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
113 def fft(self, arr):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
114 t1 = time.time()
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
115 # if this is slow, try
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
116 # https://hgomersall.github.io/pyFFTW/sphinx/tutorial.html#the-workhorse-pyfftw-fftw-class
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
117 # . But, it seems to take 1-10ms per second of audio, so who
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
118 # cares.
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
119 mags = numpy.abs(numpy.fft.fft(arr))
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
120 ft = time.time() - t1
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
121 return mags, ft
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
122
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
123 def timeSinceLastChunk(self):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
124 now = time.time()
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
125 if hasattr(self, 'lastRead'):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
126 dt = now - self.lastRead
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
127 else:
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
128 dt = 1
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
129 self.lastRead = now
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
130 return dt
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
131
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
132 def onChunk(self, arr):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
133 dt = self.timeSinceLastChunk()
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
134
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
135 n = 8192
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
136
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
137 mags, ft = self.fft(arr[:n])
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
138 freqs = numpy.fft.fftfreq(n, d=1.0/self.rate)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
139
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
140 def freq_range(lo, hi):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
141 mask = (lo < freqs) & (freqs < hi)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
142 return numpy.sum(mags * mask) / numpy.count_nonzero(mask)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
143
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
144 scl = 1000000000
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
145 bands = {'hi': freq_range(500, 8192) / scl,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
146 'mid': freq_range(300, 500) / scl,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
147 'lo': freq_range(90, 300) / scl,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
148 'value': freq_range(90, 8192) / scl,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
149 }
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
150 log.debug('%r', bands)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
151 #import ipdb;ipdb.set_trace()
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
152
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
153 if log.isEnabledFor(logging.DEBUG):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
154 self.dumpFreqs(n, dt, ft, scl, arr, freqs, mags)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
155 self._samples.put(bands)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
156
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
157 def dumpFreqs(self, n, dt, ft, scl, arr, freqs, mags):
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
158 log.debug(
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
159 'new chunk of %s samples, dt ~%.4f; ~%.1f hz; max %.1f; fft took %.2fms',
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
160 n, dt, n / dt, arr.max() / scl, ft * 1000,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
161 )
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
162 rows = zip(freqs, mags)
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
163 for fr,v in rows[1:8] + rows[8:n//8:30]:
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
164 log.debug('%6.1f %6.3f %s',
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
165 fr, v / scl, '*' * int(min(80, 80 * int(v) / scl)))
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
166
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
167
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
168 def main():
1161
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
169 arg = docopt("""
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
170 Usage: audioInputLevelsPulse.py [-v] --source=<name>
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
171
1161
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
172 --source=<name> pulseaudio source name (use `pactl list sources | grep Name`)
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
173 -v Verbose
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
174 """)
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
175
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
176 log.setLevel(logging.DEBUG if arg['-v'] else logging.INFO)
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
177
1282
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
178 # todo move this into the PeakMonitor part
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
179 subprocess.check_output(['pactl',
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
180 'set-source-volume', arg['--source'], '94900'])
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
181
61ce2830dea7 set source volume at start
drewp <drewp@bigasterisk.com>
parents: 1162
diff changeset
182 influx = InfluxDBClient('bang.vpn-home.bigasterisk.com', 9060, 'root', 'root', 'main')
1112
03b4882517dd audiolevels output to influxdb
drewp <drewp@bigasterisk.com>
parents: 887
diff changeset
183
03b4882517dd audiolevels output to influxdb
drewp <drewp@bigasterisk.com>
parents: 887
diff changeset
184 hostname = socket.gethostname()
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
185 METER_RATE = 8192
1161
6139847a72d4 switch to docopt, add -v
drewp <drewp@bigasterisk.com>
parents: 1144
diff changeset
186 monitor = PeakMonitor(arg['--source'], METER_RATE)
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
187 for sample in monitor:
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
188 log.debug(' %6.3f %s', sample['value'], '>' * int(min(80, sample['value'] * 80)))
1112
03b4882517dd audiolevels output to influxdb
drewp <drewp@bigasterisk.com>
parents: 887
diff changeset
189 influx.write_points([{'measurement': 'audioLevel',
1162
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
190 "fields": sample,
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
191 "time": int(time.time())}],
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
192 tags=dict(location=hostname),
52960ea4dfa6 audiolevels now saves multiple frequency bands
drewp <drewp@bigasterisk.com>
parents: 1161
diff changeset
193 time_precision='s')
887
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
194
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
195 if __name__ == '__main__':
64a2ba088665 audio input levels to graphite
drewp <drewp@bigasterisk.com>
parents:
diff changeset
196 main()