Tagged: over the air

Optical Theremin - Demo

At Over The Air I demonstrated what I considered a novel use for one of Android's sensors. I wanted to create a Theremin - a type of musical instrument which is played by moving one's hand over it - changing pitch and tone by moving nearer or further away.

My first attempt used the proximity sensor. However, on all the Android phones I tried the sensor's accuracy was binary - it could sense if something was close by, but not say how close.

So, what else could I use to detect how near or far a hand was from the screen? I decided to co-opt the Light Sensor. This is normally used to automatically adjust the brightness of the screen - making it easier to see in strong light.

When the light sensor is uncovered, the total lux (that's the measure of light) may be 100. As a hand moves closer to it, that value will dip until it reaches 0 (or, on my phone, 4).

We can then represent that light value as a sound - essentially transforming lx into Hz!

This is what is sounds like


Beautiful, I'm sure you agree! You can hear an interview where I discuss this app with the BBC's Jamillah Knowles on the Outriders Podcast (22m 50s in).

If you want to have a play with it, the Optical Theremin Demo is in the Google App Store. Do note, it was coded in a couple of sleep deprived hours, crashes when you exit, and can produce "music" which scares children and animals. You have been warned!

Use The Source, Luke!

I've included the full source below, but I'd like to pick out two points which may be of interest.

Getting The Lux Value

Firstly, we need to register a listener for the light sensor.

@Override public void onCreate(Bundle savedInstanceState) {
  1. super.onCreate(savedInstanceState);
  2. mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  3. mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
  4. mSensorManager.registerListener(this, mLightSensor, SensorManager.SENSOR_DELAY_FASTEST);
  5. }

Every time the light sensor changes, this method will be called. It takes the light value and performs a simple mathematical transformation on it (adds 10, multiplies by 5). I found that this gave the most pleasing sound - but you can adjust it to your tastes

@Override public void onSensorChanged(SensorEvent event){
  1. if (event.sensor.getType()==Sensor.TYPE_LIGHT){
  2.  mLux = event.values[0];
  3.  freqOfTone = (mLux +10) * 5;
  4.  }
  5. }

Cum on Feel the Noize

So, how do we get Android to generate a tone? I faffed around with this audio generating code from StackOverflow until I could successfully generate a tone.

Essentially, this creates a WAV of a tone and gets it ready to play.

However, this sounded rather boring, so I added some reverb.

  1. audioTrack.attachAuxEffect(EnvironmentalReverb.PARAM_DECAY_TIME);

And that's it!

Download the Optical Theremin Demo App - or use the source to create something much more melodious.

Full Source

package mobi.shkspr.android.theremin;
  1.  
  2. import java.util.Random;
  3.  
  4. import android.app.Activity;
  5. import android.hardware.Sensor;
  6. import android.hardware.SensorEvent;
  7. import android.hardware.SensorEventListener;
  8. import android.hardware.SensorManager;
  9. import android.media.AudioFormat;
  10. import android.media.AudioManager;
  11. import android.media.AudioTrack;
  12. import android.media.audiofx.EnvironmentalReverb;
  13. import android.os.Bundle;
  14. import android.os.Handler;
  15. import android.util.Log;
  16. import android.widget.TextView;
  17.  
  18.  public class TheraminActivity
  19.   extends Activity
  20.   implements SensorEventListener{
  21.   // originally from http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-android.html
  22.   // and modified by Steve Pomeroy [email protected]
  23.  
  24.   private final int duration = 5; // seconds
  25.   private final int sampleRate = 8000;
  26.   private final int numSamples = duration * sampleRate;
  27.   private final double sample[] = new double[numSamples];
  28.   private double freqOfTone = 440; // hz
  29.  
  30.   private final byte generatedSnd[] = new byte[2 * numSamples];
  31.  
  32.   private SensorManager mSensorManager;
  33.   private Sensor mLightSensor;
  34.   private float mLux = 0.0f;
  35.   private String tLux = "Lux is ";
  36.  
  37.   public AudioTrack audioTrack;
  38.  
  39.   Handler handler = new Handler();
  40.  
  41.   @Override public void onCreate(Bundle savedInstanceState) {
  42.  
  43.    super.onCreate(savedInstanceState);
  44.    
  45.    
  46.    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  47.    mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
  48.    
  49.    mSensorManager.registerListener(this, mLightSensor, SensorManager.SENSOR_DELAY_FASTEST);
  50.    
  51.   }
  52.  
  53.   @Override public void onSensorChanged(SensorEvent event){
  54.    if (event.sensor.getType()==Sensor.TYPE_LIGHT){
  55.     mLux = event.values[0];
  56.     String luxStr = String.valueOf(mLux);
  57.     TextView tv = new TextView(this);
  58.     tv.setText(tLux);
  59.     setContentView(tv);
  60.     Random r = new Random();
  61.     freqOfTone = (mLux +10) * 5;
  62.    }
  63.    
  64.   }
  65.   @Override protected void onResume() {
  66.    super.onResume();
  67.    final Thread thread = new Thread(new Runnable() {
  68.     public void run() {
  69.      
  70.      for (int i = 0; i < 300; i++) {
  71.       genTone();
  72.      
  73.       audioTrack = new AudioTrack(
  74.           AudioManager.STREAM_MUSIC,
  75.           sampleRate,
  76.           AudioFormat.CHANNEL_OUT_MONO,
  77.           AudioFormat.ENCODING_PCM_16BIT,
  78.           numSamples,
  79.           AudioTrack.MODE_STATIC);
  80.      
  81.      
  82.        try {
  83.          
  84.         playSound();
  85.         Thread.sleep(505);
  86.        } catch (IllegalStateException e) {
  87.        
  88.        } catch (InterruptedException e) {
  89.         // TODO Auto-generated catch block
  90.         e.printStackTrace();
  91.        }
  92.      }
  93.     }
  94.    });
  95.    
  96.    thread.start();
  97.   }
  98.  
  99.   void genTone(){ // fill out the array
  100.    tLux = "Frequency is " + freqOfTone;
  101.    //Log.d("LUXTAG", "Lux value: " + tLux);
  102.    
  103.    for (int i = 0; i < numSamples; ++i) {
  104.     sample[i] = Math.sin(2 * Math.PI * i /(sampleRate/freqOfTone));
  105.    }
  106.  
  107.   // convert to 16 bit pcm sound array
  108.   // assumes the sample buffer is normalised.
  109.    int idx = 0; for (final double dVal : sample) {
  110.     // scale to maximum amplitude
  111.     final short val = (short) ((dVal * 32767)); // in 16 bit wav PCM, first byte is the low order byte
  112.     generatedSnd[idx++] = (byte) (val & 0x00ff);
  113.     generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
  114.  
  115.    }
  116.   }
  117.  
  118.   void playSound(){
  119.    genTone();
  120.    try {     audioTrack.attachAuxEffect(EnvironmentalReverb.PARAM_DECAY_TIME);
  121.     audioTrack.write(generatedSnd, 0, generatedSnd.length); audioTrack.play();
  122.    } catch (IllegalStateException e) {
  123.     audioTrack.release();
  124.    }
  125.   }
  126.  
  127.   @Override
  128.   public void onAccuracyChanged(Sensor sensor, int accuracy) {
  129.    // TODO Auto-generated method stub
  130.   }
  131.  
  132.   @Override
  133.   public void onPause() {
  134.    super.onPause();
  135.    audioTrack.stop();
  136.    audioTrack.flush();
  137.    audioTrack.release();
  138.   }
  139.  
  140.   @Override
  141.   public void onStop() {
  142.    super.onStop();
  143.    audioTrack.stop();
  144.    audioTrack.flush();
  145.    audioTrack.release();
  146.   }
  147.  
  148.   @Override
  149.   public void onDestroy() {  
  150.    super.onDestroy();
  151.    audioTrack.flush();
  152.    audioTrack.stop();
  153.    audioTrack.flush();
  154.    audioTrack.release();      
  155.   }
  156.  }

Over The Air 2012

Another brilliant event from Over The Air. The perfect mix of lectures, hacking, and relaxing in a country manor / museum. And, to top it off, my hack won a brace of prizes!

The Wifi just about held up. Although I think it's fundamentally impossible to provide decent connectivity to 200+ people. Especially when they're geeks.


It's people like @ that break conference Wi-Fi ;-) #ota12 http://t.co/DL2fIbfi
@dogsbodyorg
Dan Benton

Which, in turn, lead to this:


My data usage at #ota12 may have been a bit excessive... http://t.co/lVh5nSCN
@edent
Terence Eden

As per my post of two years ago, I tried to encourage people to record video or audio of the talks they were in. It was a reasonable success. We captured several great sessions, but others have been lost to the æther.

I honestly believe that BarCamps, unconferences, and hack-days are part of our culture and should be preserved. There's a selfish element in that I want to see the talks that I missed - but more than that, I want to ensure that what we're doing isn't lost forever.

So, here are my thoughts (and videos) of the day.

Everything You Know About QR Codes is WRONG!

The devilishly handsome Terence Eden gave one of his excellent talks upon the subject of QR codes.

I was really pleased with how this went, a packed room and lots of great questions. Thanks to Craig Heath for videoing it.

Responsive Web Design - the Specs Behind the Sex

Bruce Lawson talked through some of the issues with RWD especially when it comes to adaptive images.

My thoughts on the subject are still developing, but I think that it ought to be the server / CDN which adapts the images, rather than the handset relying on JavaScript and CSS. I've two primary reasons for this,

  1. There are billions of phones already on the market which don't support CSS or JS sufficiently to handle this. There's no realistic way to upgrade their browser.
  2. Programmers and web designers are lazy. I don't believe that the more complex mark-up will be used, nor that they will generate several different images.

A Means to Interact: A Guided Tour of Arts Programming Platforms

I must confess, I misread the subject of this talk - I thought it would be about artistic APIs. Instead, it was a fascinating talk about different ways to create graphics programatically. Becky Stewart stepped us through the pros and cons of each platform and showed us how they worked. I love interactive sessions - so coding along was great fun. She wisely distributed Windows, Mac, and Linux versions of the SDKs on memory stick so we wouldn't spend half the session downloading them.

Mobile Websites Can Have Nice Fonts Too

I'm a bit of a philistine when it comes to fonts. I have the vague feeling they're important, but I don't really know why - nor how to implement them on a website. Laura Kalbag to the rescue then!

After the session, I was talking to my friend Saqib (who is blind) about fonts. He wanted a better understanding of how they affected the reading of text.
I realised that fonts are like the background music in a film. It's the music which makes Star Wars as much as the dialogue and special effects. Imagine watching a Schindler's List with a jaunty comedy score - it would completely destroy the meaning of the film. As well as readability, picking a font changes the emotional engagement that a reader has with your text.

TheLab: Demo Cool Things!

I say! Those chaps from O2's TheLab are rather clever, aren't they? Just goes to show what a bit of ingenuity can do when applied to a telco. We saw a demo which tracked which country people were in based on whether their phone was roaming, HashBlue which backs up your text messages and provides an API to access them, and O2 Connect which routes your calls over WiFi if you're out of signal.
Evidently lots of smart thinking going on in Slough!

Connecting Microcontrollers to the Cloud

The guys from Vodafone were showing off mbed. It's a micro-controller similar to the Arduino. The idea is that you can rapidly prototype sensor data, send it via a data or SMS connection and do other cool stuff with it. The session I attended went into the C code behind it (which was a little over my head) as well as demoing practical uses for it. It's great to see kit electronics like this and the Raspberry Pi become popular - hopefully it will make hardware more accessible.

An Illustrated History of Computation

What a delightful session! Professor Bernie Cohen took us through a history of computing, mixed with personal anecdotes, and live algorithm solving. He seems to know a thing or two - I predict the lad'll go far!

ePatient 101: An Introduction to the Asymmetrical World of Technology and Healthcare

Mark Kramer (AKA Mamk) joined us via a dodgy Skype connection from the US, where he has just finished being treated for cancer.

Fuck cancer. Seriously, fuck it.
Mark was talking about the disparity between the technology which the medical profession has access to versus that of their patients. Doctors may have MRI machines - but they're often stuck with handwritten notes, or ancient PCs. Patients have more CPU power in their phones than a whole office full of medical staff.

Hacking

Over The Air is where geeks come to play. Some of the inventions on display were simply marvellous. I think there were 39 hacks presented - I'm going to highlight the ones I thought were exceptional.

Sam Machin built a tool to allow you to send tweets via a DNS lookup! As he said during his introduction:


"There are some regimes which block access to Twitter: Iran, Syria and the Hilton Hotel Group" #ota12
@olivia_solon
Olivia Solon

Without going into too much detail, you do a lookup on my-message-is-this.example.com, when the server receives the NS, it tweets on your behalf. So, as long as you can do a DNS request - even if the response is blocked - you can tweet. Amazing!

Tom Hume built an app which lets you post your call history on Facebook. It's not as creepy as it sounds! Remember "poking"? Well, a phone call is a private poke, in essence. So, your friends can see that you called X to wish them happy birthday.

Jatrobot was the scariest looking hack I'd seen!
Jatrobot
Herx The Vampire Slayer!
The team had built a modern farming tool. It measured soil moisture, weather, gps, and a bunch of other stuff via mbed - then reported it all back via Android.

Finally, my hack! This was the first time I'd entered a hack at OTA and I was unusually nervous!

I took inspiration from Ariel Waldman's mesmerising keynote about creating accessible interfaces to science. I was reminded of the Music of the Spheres (not the Doctor Who episode!) - which is the idea that the movement of the planets and celestial bodies can be thought of as a musical arrangement. We can also tune in to the background radiation of the universe and turn that into music. My phone doesn't have a gamma ray detector - but it does have a solar radiation sensor - the Lux Meter! It also has a proximity sensor - so it can tell how far away my hand is from the screen.

So, I created an ersatz Theremin! Having created a musical instrument (despite having no musical talent) I set about composing a work to be played via the medium of light.

Terence Playing the Theremin at OTA12
Edent theremin ota12

I'm chuffed to say it worked really well and the crowd seemed to like it!


Still liking @’s ‘Music of the Geeks’ on his android theremin. Beautiful. :) #OTA12
@Documentally
Documentally


@ got his Android to play music in response to hand waving & dancing in front of it. Great use of lux sensor & proximity sensor. #ota12
@hadleybeeman
Hadley Beeman


@ playing the music of the geeks. #ota12 http://t.co/WOS7NAyj
@ukandroid
Androidbloke Blogger


#OTA12 @ brings house down with smartphone music performance art :-)
@heathcr
Craig Heath


Things I liked @: @'s theremin app, @'s QR code talk, Bernie Cohen's computing history, @'s HTML5 & AppFire..
@duncancragg
Duncan Cragg


@ was fantastic... Want! (theremin 'proper' is my instrument on The List!)
@HelenArmfield
HelenArmfield


.@ just killed it at#ota12 - I want his app!
@MrPJEvans
PJ Evans

The app won one of the awards for Best Android App and was crowned Best In Show! Utterly gobsmacked, truly humbled, and over-excited to receive a Galaxy Nexus and a Raspberry Pi.

You can download the theremin and read all about the technology behind it.

Massive thanks to Dan, Maggie, Matt, and all the others involved in the highlight of the mobile geek calendar.

I cannot wait for next year!