‹ SuperCollider Firmata serialAudio ›

audioSerial

2014-10-20 23:31 electronics, supercollider

clean-up: #56

Compared to generating a serial bitstream in audio, analysing and extract serial data from audio is much harder. The SuperCollider code below does it, but the program has limitations and is quite sensitive for noise.

The code takes a string, chops it up into groups of six 8bit bytes and generates a serial audio bitstream from that. Another part listens to this sound and tries to decode it. If it finds six full bytes it sends the result back to sclang via OSC where it is printed.

To test the example connect an audio cable directly from your computer's output to its input (preferably via a small mixer), or change the audioSerial SynthDef to use an internal audio bus. I can also imagine it could function with a mic next to the speakers - but I didn't test this.

If it only prints gibberish try with a different threshold setting, different volume on your computer or use a lower baud rate.

(
s.waitForBoot{
  var baudrate= 9600;
  SynthDef(\serialAudio, {|out= 0, amp= -0.5|  //for sending out serial via audio
    var data= Control.names([\data]).kr(Array.fill(60, 0));  //max 6 bytes
    var src= Duty.ar(1/baudrate, 0, Dseq(data), 2);
    OffsetOut.ar(out, src*amp);
  }).add;
  SynthDef(\audioSerial, {|in= 0, thresh= 0.05|  //for receiving serial via audio
    var raw= 0-SoundIn.ar(in);  //here change to In.ar if trying internal audio bus
    var src= raw>thresh;
    var reading= DelayC.ar(Trig1.ar(src, 1/baudrate*9), 1/baudrate/2, 1/baudrate/2);
    var osc= Phasor.ar(reading, baudrate/SampleRate.ir);
    var clock= (osc-Delay1.ar(osc))<0+Impulse.ar(0);
    var index= PulseCount.ar(clock, reading);
    var stopTrig= index>7;
    var data= Latch.ar(src, index>=#[7, 6, 5, 4, 3, 2, 1]);
    var byte= (1-data).sum{|x, i| 2**(6-i)*x};
    SendReply.ar(stopTrig, '/data', byte);
    DC.ar(0);
  }).add;
  OSCFunc({|msg| msg[3].asInteger.asAscii.post}, '/data');
  s.sync;
  Synth(\audioSerial);
};
)

(
var str= "hello supercollider!";
var baudrate= 9600;
fork{
  1.wait;
  str.ascii.clump(6).do{|bytes|
    var data= bytes.collect{|x| [1]++(1-x.asBinaryDigits.reverse)++[0]}.flat;
    s.bind{
      Synth(\serialAudio, [\data, data]);
    };
    (1/baudrate*60+0.005).wait;
  };
};
)

One can use this technique to communicate with another computer via audio. To communicate with a microcontroller (e.g. an Arduino), one needs additional electronics (amplification, rectification). Here's schematic for a bi-directional circuit for talking to a 5V Arduino.

This audio-to-serial technique was used to get input from RFID, touch and bend sensors in our Reflect installation i.e. SuperCollider is running on an iPod Touch and receives all sensor data via audio from an ATmega168 microcontroller.


‹ SuperCollider Firmata serialAudio ›