Measure devel notes: Difference between revisions

From OLPC
Jump to navigation Jump to search
No edit summary
m (Reverted edits by 79.76.12.59 (Talk) to last version by Cjl)
 
Line 1: Line 1:
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 [[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


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()