Mobile Photography

What is the best camera?

Why is the iPhone the top camera on Flickr? Most Popular Cameras in the Flickr Community

Mobile phones have cameras built in that rival the best point and shoot cameras out there. Some even have optical zoom, built-in flashes and so on.

Not only capture but … (capture, storage, editing, viewing, sharing)

Impossible before, possible now:

Polaroid Android

Say, Can You Make Phone Calls on That Camera?

HDR 35 Fantastic HDR Pictures

Instagram

What about?

Cameras, the new lighter

The rise of the camera-phone
Everywhere you go these days, there are people with camera-phones – many of us record, document, and upload the minutae of our lives. But, ultimately, should we be doing it just because we can?

Why are we compelled to document everything? Are we missing anything in the process?

What about privacy? Activism/Protest? Surveillance?
Illicit photos?

Vancouver Riot Identify Suspects
Arab Spring
Remove Location Information on Photos

Audio Synthesis

Android has a built-in class called AudioTrack that can be used to play or synthesize audio.

Here is a code snippet:

final int SAMPLE_RATE = 11025;
int minSize = 0; 
short[] buffer = {8130,15752,22389,27625,31134,32695,32210,29711,25354,19410,12253, 4329,-3865,-11818,-19032,-25055,-29511,-32121,-32722,-31276,-27874, -22728,-16160,-8582,-466};

boolean playing = false;

android.media.AudioTrack audioTrack;
    
void setup() {
  minSize = android.media.AudioTrack.getMinBufferSize(SAMPLE_RATE, android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO, android.media.AudioFormat.ENCODING_PCM_16BIT);
  
  audioTrack = new android.media.AudioTrack(android.media.AudioManager.STREAM_MUSIC, 
    SAMPLE_RATE, android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO, 
    android.media.AudioFormat.ENCODING_PCM_16BIT, minSize,
    android.media.AudioTrack.MODE_STREAM);
    
  audioTrack.play();
  
}

void draw() {

}

void mousePressed() {
  if (!playing) {
    playing = true; 

    while (true) { 
      audioTrack.write(buffer, 0, buffer.length);
    }
  }
}

If you run this, it should generate a static tone but you will notice a couple of problems. The first is that the app becomes unresponsive and the second is that Android wants you to quit it.

This is because we are running the sound playback in an infinite loop and it is tying up the “UI thread”.

A Thread is a concurrently running piece of code that your program can create to handle tasks that would otherwise occupy the main part of the program. In a sense, it is running these other portions of your program in the background, simultaneously. Of course, this is a very simplified explanation, see Java’s Thread documentation and the Wikipedia Thread article.

What we really want to do is run the audio playback on a separate thread.

AudioSynth Class:

class AudioSynth 
{
  final int SAMPLE_RATE = 11025;
  int minSize = 0; 
  short[] buffer = {8130,15752,22389,27625,31134,32695,32210,29711,25354,19410,12253, 4329,-3865,-11818,-19032,-25055,-29511,-32121,-32722,-31276,-27874, -22728,-16160,-8582,-466};
  android.media.AudioTrack audioTrack;
        
  boolean keepGoing = false;


  public AudioSynth() {

    minSize = android.media.AudioTrack.getMinBufferSize(SAMPLE_RATE, android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO, android.media.AudioFormat.ENCODING_PCM_16BIT);
  
    audioTrack = new android.media.AudioTrack(android.media.AudioManager.STREAM_MUSIC, 
      SAMPLE_RATE, android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO, 
      android.media.AudioFormat.ENCODING_PCM_16BIT, minSize,
      android.media.AudioTrack.MODE_STREAM);
  }
  
  public void stop() {
    keepGoing = false;
  }
  
  public void play() {
    keepGoing = true;
    audioTrack.play();				
  
    new Thread(new Runnable() {
      public void run() {
        while (keepGoing) {
           audioTrack.write(buffer, 0, buffer.length);
        }
        audioTrack.stop();
      }
    }
    ).start();
  }
  
  void setBuffer(short[] newbuffer) {
   buffer = newbuffer; 
  }
}

Main Processing Sketch:

boolean playing = false;
AudioSynth synth;
    
void setup() {
  synth = new AudioSynth();      
}

void draw() {

}

void mousePressed() {
  if (!playing) {
    playing = true; 
    synth.play();
  } else {
    playing = false;
    synth.stop(); 
  }
}

Now that’s all well and good but what if we want to dynamically generate the sound to play?

Here is a really annoying version:

boolean playing = false;
AudioSynth synth;
    
void setup() {
  synth = new AudioSynth();  
  synth.play();  
}

void draw() {

}

void mousePressed() {
  short[] buffer = {(short)(mouseX*100),(short)(mouseY*100)};
  synth.setBuffer(buffer);
}

In many cases, people will use math to generate samples. Here is a sine wave (at mouseX frequency):


boolean playing = false;
AudioSynth synth;
    
void setup() {
  synth = new AudioSynth();  
  synth.play();  
}

void draw() {

}

void mousePressed() {
  short[] buffer = new short[synth.minSize];
  float angle = 0;
  float angular_frequency = (float)(2*Math.PI) * mouseX / synth.SAMPLE_RATE;
    // 2 x PI is the angle in radians of 360 degrees
    // multiply that by the mouseX/frequency of samples, you get the angle in radians of a specific frequency (C, 440Hz)
    // http://www.motionscript.com/mastering-expressions/simulation-basics-1.html
    
  for (int i = 0; i < buffer.length; i++)
  {
    buffer[i] = (short)(Short.MAX_VALUE * ((float) Math.sin(angle)));
    angle += angular_frequency;
  }  
  
  synth.setBuffer(buffer);
}