#!/usr/bin/python import pylast, math, operator, sys ############################################### # This is a simple script to play with pylast # # and the last.fm API. It goes through your # # library and gets the top tags for your top # # artists, and weights them based on playcounts,# # giving you a percentage for different tags. # # Be sure to install pylast! # # http://code.google.com/p/pylast/ # ################################################# # Charles Knight - charles@rabidaudio.com # ############################################### usage = "python genre_influences.py username artist_limit tag_limit [log_plays]" if len(sys.argv) < 4: print usage sys.exit() username = sys.argv[1] artist_limit=int(sys.argv[2]) #How many artist's tags to use (e.g. top 50) tag_limit=int(sys.argv[3]) #How many tags for each artist if len(sys.argv) > 4: log_plays=int(sys.argv[4]) else: log_plays = 0 #1 to take the natural logarithm for playcounts. This smooths out your results by # giving more weight to artists with fewer listens (0 weighs by normal playcount) # You have to have your own unique two values for API_KEY and API_SECRET # Obtain yours from http://www.last.fm/api/account for Last.fm API_KEY = "YOURAPIKEY" API_SECRET = "YOURAPISECRET" #This is an exclude list for tags. Here are some of the shitty ones I got. reducing tag_limit might help bad_tags = ["female vocalists", "singer-songwriter", "rock opera", "80s", "90s", "political", "epic", "canadian", "megaman", "female vocalist", "eminem", "60s", "female fronted metal", "bass", "christian", "british"] all_tags = {} # In order to perform a write operation you need to authenticate yourself network = pylast.get_lastfm_network(api_key = API_KEY, api_secret = API_SECRET) mylibrary = pylast.Library(user = username, network = network) artists = mylibrary.get_artists(limit=artist_limit) for a in artists: artist = a.item playcount = a.playcount if log_plays: playcount = math.log(playcount) name = artist.get_name() top_tags = artist.get_top_tags(limit=tag_limit) weights = [] tags = [] for t in top_tags: tt = t.item.get_name().lower() if tt not in bad_tags: tags.append(tt) weight = float(t.weight) weights.append(weight) sw = sum(weights) for i in range(len(weights)): weights[i]=weights[i] / sw tag = tags[i] if tag in all_tags: all_tags[tag] += weights[i]*playcount else: all_tags[tag] = weights[i]*playcount #This black magic came from StackOverflow. Sorts a dictionary by value into tuples, no idea how. Requres 'operator' #http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value#613218 scores=sorted(all_tags.iteritems(), key=operator.itemgetter(1)) scores.reverse() ss = sum(s[1] for s in scores) for t,s in scores: print '%-22s ==> %5s' % (t, str(round(s/ss,3)*100)+"%")
Sunday, May 12, 2013
last.fm API: genre influences
I've been talking about writing something using the last.fm API, and I finally have. Nothing to exciting here, just testing the water. This little script (using pylast) gets the top tags from your top artists, and scores them, giving you a percentage for each tag. It is pretty shitty code; this was a one-off thing, and the way it (I) can't make up it's (my) mind whether to use lists, dictionaries, or tuples is pretty embarrassing. Be sure to get an API key from last.fm first.
Tuesday, April 30, 2013
DSP + Arduino
Amanda Ghassaei, who has this amazing project I just found out about, also has a great Instructable for doing DSP with Arduino. A few hours and one blown op-amp later, I was able to get my Arduino to pickup my bass playing. It samples around 38.5 kHz, but I only had it send serial data back every 10 ms (a measly 100 Hz). Still, I was able to generate this graph with the data. You can see the clipping where I cranked it up to test the peak indicator LED.
The atmega328 has 32Kb flash memory. If I used half of that for a delay line, 16,000 samples / 38500 samples/sec = .42 second delay. I could get a longer delay by using external flash (e.g. SD card), but I worry that the read/write time would be low. It will be interesting to apply some of the concepts from class to actual signals. What does a 50-point averager do to my tone? (answer: probably reverb)
There's not a lot I can do with this now, since I can't hear the results of any processing yet. I just ordered a DAC0808 8-bit digital-analog converter. (The new DUE has two built-in DAC outputs, as well as PWM, although it still isn't an ideal platform for DSP). Eventually, I would like to get an FFT algorithm running and make a tuner. That will probably have to wait until after finals, though.
EDIT: Just found out about wki.pe/Resistor_ladder s.
The atmega328 has 32Kb flash memory. If I used half of that for a delay line, 16,000 samples / 38500 samples/sec = .42 second delay. I could get a longer delay by using external flash (e.g. SD card), but I worry that the read/write time would be low. It will be interesting to apply some of the concepts from class to actual signals. What does a 50-point averager do to my tone? (answer: probably reverb)
There's not a lot I can do with this now, since I can't hear the results of any processing yet. I just ordered a DAC0808 8-bit digital-analog converter. (The new DUE has two built-in DAC outputs, as well as PWM, although it still isn't an ideal platform for DSP). Eventually, I would like to get an FFT algorithm running and make a tuner. That will probably have to wait until after finals, though.
EDIT: Just found out about wki.pe/Resistor_ladder s.
Monday, April 1, 2013
Location-enabled mesh networking protocol
Think of a peer-to-peer network. Not in an application-level sense, like torrents or Bitcoin, but on a physical/data-link level. Rather than connecting to a router, your device connects directly to a handful of other nearby devices, creating a web of communication. Mesh network topologies are not a new concept. Problems such as high latency and potentially different hardware have limited usage to a few novel solutions. But these protocols lack a powerful tool that is quickly coming ubiquitous as we approach the Internet of Things, and that is location data.
Devices that require network connectivity are increasingly mobile. It is expected that networked mobile devices will include compass/gyroscope/accelerometer/GPS hardware, which in combination can give the location and heading information (position, velocity, and acceleration) of those devices. In an ad-hoc mesh network, the number of connections each node can make is limited, and creating new connections is expensive. Using this information, devices could make smart decisions about what connections to make. If a node is moving quickly away from you, the value of making a connection to it is low, as it will be out of range in a short amount of time.
A mesh network should be a preferred topology for IoT. It is cheap to implement, free of authority, and mirrors social interaction. Take, for example, a system of smart cars. To avoid collisions, the smart cars must be able to communicate with those nearby. Using our current system, each device would require a network connection such as LTE. The communications would pass up to a nearby router/server and back down to the nearby vehicles. This method has three flaws. First, it is inefficient. Direct connections to nearby vehicles would increase the rate of data transfer, and even connections that require a low number of hops would about equal the transfer rate of a router system. It is also expensive. Having high-speed, reliable dedicated routers capable of covering the entire road system of a country is quite a demand, and installing and supporting this expensive hardware would be even more burdensome. The slow and uneven deployment of broadband in America shows the extreme cost and difficulty of this. Finally, they are insecure, in that they offer a single point of failure. If an attacker were to disable the router, communication between the vehicles would be lost, with potentially catastrophic results. A distributed network lacks authority making it resilient against attacks. The network is able to quickly adapt to the loss of a single node.
A distributed network like this is not without its security problems. For example, a person sending false positioning data could reduce or possibly even disable the network by skewing the calculations of optimal connections. This is analogous to (but distinct from) the problem of, in the car example, someone standing on the sidewalk, claiming to be a car about to fly across the street, potentially causing a collision between the real cars as they react to this false threat. This is part of the security trade-off of authority-less networks, and is ultimately a problem to be solved in the field of network security. This does not diminish the value of a location-enabled mesh networking protocol.
Edit:
Turns out much of this already exists. wki.pe/Intelligent_Vehicular_AdHoc_Network specifically mentions wki.pe/Position-based_routing . Other cool stuff I found:
http://wirelessafrica.meraka.org.za/wiki/index.php/DIY_Mesh_Guide
wki.pe/Netsukuku
wki.pe/Babel_(protocol)
Edit:
Turns out much of this already exists. wki.pe/Intelligent_Vehicular_AdHoc_Network specifically mentions wki.pe/Position-based_routing . Other cool stuff I found:
http://wirelessafrica.meraka.org.za/wiki/index.php/DIY_Mesh_Guide
wki.pe/Netsukuku
wki.pe/Babel_(protocol)
Friday, February 15, 2013
Circular buffer algorithm rates on Arduino
For my chorded keyboard, I need a mode switch function. These modes increment and decrement in a loop. For example, if there are four modes (0, 1, 2, and 3), and I want to go to the next mode, 3 should loop back around to 0. I'm sure there is a name for these systems, but I'm not sure what it is. Apparently, they are called wki.pe/Circular_buffers.
This is an easy problem, and there are many ways to solve it (some more elegant than others). As I thought about all the ways to do this, I wondered which was the fastest. So I worked up 5 algorithms of varying elegance and methods and ran them against each other.
F1 increments, and then moves 4 to 0.
F2 uses modulo:
F3 is exactly the same as F2. I was curious wither it would be faster or slower to do it in one line. It is certainly more elegant.
F4 is a case-switch:
F5 is if-esleif-else:
I suspected F4 and F5 to be very slow, as they are a lot of lines. I figured modulo is probably a longer function, so my hunch was F1 would win in terms of speed, modulo's elegance aside. The speed of the algorithms would depend on the number going in: F1(0) should be faster than F1(3). Each algorithm is run for each of {0,1,2,3} 100 times, and the microseconds to do that are returned. I repeated this for all 5 algorithms 10 times. Here is the test code:
The full data is available here. The average time in microseconds for each algorithm:
This is an easy problem, and there are many ways to solve it (some more elegant than others). As I thought about all the ways to do this, I wondered which was the fastest. So I worked up 5 algorithms of varying elegance and methods and ran them against each other.
F1 increments, and then moves 4 to 0.
byte f1(byte a){
a++;
if(a>=4){
a=0;
}
return a;
}
F2 uses modulo:
byte f2(byte a){
a++;
return a % 4;
}
F3 is exactly the same as F2. I was curious wither it would be faster or slower to do it in one line. It is certainly more elegant.
byte f3(byte a){
return ++a % 4;
}
F4 is a case-switch:
byte f4(byte a){
switch(a){
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 3;
break;
case 3:
return 0;
break;
}
}
F5 is if-esleif-else:
byte f5(byte a){
if(a==0){
return 1;
}else if(a==1){
return 2;
}else if(a==2){
return 3;
}else{
return 0;
}
}
I suspected F4 and F5 to be very slow, as they are a lot of lines. I figured modulo is probably a longer function, so my hunch was F1 would win in terms of speed, modulo's elegance aside. The speed of the algorithms would depend on the number going in: F1(0) should be faster than F1(3). Each algorithm is run for each of {0,1,2,3} 100 times, and the microseconds to do that are returned. I repeated this for all 5 algorithms 10 times. Here is the test code:
byte a;
byte b;
byte c;
unsigned long starts;
unsigned long ends;
unsigned long delta;
void setup() {
Serial.begin(9600);
delay(2000);
}
void loop() {
//f1
for(a=0; a<=3; a++){
starts = micros();
for(b=0; b<=100; b++){
c=f1(b);
}
ends = micros();
delta = ends - starts;
Serial.print(delta);
Serial.print("\t");
}
Serial.println(");
delay(2000);
//f2
for(a=0; a<=3; a++){
starts = micros();
for(b=0; b<=100; b++){
c=f2(b);
}
ends = micros();
delta = ends - starts;
Serial.print(delta);
Serial.print("\t");
}
Serial.println(");
delay(2000);
//f3
for(a=0; a<=3; a++){
starts = micros();
for(b=0; b<=100; b++){
c=f3(b);
}
ends = micros();
delta = ends - starts;
Serial.print(delta);
Serial.print("\t");
}
Serial.println(");
delay(2000);
//f4
for(a=0; a<=3; a++){
starts = micros();
for(b=0; b<=100; b++){
c=f4(b);
}
ends = micros();
delta = ends - starts;
Serial.print(delta);
Serial.print("\t");
}
Serial.println(");
delay(2000);
//f5
for(a=0; a<=3; a++){
starts = micros();
for(b=0; b<=100; b++){
c=f5(b);
}
ends = micros();
delta = ends - starts;
Serial.print(delta);
Serial.print("\t");
}
Serial.println(");
delay(2000);
}
The full data is available here. The average time in microseconds for each algorithm:
| F1 | F2 | F3 | F4 | F5 |
| 0.662 | 0.539 | 0.539 | 1.101 | 0.979 |
It is worth noting that the modulus function is faster than any of the functions with conditionals, including the first. It is also interesting that there is really no difference between incrementing on a separate line vs. on the same line (this is probably because they compile to the same thing). Here is the chart of the results. Each group is for the inputs {0, 1, 2, 3}. There was no real change across inputs between each algorithm, which I thought was surprising.
This is a case where the most elegant solution is also the fastest.
Wednesday, November 28, 2012
The Color of Music
After being inspired by a neat TED talk about a colorblind guy who wears a camera device that plays different audio frequencies based on the color he is looking at, allowing him to "see" (sense) color, as well as a neat talk at Berry from Robert Schneider (no relation to Rob Schneider, it seems) about some of his math inspired music projects, I wanted to try and work backwards: turn sound into color.
load handel.mat
%The file is now stored in y
sound(y) %listen to it to make sure it works%the sound function defaults to a sample rate of 8192 per second.
% If we double it, we double the tempo and frequency (chipmonks)
sound(y,16384)
plot(y) %this will show a graph of the waveform like you see in a music editing program
%Lets get just the first note ('HA-'). look at the plot. The section we
%want is from about 1667 to about 5000, so let's define a new sound array a
a=y(1667:5000,1);
%listen to see that it is just the first note
sound(a)
plot(a)
%now we can find the FFT for a. The following is from the MATLAB guide for%the fft() function, using this data instead of theirs.
Fs=8192; %The sample frequency
T=1/Fs; %Period=1/Frequency
L=size(a,1); %the length of the signal
NFFT = 2^nextpow2(L); %the next power of two after L
Y = fft(y,NFFT)/L; %our FFT data
f = Fs/2*linspace(0,1,NFFT/2+1); %f is the set of frequencies for the x axis of the graph
p = 2*abs(Y(1:NFFT/2+1)); %p is the set of amplitudes for the y axis of the graph
plot(f,p); %isn't it beautiful!?
%now, let's find out what note they are singing.
%find(p==max(p)) will return a set of indexes in p of the maximum value of
%p (which is the one we want, a little after 500 Hz). In this case, there is
%only 1 occurence, so we can dump it streight into f, as the corresponding
%freqency for this value is then the value of f at this index.
f(find(p==max(p)))
%this returns 572 Hz, which is very close to 577.33 Hz: D5. This leads us
%to suspect the chorus opens with a D. If you look at the sheet music, it actually
%opens with an octave of D's: D5 and D6 (the song is in D Major). If you find the
%frequency for that other peak, you will find it is close to 1174.66 Hz, the frequency for D6.
The code above will generate the following graphs.
Visible light is also a complex wave. Shining light through a prism breaks the light into it's component parts. Spectral analysis of light will reveal it's component frequencies. This is an Argon tube lamp (which emits a purple-blue color) and its spectra. Notice the vertical lines in the purple, blue, and teal sections of the spectra graph are bright. The brightness corresponds to the intensity or amount of that particular frequency.
There is still another problem. All of our displays (TVs, LCD panels, even CRTs) use RGB values to determine color. Linear combinations of red, green, and blue will result in all the colors of the color wheel. However, our displays to not factor intensity into these. Believe it or not, the screen you are looking at now is not capable of producing every visible color. This graph is from this amazingly useful site, which also includes source code for converting RGB <=> CIE color data.
Sound
All sound waves are complex waveforms, which are really just a sum of normal sinusoidal waves. When you play middle C on any instrument, the sound you make is not a pure 261.63 Hz sine wave. There are overtones and so forth that also sound based on the shape and design of the instrument, giving the note its timbre. The brilliant Joseph Fourier (the bane of all undergrad EE students taking Intro to Signal Processing) did a lot of work with complex waveforms, eventually leading to a whole branch of mathematics called Fourier Analysis. The major part of this is the Discrete Fourier Transform. Given a complex wave function f(x), solving the integral
results in a very interesting function which is able to pick out the component frequencies in the complex wave. Here is an example from MathWorks:
A small section of a wave which is the sum of a 120 Hz wave
with max amplitude 1, a 50 Hz wave with max amplitude .7,
and some random data added as noise.
|
There are handy sets of computer algorithms called Fast Fourier Transforms (FFT) which, as you might have guessed, are fast ways of approximating DFTs. The most popular example is FFTW, a C library which from what I understand, picks the best FFT algorithm based on the data given.
Here is a little example I did in MATLAB. I was able to determine the first note of the Hallelujah Chorus (Handel's Messiah), which is a sample file included with MATLAB:
%The file is now stored in y
sound(y) %listen to it to make sure it works%the sound function defaults to a sample rate of 8192 per second.
% If we double it, we double the tempo and frequency (chipmonks)
sound(y,16384)
plot(y) %this will show a graph of the waveform like you see in a music editing program
%Lets get just the first note ('HA-'). look at the plot. The section we
%want is from about 1667 to about 5000, so let's define a new sound array a
a=y(1667:5000,1);
%listen to see that it is just the first note
sound(a)
plot(a)
%now we can find the FFT for a. The following is from the MATLAB guide for%the fft() function, using this data instead of theirs.
Fs=8192; %The sample frequency
T=1/Fs; %Period=1/Frequency
L=size(a,1); %the length of the signal
NFFT = 2^nextpow2(L); %the next power of two after L
Y = fft(y,NFFT)/L; %our FFT data
f = Fs/2*linspace(0,1,NFFT/2+1); %f is the set of frequencies for the x axis of the graph
p = 2*abs(Y(1:NFFT/2+1)); %p is the set of amplitudes for the y axis of the graph
plot(f,p); %isn't it beautiful!?
%now, let's find out what note they are singing.
%find(p==max(p)) will return a set of indexes in p of the maximum value of
%p (which is the one we want, a little after 500 Hz). In this case, there is
%only 1 occurence, so we can dump it streight into f, as the corresponding
%freqency for this value is then the value of f at this index.
f(find(p==max(p)))
%this returns 572 Hz, which is very close to 577.33 Hz: D5. This leads us
%to suspect the chorus opens with a D. If you look at the sheet music, it actually
%opens with an octave of D's: D5 and D6 (the song is in D Major). If you find the
%frequency for that other peak, you will find it is close to 1174.66 Hz, the frequency for D6.
The code above will generate the following graphs.
Sound
Putting it together
We have complex sound waves split into component frequencies (notes) and their relative intensities (volume), and complex light waves split into component frequencies (colors) and their relative intensities (brightness). If we shift and translate our sound data from the human audio frequency range (roughly 12 Hz to 20 KHz) to human visual frequency range (390-750 nm wavelengths at the speed of light equate to 400-790 THz; 1 THz = 1 trillion Hz).
| The triangle is the limits of the RGB system, and the "tongue" is the full human visible spectrum in CIE coordinates. |
CIE stands for the International Commission on Illumination (where you aware there was one!?), which defined the CIE X Y Z color space. My knowledge on this is pretty limited. From Wikipedia:
The human eye has photoreceptors (called cone cells) for medium- and high-brightness color vision, with sensitivity peaks in short (S, 420–440 nm), middle (M, 530–540 nm), and long (L, 560–580 nm) wavelengths... These tristimulus values of a color can be conceptualized as the amounts of three primary colors in a tri-chromatic additive color model.
In this model, Y means luminance, Z is quasi-equal to blue stimulation, or the S cone response, and X is a mix (a linear combination) of cone response curves chosen to be nonnegative. Thus, XYZ may be confused with LMS cone responses. But in the CIE XYZ color space, the tristimulus values are not the L, M, and S responses of the human eye, even if X and Z are roughly red and blue. Rather, they may be thought of as 'derived' parameters from the long-, medium-, and short-wavelength cones.
While I still don't completely understand the coordinate system, the conversion article is quite good at explaining how to normalize color values not covered by RGB coordinates to something RGB can handle (see the section called "Unrepresentable Colors").
The good news is that this project can be done with two existing C libraries. I will work on actually getting this to work, and hopefully have a graph of a song's color over time. Eventually, I would like to make a device with a microphone and a cheap LCD that displays the color of whatever it is hearing. That is a much harder problem. First, you have to sample to have a wave function to do a FFT on. That means it will have to record a brief snippet of sound and chug through a bunch of math before displaying a color. Google searches suggest people have been able to write watered-down FFT algorithms that will run on 8MHz atmegas, so it might be possible for Arduino, but the processing time might be too high for a reasonably small sample time. I would settle for 3 samples per second, and be happy with 30 (a common framerate). 100 samples per second would be ideal. If an Arduino couldn't handle this, I'm sure my RPi (which, being an ARM processor, is 32 bit and has support for floats, unlike the atmegas) can.
Thursday, September 20, 2012
Microsoft's Impending Software Versioning Woes and a Solution
The release of Windows 8 is only a few days away. In an attempt to get into the mobile game, or rather, get competitive in the mobile game (Windows Phone? Really?), there will be versions of Win8 for ARM architecture, as well as traditional x86 and x86-64. I predict Microsoft is going to run into some problems on this front (on top the flack they are going to get from the unintuitive GUI and the locking of the bootloader), and offer an alternative.
In the last several years, as PCs transitioned from 32-bit to 64-bit architecture, there were some growing pains. Software that users used to be able to run wouldn't necessarily run after an upgrade, and vice versa. Microsoft did a somewhat decent job combating this with Compatibility Mode and Windows XP Mode (a tool too few users know about, in my opinion). But for the most part, 64-bit PCs could run 32-bit software, and to some extent, users started to learn the difference, and it wasn't so bad. x86 and x86-64 are very similar, apart from the data width, as x86-64 is just an extension of the x86 instruction set. Adding ARM to the mix is a different story. ARM is a completely different philosophy with a completely different instruction set. So what happens when a user buys their Win8 (ARM) tablet, expecting all their desktop software to run on it? (Hint: Vista-level user frustration all over again).
Let me stop for a moment and compare the extremes on how other systems deal with software across architecture. On one side, you have Apple. Every device they produce uses the same architecture (often the same processor), so software compatibility isn't a problem. Also, on their mobile platform, they have strict control over what software users can run on their devices. There are ways around this, but chances are, if you understand how to sideload iOS apps after a jailbreak, you know enough about software to not run into problems. It is a big deal when Apple switches architectures (as they did a few years ago, moving from PowerPC to Intel x86-64), and after that, they drop support for the old architecture completely.
On the extreme opposite is the Linux, etc. community. Software is distributed as source code, and users compile the code for their architecture. Because of this, there is a Linux kernel for every known architecture in existence, including some really obscure ones. Virtually any software can run on any system, as long as you have the source code and a compiler for your architecture. On the other hand, you also need a pretty firm grasp of compilers, such as creating makefiles and other things that are well over my head.
Microsoft seems to generally hold a philosophy that goes something like this: The end user doesn't know much about computers, and they don't need to know much to use one. Therefore we should (try to) make our products user-friendly and in the process protect the user from their own ignorance (otherwise they might break something or get a virus!). Let's ignore how generally unsettling a philosophy this is for me, and how often "user-friendly" software has been so locked down that it is unusable, and try and tackle the problem from their point of view.
Apple only allows one architecture at a time, and keeps tabs on available software. This isn't an option for MS if they want to compete in the mobile market without getting into the hardware business (and we know how bad Microsoft is at hardware). But MS has way too much value on Intellectual Property to ask developers to release their source code (and would never do it for their products), and furthermore, asking users to compile software violates the above philosophy.
So how about this:
Software installers (i.e. setup.exe files) contain the source code uncompiled but in an encrypted form. Also in the installer is a compiler or compiler library that has the private key for the source code hidden inside (this file is pre-compiled, so protecting the key should be trivial). When a user runs the install file, the compiler library checks the OS, processor, etc. and generates or looks up the correct compiling options for the system, decrypts and compiles the binaries, and then starts the regular install process (moving files, updating the registry, etc.). To the end user, this just looks like installing; they neither know nor care what is going on as the progress bar slides along (just as before) but now the same software runs on all their Windows devices, regardless of architecture. To the developer, they have always had to pre-compile software for Windows and create install files. The only difference now is exactly how that process works, but a wizard handles all the details (and oh, how Microsoft loves wizards). Their code is protected, just as it was as a compiled binary, but they don't have to compile and distribute a different version of their software for each combination of OS and architecture, and make sure their users get the right version.
This in theory would be a workable solution. Such a system could be implemented into Visual Studio, so even existing software could be distributed to mobile users, and versioning would no longer be an issue. Maybe someone with a deeper understanding of development for Windows can identify some problems with this solution, but I can't. Security might be a problem (as it always is with MS), but if the system is designed from the start with robust security in mind, even large developers of major, expensive, proprietary software (Adobe, etc.) could distribute this way without fear of a competitor (or worse, a pirate!) accessing the source code and reverse engineering the software. If anyone has any thoughts or comments, please share them.
In the last several years, as PCs transitioned from 32-bit to 64-bit architecture, there were some growing pains. Software that users used to be able to run wouldn't necessarily run after an upgrade, and vice versa. Microsoft did a somewhat decent job combating this with Compatibility Mode and Windows XP Mode (a tool too few users know about, in my opinion). But for the most part, 64-bit PCs could run 32-bit software, and to some extent, users started to learn the difference, and it wasn't so bad. x86 and x86-64 are very similar, apart from the data width, as x86-64 is just an extension of the x86 instruction set. Adding ARM to the mix is a different story. ARM is a completely different philosophy with a completely different instruction set. So what happens when a user buys their Win8 (ARM) tablet, expecting all their desktop software to run on it? (Hint: Vista-level user frustration all over again).
Let me stop for a moment and compare the extremes on how other systems deal with software across architecture. On one side, you have Apple. Every device they produce uses the same architecture (often the same processor), so software compatibility isn't a problem. Also, on their mobile platform, they have strict control over what software users can run on their devices. There are ways around this, but chances are, if you understand how to sideload iOS apps after a jailbreak, you know enough about software to not run into problems. It is a big deal when Apple switches architectures (as they did a few years ago, moving from PowerPC to Intel x86-64), and after that, they drop support for the old architecture completely.
On the extreme opposite is the Linux, etc. community. Software is distributed as source code, and users compile the code for their architecture. Because of this, there is a Linux kernel for every known architecture in existence, including some really obscure ones. Virtually any software can run on any system, as long as you have the source code and a compiler for your architecture. On the other hand, you also need a pretty firm grasp of compilers, such as creating makefiles and other things that are well over my head.
Microsoft seems to generally hold a philosophy that goes something like this: The end user doesn't know much about computers, and they don't need to know much to use one. Therefore we should (try to) make our products user-friendly and in the process protect the user from their own ignorance (otherwise they might break something or get a virus!). Let's ignore how generally unsettling a philosophy this is for me, and how often "user-friendly" software has been so locked down that it is unusable, and try and tackle the problem from their point of view.
Apple only allows one architecture at a time, and keeps tabs on available software. This isn't an option for MS if they want to compete in the mobile market without getting into the hardware business (and we know how bad Microsoft is at hardware). But MS has way too much value on Intellectual Property to ask developers to release their source code (and would never do it for their products), and furthermore, asking users to compile software violates the above philosophy.
So how about this:
Software installers (i.e. setup.exe files) contain the source code uncompiled but in an encrypted form. Also in the installer is a compiler or compiler library that has the private key for the source code hidden inside (this file is pre-compiled, so protecting the key should be trivial). When a user runs the install file, the compiler library checks the OS, processor, etc. and generates or looks up the correct compiling options for the system, decrypts and compiles the binaries, and then starts the regular install process (moving files, updating the registry, etc.). To the end user, this just looks like installing; they neither know nor care what is going on as the progress bar slides along (just as before) but now the same software runs on all their Windows devices, regardless of architecture. To the developer, they have always had to pre-compile software for Windows and create install files. The only difference now is exactly how that process works, but a wizard handles all the details (and oh, how Microsoft loves wizards). Their code is protected, just as it was as a compiled binary, but they don't have to compile and distribute a different version of their software for each combination of OS and architecture, and make sure their users get the right version.
This in theory would be a workable solution. Such a system could be implemented into Visual Studio, so even existing software could be distributed to mobile users, and versioning would no longer be an issue. Maybe someone with a deeper understanding of development for Windows can identify some problems with this solution, but I can't. Security might be a problem (as it always is with MS), but if the system is designed from the start with robust security in mind, even large developers of major, expensive, proprietary software (Adobe, etc.) could distribute this way without fear of a competitor (or worse, a pirate!) accessing the source code and reverse engineering the software. If anyone has any thoughts or comments, please share them.
Sunday, August 19, 2012
Chorded Keyboard
Since I had first been introduced to the wearable computing community, I have always wanted to build a chorded keyboard. I've had some basic design in my head for a while, but now that the hardware part has been started, I felt it was time for a post.
Simply put, a chorded keyboard is a keyboard device that you use with one hand, where different combinations of buttons ("chords") represent different keys on a keyboard. All the designs I have seen involve some bulky device you must either carry around or attach to your arm. They also have many buttons to increase the number of available chord combinations. I wanted a device that was not intrusive, easy to learn to use, and did not obstruct the use of my hand. Enter the glove.
I am building a glove where buttons are pressed by tapping them on a hard surface, such as a table. A conductive surface, such as conductive fabric, will be attached to the fingertips, and will act as capacitive switches. A small amount of fabric or foam will separate the fingertips from the plate, and the change in capacitance is measured (see Capacitive Sensing). As this is my first project in the "wearables" subgenre of DIY electronics, I had planed on using a LilyPad. However, I settled on the Teensy 2.0, which is much smaller, cheaper, and uses a ATmega32u4 instead, allowing native USB support (and can easily be made into a HID). The wearable community had a great suggestion of using crimp beads to attach smd devices to fabric. 4 LEDs will signal which mode the glove is in. There will also be a "soft-off" toggle switch (so I can pick up a pencil or open a door, for example).
The colored X's correspond to each possible chord combo. I am an avid Guitar Hero player, so I used the color codes from the game. The left column is the decimal form of each chord. Take, for example, chord 17: green and orange. 17 is 10001 in binary. As you can see, the first '1' means that green is pressed, the last '1' means orange is pressed, and the '0's mean the other respective keys are not pressed. Chords 3 and 17 I am using as mode switch chords. Pressing one of these two shifts the glove through each of the modes: standard, capital, arrows, and symbols.
So we currently have 5 bits that correspond to the chord itself. If we tack on two more bits to represent the current mode (standard = 00, capital=01, arrows=10, symbols=11), we are up to 7. To make it an even byte, I tacked on a final bit where '1' refers to a "special case" (either a mode switch chord or a keyboard shortcut, such as Alt+Tab). I generated all the combinations, and made a table matching them to the ASCII keyboard code (and I converted both to HEX so it was easier to look at). Both columns are a single byte. We are dealing with less than 128 pairs of bytes. Really what we need then is a database that the Teensy can use to lookup which keyboard command to send with which chord.
Fortunately, the Teensy (and all Ardunios and compatibles, I think) have 1 KB of EEPROM. EEPROM is perfect for this task. It is for long term data storage which needs to persist after the device is powered off (devices with firmware, such as your motherboard's CMOS, use EEPROM or similar stuff). Also, it is pretty fast to do a lookup, which will lighten the load on the microprocessor, which will need to be able ot listen for button presses and do other strenuous calculations really fast. The chord byte we generated can be the address in the EEPROM, and the data stored there is the ASCII byte to send to the keyboard.
Here is the sketch that writes and checks the firmware (it is just the EEPROM.read example sketch with a bunch of write() statements during setup):
Simply put, a chorded keyboard is a keyboard device that you use with one hand, where different combinations of buttons ("chords") represent different keys on a keyboard. All the designs I have seen involve some bulky device you must either carry around or attach to your arm. They also have many buttons to increase the number of available chord combinations. I wanted a device that was not intrusive, easy to learn to use, and did not obstruct the use of my hand. Enter the glove.
Hardware
I am building a glove where buttons are pressed by tapping them on a hard surface, such as a table. A conductive surface, such as conductive fabric, will be attached to the fingertips, and will act as capacitive switches. A small amount of fabric or foam will separate the fingertips from the plate, and the change in capacitance is measured (see Capacitive Sensing). As this is my first project in the "wearables" subgenre of DIY electronics, I had planed on using a LilyPad. However, I settled on the Teensy 2.0, which is much smaller, cheaper, and uses a ATmega32u4 instead, allowing native USB support (and can easily be made into a HID). The wearable community had a great suggestion of using crimp beads to attach smd devices to fabric. 4 LEDs will signal which mode the glove is in. There will also be a "soft-off" toggle switch (so I can pick up a pencil or open a door, for example).Software
Having only five fingers creates a problem for chorded keyboards. There are only 2^5 = 32 possible chord combinations with 5 buttons. If you subtract one (because the "null" chord, where no buttons are pressed, is unusable because that is when you aren't pressing anything!), we are down to 31 chord combinations. Considering there are 26 letters, we can see there certainly aren't going to be enough chords to emulate a full keyboard. The solution is the same as is used on phone keyboards (and traditional keyboards, for that matter): switchable modes.
The colored X's correspond to each possible chord combo. I am an avid Guitar Hero player, so I used the color codes from the game. The left column is the decimal form of each chord. Take, for example, chord 17: green and orange. 17 is 10001 in binary. As you can see, the first '1' means that green is pressed, the last '1' means orange is pressed, and the '0's mean the other respective keys are not pressed. Chords 3 and 17 I am using as mode switch chords. Pressing one of these two shifts the glove through each of the modes: standard, capital, arrows, and symbols.
I really need to point out that I am left handed (and planning to use this on my dominant hand), which explains the layout (PRMIT, for pinky, ring, middle, index, thumb; from left to right). If you are right-handed, and you want to build something like this, some software changes are probably necessary. I matched keys to chords, roughly such that more common letters have easier chords. I also tried to make them easy to remember. For example, 'm' is 11100, because the chord, green-red-yellow, looks like an upside-down 'm'. Similarly, 'w' is 01110 and 'n' is 01100. I then filled in symbols, numbers, and a few keyboard shortcuts in the remaining spots.
So we currently have 5 bits that correspond to the chord itself. If we tack on two more bits to represent the current mode (standard = 00, capital=01, arrows=10, symbols=11), we are up to 7. To make it an even byte, I tacked on a final bit where '1' refers to a "special case" (either a mode switch chord or a keyboard shortcut, such as Alt+Tab). I generated all the combinations, and made a table matching them to the ASCII keyboard code (and I converted both to HEX so it was easier to look at). Both columns are a single byte. We are dealing with less than 128 pairs of bytes. Really what we need then is a database that the Teensy can use to lookup which keyboard command to send with which chord.Fortunately, the Teensy (and all Ardunios and compatibles, I think) have 1 KB of EEPROM. EEPROM is perfect for this task. It is for long term data storage which needs to persist after the device is powered off (devices with firmware, such as your motherboard's CMOS, use EEPROM or similar stuff). Also, it is pretty fast to do a lookup, which will lighten the load on the microprocessor, which will need to be able ot listen for button presses and do other strenuous calculations really fast. The chord byte we generated can be the address in the EEPROM, and the data stored there is the ASCII byte to send to the keyboard.
Here is the sketch that writes and checks the firmware (it is just the EEPROM.read example sketch with a bunch of write() statements during setup):
/* * EEPROM Read * * Reads the value of each byte of the EEPROM and prints it * to the computer. * This example code is in the public domain. */ #include <EEPROM.h> // start reading from the first byte (address 0) of the EEPROM int address = 0; byte value; void setup() { // initialize serial and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only }
EEPROM.write(0,0x0);EEPROM.write(1,0x0); EEPROM.write(3,0x0);EEPROM.write(5,0x0); EEPROM.write(7,0x0);EEPROM.write(8,0x40); EEPROM.write(10,0x20);EEPROM.write(12,0x0A); EEPROM.write(14,0x30);EEPROM.write(16,0x6F); EEPROM.write(18,0x4F);EEPROM.write(20,0xD7); EEPROM.write(22,0x31);EEPROM.write(25,0x0); EEPROM.write(27,0x0);EEPROM.write(29,0x0); EEPROM.write(31,0x0);EEPROM.write(32,0x61); EEPROM.write(34,0x41);EEPROM.write(36,0xD9); EEPROM.write(38,0x2E);EEPROM.write(40,0x6C); EEPROM.write(42,0x4C);EEPROM.write(44,0xD6); EEPROM.write(46,0x3F);EEPROM.write(48,0x73); EEPROM.write(50,0x53);EEPROM.write(52,0x29); EEPROM.write(54,0x32);EEPROM.write(56,0x75); EEPROM.write(58,0x55);EEPROM.write(60,0x7D); EEPROM.write(62,0x2A);EEPROM.write(64,0x74); EEPROM.write(66,0x54);EEPROM.write(68,0xDA); EEPROM.write(70,0x2C);EEPROM.write(72,0x75); EEPROM.write(74,0x55);EEPROM.write(76,0xD3); EEPROM.write(78,0x21);EEPROM.write(80,0x64); EEPROM.write(82,0x44);EEPROM.write(84,0x5D); EEPROM.write(86,0x22);EEPROM.write(88,0x7A); EEPROM.write(90,0x5A);EEPROM.write(92,0x84); EEPROM.write(94,0x2B);EEPROM.write(96,0x6E); EEPROM.write(98,0x4E);EEPROM.write(100,0x28); EEPROM.write(102,0x27);EEPROM.write(104,0x79); EEPROM.write(106,0x59);EEPROM.write(109,0x0); EEPROM.write(110,0x3D);EEPROM.write(112,0x77); EEPROM.write(114,0x57);EEPROM.write(116,0x2F); EEPROM.write(118,0x33);EEPROM.write(120,0x6A); EEPROM.write(122,0x4A);EEPROM.write(124,0xD2); EEPROM.write(126,0x39);EEPROM.write(128,0x65); EEPROM.write(130,0x45);EEPROM.write(132,0xD8); EEPROM.write(134,0x36);EEPROM.write(137,0x0); EEPROM.write(139,0x0);EEPROM.write(141,0x0); EEPROM.write(143,0x0);EEPROM.write(144,0x68); EEPROM.write(146,0x48);EEPROM.write(148,0x5F); EEPROM.write(150,0x3A);EEPROM.write(152,0x67); EEPROM.write(154,0x47);EEPROM.write(156,0xB1); EEPROM.write(158,0x23);EEPROM.write(160,0x72); EEPROM.write(162,0x52);EEPROM.write(164,0x5B); EEPROM.write(166,0x3B);EEPROM.write(168,0x70); EEPROM.write(170,0x50);EEPROM.write(173,0x0); EEPROM.write(174,0x5E);EEPROM.write(176,0x66); EEPROM.write(178,0x46);EEPROM.write(180,0xC6); EEPROM.write(182,0x40);EEPROM.write(184,0x6B); EEPROM.write(186,0x4B);EEPROM.write(188,0x3C); EEPROM.write(190,0x7E);EEPROM.write(192,0x69); EEPROM.write(194,0x49);EEPROM.write(196,0x2D); EEPROM.write(198,0x37);EEPROM.write(200,0x62); EEPROM.write(202,0x42);EEPROM.write(204,0x7B); EEPROM.write(206,0x25);EEPROM.write(208,0x63); EEPROM.write(210,0x43);EEPROM.write(212,0x87); EEPROM.write(214,0x24);EEPROM.write(216,0x78); EEPROM.write(218,0x58);EEPROM.write(220,0x60); EEPROM.write(222,0x7C);EEPROM.write(224,0x6D); EEPROM.write(226,0x4D);EEPROM.write(228,0x5C); EEPROM.write(230,0x38);EEPROM.write(232,0x71); EEPROM.write(234,0x51);EEPROM.write(236,0x3E); EEPROM.write(238,0x26);EEPROM.write(240,0x8); EEPROM.write(242,0x8);EEPROM.write(244,0xD5); EEPROM.write(246,0x34);EEPROM.write(248,0xB0); EEPROM.write(250,0xB0);EEPROM.write(252,0xB3); EEPROM.write(254,0x35);EEPROM.write(255,0x0); Serial.println("Done writing. Reading:"); } void loop() { // read a byte from the current address of the EEPROM value = EEPROM.read(address); //Serial.print(address); //Serial.print("\t"); Serial.print(value, HEX); //Serial.println(); // advance to the next address of the EEPROM address = address + 1; // there are only 512 bytes of EEPROM, from 0 to 511, so if we're // on address 512, wrap around to address 0 if (address == 512) address = 0; delay(500); } Then, a new sketch actually reads the button presses, formats the chord byte correctly, and does an EEPROM lookup. The code is nothing near complete. The special cases are still missing, mode switching still isn't implemented, and the program is still printing to Serial instead of emulating a keyboard (I don't have a Teensy yet, so I'm using a Duemilanove, which doesn't have native USB support short of serial via FTDI, to test the software). It is also littered with comments of future features and removed test lines, without any sort of explanation of the current lines in most places. I will update the code when it is more functional. It uses bitwise operations as often as possible to maximize speed and keep variables byte-size (no pun intended) for EEPROM.
#include <CapSense.h> #include <EEPROM.h> CapSense cs_4_2 = CapSense(3,2); CapSense cs_4_6 = CapSense(7,6); CapSense cs_4_8 = CapSense(9,8); CapSense cs_4_10 = CapSense(11,10); CapSense cs_4_12 = CapSense(13,12); byte mode = 0; void setup(){ Serial.begin(9600); //wait for driver } void loop(){ byte recd = 0; long start=millis(); while(millis()<start+300){ recd = recd|listener(); } //Serial.print(cs_4_2.capSense(30));Serial.print("\t"); //Serial.print(cs_4_6.capSense(30));Serial.print("\t"); //Serial.print(cs_4_8.capSense(30));Serial.print("\t"); //Serial.print(cs_4_10.capSense(30));Serial.print("\t"); //Serial.print(cs_4_12.capSense(30));Serial.print("\t"); if(recd>0){ recd=recd<<2 +mode; recd=recd<<1; if (recd==0x18 || recd==0x88 || recd==0x1A || recd==0x8A || recd==0x1C || recd==0x8C || recd==0x6C || recd==0xAC || recd==0x1E || recd==0x8E){ recd=recd+1; specialkey(recd); }else{ sendkey(recd); } Serial.print("\t"); Serial.println(mode); } // for miliseconds // recd=listener(recd) //if recd not null //recd=bitwise shift << x2, add mode, bitwise shift<< //if recd=(list of special cases), add 1 //if first bit is 1, specialkey(recd) else sendkey(recd) } byte listener(){ byte held=0; if (cs_4_2.capSense(30) > 10){ held=held+1; }held=held<<1; if (cs_4_6.capSense(30) > 10){ held=held+1; }held=held<<1; if (cs_4_8.capSense(30) > 10){ held=held+1; }held=held<<1; if (cs_4_10.capSense(30) > 10){ held=held+1; }held=held<<1; if (cs_4_12.capSense(30) > 10){ held=held+1; } return held; } void sendkey(byte srecd){ //read eeprom, send key Serial.write(EEPROM.read(srecd)); } void specialkey(byte srecd){ //mode forward: 19, 1B, 1D, 1F //mode backward: 89, 8B, 8D, 8F //alt-tab 6D //ctlaltdel AD Serial.print("SPECIAL:\t"); //if(srecd==0x6D){Serial.println("alt-tab");} //if(srecd==0xAD){Serial.println("ctlaltdel");} //if(srecd==0x19 //|| srecd==0x1B //|| srecd==0x1D){Serial.println("up mode"); mode++;} // if(srecd==0x8B //|| srecd==0x8D //|| srecd==0x8F){Serial.println("down mode"); mode--;} //if(srecd==0x1F){mode=0;} //if(srecd==0x89){mode=4;} }
Thursday, July 26, 2012
Not the Cloud, the Hive
The cloud is evil.
It is a model of the internet that is fast approaching, and it is completely counter to the idea of the internet. In a cloud-based approach, data is stored by third parties. Companies like Google and Facebook, with vast server space and bandwidth, store your important data so you can access it anywhere, and distribute it to others. But there is a serious problem with that model. Companies are trying to make money, and as the internet ad bubble comes steadily closer to bursting (Facebook IPO, anyone?), companies turn to business models that aught to make you uncomfortable. They hold onto your data not just for you. Data is now a commodity, and companies use it to target advertisements or sell it to marketers and other interested parties. Furthermore, ISP's and other companies are often willing and able to give out user data to snooping governments.
The internet runs on a protocol stack called TCP/IP. Simply put, it is organized in a tree-like structure, where data goes higher up the tree until it reaches a common node with it's destination, and then trickles back down again. Consider for a moment just how many computers this page went through before it reached you. If you want to know exactly, open up a terminal window and type
To realize the solution, we have to look at a little internet sociology. At first, the internet was a very small group of ultra-nerds sharing files and ideas on newsgroups and BBS'es. As the internet's popularity rose, we saw a number of different communication systems become popular: email, forums, chat rooms. Recently, the boom has been in social media platforms. Notice that these are all about communications between real people; data transferred between users.
If Alice and Bob are in the same room and Alice wants to send a file to Bob, it goes from Alice's machine to the wireless router, which then has to find Bob before giving him the file. A generally faster method is for Alice and Bob to connect ad-hoc. Alice sends Bob the file directly, with no stops between. Add in another user, and all three can share a file freely. The one caveat is that each connection requires an individual wireless card. However, if each user has at least two connections, a stable mesh network can be built. Alice can pass a file through Bob to Chelsea. More importantly, however, is that if both Bob and Alice have a piece of data, it is easy for Chelsea to get a copy. This allows information to propagate by popularity, as it does in the real world.
Imagine a school with a mesh network running alongside traditional TCP/IP. Alice takes notes for a class, and can easily distribute them to her classmates. Bob read an article from The Huffington Post (which he got via TCP/IP), and now Chelsea doesn't need to connect to The Huffington Post (or any of the traditional internet at all) to read the article; she can get it from Bob.
Principles of sharing (which allows P2P to work) can lead to very fast data transfer that does not need to leave a local area. Every user can dedicate some space on their device to storing data from other users on the network. When they access data from another user, they have just increased the number of available copies of that data for other users. For files that might potentially be less popular, partial copies can be distributed across user's devices. Speed and network stability could be increased by adding nodes capable of connecting to several devices, avoiding network bottlenecks. They could be static like traditional wireless routers, or even be mobile (imagine a solar-powered UAV flying over campus, automatically maintaining network stability by creating new connections). Such systems are best suited for smaller, localized networks, but as wireless technology improves in range and speed, it is conceivable that such networks could replace the internet at large. If every car, train, cellphone, etc were a node, mesh networks could stretch cross-country. No need to pay for internet service.
There are a few major problems that need to be overcome. First, the more hops necessary, the greater the latency, which would need to be reduced if large networks are to exist. Second, security is an issue (as it always is). Storing other user's data on your device without your knowledge is potentially very dangerous. Several things can be done about this. For example, distributed data (such as incomplete files) make viruses in the form of binary files nearly impossible. A way to quarantine network storage from the host device would also improve security. Serious mathematics (across game theory, information theory, graph theory, and more) will be necessary to develop adaptive networks that can create new nodes and connections quickly, avoid congestion, and optimize searching and locating other users. Protocol stacks that include all of this need to be written. Some are in progress, although they still have issues. Hardware that is easy and cheap to deploy while still being capable of multiple high-speed connections will need to be developed.
The benefits of such a network are well worth the work in my opinion. It's decentralized, meaning reduced chance of surveillance by corporations and governments, as well as removing reliance on ISP's, which removes issues of network infrastructure, monopolies/duopolies, network neutrality, and more. The right implementations have the potential to be significantly faster than traditional TCP/IP (for the same reason that P2P is often the fastest way to distribute popular data). Finally, it is firmly rooted in the ideas of sharing and community, which is what the internet is all about.
If anyone, particularly in the Georgia Tech area, would like to help me develop a deployable mesh wireless network, let me know.
It is a model of the internet that is fast approaching, and it is completely counter to the idea of the internet. In a cloud-based approach, data is stored by third parties. Companies like Google and Facebook, with vast server space and bandwidth, store your important data so you can access it anywhere, and distribute it to others. But there is a serious problem with that model. Companies are trying to make money, and as the internet ad bubble comes steadily closer to bursting (Facebook IPO, anyone?), companies turn to business models that aught to make you uncomfortable. They hold onto your data not just for you. Data is now a commodity, and companies use it to target advertisements or sell it to marketers and other interested parties. Furthermore, ISP's and other companies are often willing and able to give out user data to snooping governments.
The internet runs on a protocol stack called TCP/IP. Simply put, it is organized in a tree-like structure, where data goes higher up the tree until it reaches a common node with it's destination, and then trickles back down again. Consider for a moment just how many computers this page went through before it reached you. If you want to know exactly, open up a terminal window and type
tracert blog.rabidaudio.comThe data squiggles through Google's web of servers, through a couple of ISPs and then back down through your ISP before arriving at your machine. Furthermore, Your computer had to talk to at least 6 (and probably closer to 15) different servers just to find the server that had the page in the first place (and that is if you are in the US!). Consider further that the tracert command doesn't count any of the (likely hundreds of) routers, switches, proxies, etc. (which are all essentially servers themselves) that had to pass each request along the line. Each step gives corporations and governments more opportunity to collect and potentially misuse your data.
To realize the solution, we have to look at a little internet sociology. At first, the internet was a very small group of ultra-nerds sharing files and ideas on newsgroups and BBS'es. As the internet's popularity rose, we saw a number of different communication systems become popular: email, forums, chat rooms. Recently, the boom has been in social media platforms. Notice that these are all about communications between real people; data transferred between users.
If Alice and Bob are in the same room and Alice wants to send a file to Bob, it goes from Alice's machine to the wireless router, which then has to find Bob before giving him the file. A generally faster method is for Alice and Bob to connect ad-hoc. Alice sends Bob the file directly, with no stops between. Add in another user, and all three can share a file freely. The one caveat is that each connection requires an individual wireless card. However, if each user has at least two connections, a stable mesh network can be built. Alice can pass a file through Bob to Chelsea. More importantly, however, is that if both Bob and Alice have a piece of data, it is easy for Chelsea to get a copy. This allows information to propagate by popularity, as it does in the real world.
Imagine a school with a mesh network running alongside traditional TCP/IP. Alice takes notes for a class, and can easily distribute them to her classmates. Bob read an article from The Huffington Post (which he got via TCP/IP), and now Chelsea doesn't need to connect to The Huffington Post (or any of the traditional internet at all) to read the article; she can get it from Bob.
Principles of sharing (which allows P2P to work) can lead to very fast data transfer that does not need to leave a local area. Every user can dedicate some space on their device to storing data from other users on the network. When they access data from another user, they have just increased the number of available copies of that data for other users. For files that might potentially be less popular, partial copies can be distributed across user's devices. Speed and network stability could be increased by adding nodes capable of connecting to several devices, avoiding network bottlenecks. They could be static like traditional wireless routers, or even be mobile (imagine a solar-powered UAV flying over campus, automatically maintaining network stability by creating new connections). Such systems are best suited for smaller, localized networks, but as wireless technology improves in range and speed, it is conceivable that such networks could replace the internet at large. If every car, train, cellphone, etc were a node, mesh networks could stretch cross-country. No need to pay for internet service.
There are a few major problems that need to be overcome. First, the more hops necessary, the greater the latency, which would need to be reduced if large networks are to exist. Second, security is an issue (as it always is). Storing other user's data on your device without your knowledge is potentially very dangerous. Several things can be done about this. For example, distributed data (such as incomplete files) make viruses in the form of binary files nearly impossible. A way to quarantine network storage from the host device would also improve security. Serious mathematics (across game theory, information theory, graph theory, and more) will be necessary to develop adaptive networks that can create new nodes and connections quickly, avoid congestion, and optimize searching and locating other users. Protocol stacks that include all of this need to be written. Some are in progress, although they still have issues. Hardware that is easy and cheap to deploy while still being capable of multiple high-speed connections will need to be developed.
The benefits of such a network are well worth the work in my opinion. It's decentralized, meaning reduced chance of surveillance by corporations and governments, as well as removing reliance on ISP's, which removes issues of network infrastructure, monopolies/duopolies, network neutrality, and more. The right implementations have the potential to be significantly faster than traditional TCP/IP (for the same reason that P2P is often the fastest way to distribute popular data). Finally, it is firmly rooted in the ideas of sharing and community, which is what the internet is all about.
If anyone, particularly in the Georgia Tech area, would like to help me develop a deployable mesh wireless network, let me know.
Friday, November 18, 2011
Fun with last.fm API
I am currently writing a program in python (using pylast) to analyze my last.fm plays and other data. I'm not sure currently everything I want it to do, but I would eventually like something that will chart plays over time for artists, tags, or all tracks over time. Normally, I wouldn't have posted something on it now, but to get my API access credentials from last.fm, I need to link to a site, so I will update this post as the project develops.
Music and Math ftw.
http://www.last.fm/api/account
EDIT: Here is my first Project: Tag percentages
Music and Math ftw.
http://www.last.fm/api/account
EDIT: Here is my first Project: Tag percentages
Thursday, November 17, 2011
An interesting case of digital property
Apparently, there is a new site called ReDigi that allows users to upload their unwanted, legally-acquired music tracks for credit, and resell these "used" tracks for less than most retail digital music stores. Apparently, they have an algorithm for determining if a track is the original file I hadn't heard of this site until Ars Technica did an article on the RIAA's expected negative response. They are currently demanding ReDigi cease and desist, pay restitution, and delete all content from their servers.
The interesting part here though is the legal philosophy. ReDigi claims protection under the right to sell provision:
When a user buys a track from Amazon, he is the legal owner of the particular copy. If he were to send a copy to a friend, that would be unauthorized distribution, and the recipient would not have legal ownership of the file. However, it would be highly unreasonable to claim that copying the file for personal use, such as moving it to other devices or playing it do not fall under fair use, considering that is why he bought the track in the first place. Do the same rules for transfer of ownership apply to digital objects the same way they apply to physical ones? According to the copyright law referenced above:
So, in a way, I guess I am actually defending the RIAA for once. Let me close with my thoughts on how the case should actually go, however. The RIAA has a case not in terms of their claim that by uploading files to their servers that ReDigi is making illegal copies, but instead in that there is not legal justification for the transfer of ownership of digital files. However, ReDigi should not be held responsible ex post facto, and the dying record industry certainly does not need restitution, and should not be able to dismantle a legitimate business the way they are trying.
The interesting part here though is the legal philosophy. ReDigi claims protection under the right to sell provision:
(a) Notwithstanding the provisions of section 106(3), the owner of a particular copy or phonorecord lawfully made under this title, or any person authorized by such owner, is entitled, without the authority of the copyright owner, to sell or otherwise dispose of the possession of that copy or phonorecord.The RIAA claims that in the process of acquiring the files from end-users, ReDigi is making a copy of the file, and therefore engaging in copyright infringement. Let's look at the actual technical level as to what is going on. When you move a digital file from one place to another (on different computers or the same, and independent of the technology used to transport), the data is read from the hard drive and copied into memory. It is then copied from memory to its destination, and then deleted from memory, and then deleted from the original hard drive location. Thus, the RIAA is technically right in saying that ReDigi is making a copy of the file. However, this same process occurs anytime you work with any digital files. Under this argument, Apple commits copyright infringement every time someone buys a track from their website, and the end user does every time they listen to the track or copy it to their device. So the question is, in a digital world, what constitutes a particular copy?
Copyright Act, Section 109(a).
When a user buys a track from Amazon, he is the legal owner of the particular copy. If he were to send a copy to a friend, that would be unauthorized distribution, and the recipient would not have legal ownership of the file. However, it would be highly unreasonable to claim that copying the file for personal use, such as moving it to other devices or playing it do not fall under fair use, considering that is why he bought the track in the first place. Do the same rules for transfer of ownership apply to digital objects the same way they apply to physical ones? According to the copyright law referenced above:
“Phonorecords” are material objects in which sounds, other than those accompanying a motion picture or other audiovisual work, are fixed by any method now known or later developed, and from which the sounds can be perceived, reproduced, or otherwise communicated, either directly or with the aid of a machine or device. The term “phonorecords” includes the material object in which the sounds are first fixed. Copyright Act, Section 101.Digital music files are not "material objects" and thus cannot fall under the Copyright Act, and thus, presumably there is no law regarding the transfer of ownership of digital files. Should these rights still apply? The RIAA's biggest legitimate concern is that it would be impossible to prove original ownership of files. This is because it is much easier to forge digital files than physical objects. If you placed meta-data in the file with regards to ownership, this could easily be removed, manipulated, or forged. You could protect these files with DRM software, but I have already discussed at length how this only hurts the legitimate owners, is easily overcome, and therefore drives people to piracy. Furthermore, I don't think we socially expect this right (and by socially, I mean the digital society). Admittedly, when I first heard of what ReDigi was doing, I laughed, because it seems absurd to think that you can prove legal ownership of data in a society like the internet where the entire goal is the spread and reproduction of data.
So, in a way, I guess I am actually defending the RIAA for once. Let me close with my thoughts on how the case should actually go, however. The RIAA has a case not in terms of their claim that by uploading files to their servers that ReDigi is making illegal copies, but instead in that there is not legal justification for the transfer of ownership of digital files. However, ReDigi should not be held responsible ex post facto, and the dying record industry certainly does not need restitution, and should not be able to dismantle a legitimate business the way they are trying.
Subscribe to:
Posts (Atom)




