Measure devel notes: Difference between revisions
No edit summary |
m (Reverted edits by 79.76.12.59 (Talk) to last version by Cjl) |
||
(31 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
Development notes. For the official page, please see [[Measure]] |
|||
==Measure Development Notes== |
|||
'''For note-taking and reference during the course of development of Measure Activity. For the official page please see [[Measure]]''' |
|||
==Metadata file associated with Logs== |
|||
Measure Activity logs metadata file |
|||
Filename |
|||
Filename |
|||
Filename |
|||
Logname |
|||
Logname |
|||
Logname |
|||
==Log file format== |
|||
'''FIXME:''' There is no reliable way for the "file" command to identify this data format. It is not clear what parts of this description are to be actually in the file; for example if the first line has 4 "/" characters or if that notation indicates alternatives. It is not clear if "minute" is a 6-character word that should appear in the file or if it is supposed to be a number, etc. The word "stop" at the end will mildly complicate both generators and consumers of this file format. Future extensions are neither prohibited nor defined; it is anyone's guess what might be valid in the future. If I guess the format right, it appears that the three discrete rate choices (a limitation of the current Measure activity) have been enshrined into the data file format. The y_mag and g values, both undocumented, appear to be display-related rather than data-related and thus do not belong in the file. |
|||
sec/minute/hour/snapshot |
|||
time/freq |
|||
y_mag |
|||
g |
|||
freq_range ( l / m /h) |
|||
2232 |
|||
3445 |
|||
... |
|||
... |
|||
stop |
|||
==Draw dotted log== |
|||
context.move_to(x,y) |
|||
context.arc(x,y,r,0,2*pi) |
|||
==Convert #RRGGBB to an (R, G, B) tuple== |
|||
colorstring = colorstring.strip() |
|||
if colorstring[0] == '#': colorstring = colorstring[1:] |
|||
r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:] |
|||
r, g, b = [int(n, 16) for n in (r, g, b)] |
|||
return (r, g, b) |
|||
==Get the XO colors== |
|||
from sugar import profile |
|||
color=profile.get_color() |
|||
fill = color.get_fill_color() |
|||
stroke = color.get_stroke_color() |
|||
==DSP== |
|||
===Filtering using sinc=== |
|||
* http://www.dspguide.com/ch16/2.htm |
|||
* I will precompute h[i] for all the three ranges and apply it to all the three ranges |
|||
* See [[http://dev.laptop.org/git?p=projects/measure;a=blob;f=testing_scripts/sinc_value_estimate.py;h=6f0ed6c8f7bed0fada6ee69cd24d3117bc6e2af6;hb=HEAD|Script]] |
|||
===Scaling - for scale display, and RMS values=== |
|||
* I get a buffer of 16bit values (-32768 to 32768). I need to calculate the corresponding rms value of the voltage |
|||
* The correspondence between digital domain values and physical values has been found out experimentally as |
|||
v = (m/g)*(s) + 1180 millivolts |
|||
where s is a sample value ranging from -32768 to +32768 |
|||
where m = .0238(i.e. slope when all capture gains are 0dB i.e. g=1) |
|||
where g is the gain introduced by capture gains. |
|||
There are two such gains Mic Boost +20dB and Capture Gain. |
|||
Note that g IS NOT in dB. |
|||
* Also let k = m/g and c = 1180 |
|||
* One option is to scale each sample in voltage domain (which would come out to be a float value) to get rms voltage, Rv = sqrt(sigma(Vi^2)) / N |
|||
* The other option is to calculate RMS of all samples s and then convert result to equivalent voltage |
|||
* For calculating RMS of samples s and then converting to Rv |
|||
** sigma(Vi^2) = (k^2)*(sigma(Xi^2)) + N*c^2 + 2*k*c*sigma(Xi) |
|||
** Once we have sigma(Vi^2) we can take square root of that and divide by N |
|||
* The big question is which one would be better suited in terms of performance overheads on the XO ? <-- profiling is the answer ? |
|||
::You can get rid of the floating point and the division if Python does OK with 64-bit numbers. You do something like this... |
|||
G = 1000/g |
|||
V = s*238*G + 1180*10000000 |
|||
v = V/10000000 |
|||
::...except that you don't immediately divide to get v, and you don't use 10000000. Use 2**32 instead, allowing a 32-bit right shift (free) instead of the division. (so the 1000 has to change, and you don't do .0238*10000 but rather something else appropriate) You may also delay that right shift, adding up the numbers first. |
|||
==Profiling== |
|||
import os |
|||
import cProfile |
|||
import lsprofcalltree |
|||
self._profiler = cProfile.Profile() |
|||
self._profiler.enable() |
|||
#code to profile# |
|||
self._profiler.disable() |
|||
k = lsprofcalltree.KCacheGrind(self._profiler) |
|||
data = open(os.path.expanduser('/tmp/measure.kgrind'), 'w+') |
|||
k.output(data) |
|||
data.close() |
|||
[[Category:Measure]] |
Latest revision as of 03:45, 3 April 2009
Development notes. For the official page, please see Measure
Metadata file associated with Logs
Measure Activity logs metadata file Filename Filename Filename Logname Logname Logname
Log file format
FIXME: There is no reliable way for the "file" command to identify this data format. It is not clear what parts of this description are to be actually in the file; for example if the first line has 4 "/" characters or if that notation indicates alternatives. It is not clear if "minute" is a 6-character word that should appear in the file or if it is supposed to be a number, etc. The word "stop" at the end will mildly complicate both generators and consumers of this file format. Future extensions are neither prohibited nor defined; it is anyone's guess what might be valid in the future. If I guess the format right, it appears that the three discrete rate choices (a limitation of the current Measure activity) have been enshrined into the data file format. The y_mag and g values, both undocumented, appear to be display-related rather than data-related and thus do not belong in the file.
sec/minute/hour/snapshot time/freq y_mag g freq_range ( l / m /h) 2232 3445 ... ... stop
Draw dotted log
context.move_to(x,y) context.arc(x,y,r,0,2*pi)
Convert #RRGGBB to an (R, G, B) tuple
colorstring = colorstring.strip() if colorstring[0] == '#': colorstring = colorstring[1:] r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:] r, g, b = [int(n, 16) for n in (r, g, b)] return (r, g, b)
Get the XO colors
from sugar import profile color=profile.get_color() fill = color.get_fill_color() stroke = color.get_stroke_color()
DSP
Filtering using sinc
- http://www.dspguide.com/ch16/2.htm
- I will precompute h[i] for all the three ranges and apply it to all the three ranges
- See [[1]]
Scaling - for scale display, and RMS values
- I get a buffer of 16bit values (-32768 to 32768). I need to calculate the corresponding rms value of the voltage
- The correspondence between digital domain values and physical values has been found out experimentally as
v = (m/g)*(s) + 1180 millivolts
where s is a sample value ranging from -32768 to +32768 where m = .0238(i.e. slope when all capture gains are 0dB i.e. g=1) where g is the gain introduced by capture gains. There are two such gains Mic Boost +20dB and Capture Gain. Note that g IS NOT in dB.
- Also let k = m/g and c = 1180
- One option is to scale each sample in voltage domain (which would come out to be a float value) to get rms voltage, Rv = sqrt(sigma(Vi^2)) / N
- The other option is to calculate RMS of all samples s and then convert result to equivalent voltage
- For calculating RMS of samples s and then converting to Rv
- sigma(Vi^2) = (k^2)*(sigma(Xi^2)) + N*c^2 + 2*k*c*sigma(Xi)
- Once we have sigma(Vi^2) we can take square root of that and divide by N
- The big question is which one would be better suited in terms of performance overheads on the XO ? <-- profiling is the answer ?
- You can get rid of the floating point and the division if Python does OK with 64-bit numbers. You do something like this...
G = 1000/g V = s*238*G + 1180*10000000 v = V/10000000
- ...except that you don't immediately divide to get v, and you don't use 10000000. Use 2**32 instead, allowing a 32-bit right shift (free) instead of the division. (so the 1000 has to change, and you don't do .0238*10000 but rather something else appropriate) You may also delay that right shift, adding up the numbers first.
Profiling
import os import cProfile import lsprofcalltree self._profiler = cProfile.Profile() self._profiler.enable() #code to profile# self._profiler.disable() k = lsprofcalltree.KCacheGrind(self._profiler) data = open(os.path.expanduser('/tmp/measure.kgrind'), 'w+') k.output(data) data.close()