Shameless plug for my CD: Next Door Ninja – Noise is for Everyone

It has been a couple of months since it has been released, but I never did the shameless plug in here so here it goes:
I have gathered the outcome of my FAWM 2008 participation and put it on a nice CD format and it is available for sale through CD baby. So… if you are feeling adventurous, why not buy it? is cheap! :)

NEXT DOOR NINJA: Noise is for Everyone

Here are a couple of full tracks, for your enjoyment.

Mixed-up Logic [download]


Sunday Morning [download]

Also, for more music, my myspace page is http://myspace.com/nextdoorninja

Controlling a Gakken SX-150 synth with Arduino

The Gakken SX-150 is a really inexpensive analog synth (about $50, now available at the make store). This synth is included on a Japanese magazine (I wouldn’t expect less from them) so that makes it 2*2 times as cool.

Since its release, someone already has created a module to add midi support to it using the atmel attiny2313, but I’ve wanted to use an Arduino board to do it, to keep things easy to prototype and hack.

My implementation uses a single DAC IC chip, the MCP4921, which sells for about 2 bucks from Mouser. The current version uses the Arduino, only to read one byte, as a midi note, from the serial connection and sends that to the SX-150. I could have created the full midi circuit to make it a standalone solution, but that increases the cost and complexity of the physical connections. I’ll probably do that on a later revision.

So, in order to receive midi data, I wrote a small Processing sketch that receives midi, and sends the note information through the serial port to the Arduino.

The Arduino connection diagram looks like this:
arduinosx150diagram

And the final connections, like this:
arduinosx150-detail

arduinosx150

And.. the whole thing sounds like this:

On the video, I’m using Ableton Live to send midi data to the processing sketch using a Network Midi connection on the Mac. On windows, you should be able to use Midi Yolke to accomplish the same thing. Then, I make sure that the processing sketch receives midi on that same virtual midi connection and sends the data through serial to the arduino. So, depending on your system configuration, you might have to tweak the Processing sketch a little bit to make sure it is reading and writing to the right midi and serial ports.

The flow of data from the sequencer to the synth looks like this:
Ableton Live => Virtual Midi Connection => Processing Sketch => Serial Port =≶ Arduino => DAC => SX-150

And finally, the source code:

Now, hook it up and make some noise!

Simple class for getting Midi natively with Processing

So I started learning a little bit of Processing and as a first exercise, I wanted to do a visualization of the midi data from one of my songs. The most common midi library used with processing was not able to detect midi inputs on my mac, so I had to write my own class. I’m putting the code in here hoping that it can help someone else.

Oh, and some of the code was taken from here:

http://www.jsresources.org/examples/MidiInDump.html

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;

/*** MyMidi Class implementation ***/

class MyMidi implements Receiver {
  public int[] lastNoteOnByChannels = new int[16];
  public MyMidi()
  {
    
  }
  
  public long seByteCount = 0;
	public long smByteCount = 0;
	public long seCount = 0;
	public long smCount = 0;

	private final String[]		sm_astrKeyNames = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

	private final String[]		sm_astrKeySignatures = {"Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#"};
	private  final String[]		SYSTEM_MESSAGE_TEXT =
	{
		"System Exclusive (should not be in ShortMessage!)",
		"MTC Quarter Frame: ",
		"Song Position: ",
		"Song Select: ",
		"Undefined",
		"Undefined",
		"Tune Request",
		"End of SysEx (should not be in ShortMessage!)",
		"Timing clock",
		"Undefined",
		"Start",
		"Continue",
		"Stop",
		"Undefined",
		"Active Sensing",
		"System Reset"
	};

	private final String[]		QUARTER_FRAME_MESSAGE_TEXT =
	{
		"frame count LS: ",
		"frame count MS: ",
		"seconds count LS: ",
		"seconds count MS: ",
		"minutes count LS: ",
		"minutes count MS: ",
		"hours count LS: ",
		"hours count MS: "
	};

	private  final String[]		FRAME_TYPE_TEXT =
	{
		"24 frames/second",
		"25 frames/second",
		"30 frames/second (drop)",
		"30 frames/second (non-drop)",
	};
private char hexDigits[] = 
	   {'0', '1', '2', '3', 
	    '4', '5', '6', '7', 
	    '8', '9', 'A', 'B', 
	    'C', 'D', 'E', 'F'};


  public String getKeyName(int nKeyNumber)
	{
		if (nKeyNumber > 127)
		{
			return "illegal value";
		}
		else
		{
			int	nNote = nKeyNumber % 12;
			int	nOctave = nKeyNumber / 12;
			return sm_astrKeyNames[nNote] + (nOctave - 1);
		}
	}


	public int get14bitValue(int nLowerPart, int nHigherPart)
	{
		return (nLowerPart & 0x7F) | ((nHigherPart & 0x7F) << 7);
	}
        
        private void noteOn(int note, int velocity, int channel){
            lastNoteOnByChannels[channel] = note;
            System.out.println(note + " " + velocity);
        }

  public String decodeMessage(ShortMessage message)
	{
		String	strMessage = null;
		switch (message.getCommand())
		{
		case 0x80:
			strMessage = "note Off " + getKeyName(message.getData1()) + " velocity: " + message.getData2();
			break;

		case 0x90:
			strMessage = "note On " + getKeyName(message.getData1()) + " velocity: " + message.getData2();
                        noteOn(message.getData1(), message.getData2(), message.getChannel());
			break;

		case 0xa0:
			strMessage = "polyphonic key pressure " + getKeyName(message.getData1()) + " pressure: " + message.getData2();
			break;

		case 0xb0:
			strMessage = "control change " + message.getData1() + " value: " + message.getData2();
			break;

		case 0xc0:
			strMessage = "program change " + message.getData1();
			break;

		case 0xd0:
			strMessage = "key pressure " + getKeyName(message.getData1()) + " pressure: " + message.getData2();
			break;

		case 0xe0:
			strMessage = "pitch wheel change " + get14bitValue(message.getData1(), message.getData2());
			break;

		case 0xF0:
			strMessage = SYSTEM_MESSAGE_TEXT[message.getChannel()];
			switch (message.getChannel())
			{
			case 0x1:
				int	nQType = (message.getData1() & 0x70) >> 4;
				int	nQData = message.getData1() & 0x0F;
				if (nQType == 7)
				{
					nQData = nQData & 0x1;
				}
				strMessage += QUARTER_FRAME_MESSAGE_TEXT[nQType] + nQData;
				if (nQType == 7)
				{
					int	nFrameType = (message.getData1() & 0x06) >> 1;
					strMessage += ", frame type: " + FRAME_TYPE_TEXT[nFrameType];
				}
				break;

			case 0x2:
				strMessage += get14bitValue(message.getData1(), message.getData2());
				break;

			case 0x3:
				strMessage += message.getData1();
				break;
			}
			break;

		default:
			strMessage = "unknown message: status = " + message.getStatus() + ", byte1 = " + message.getData1() + ", byte2 = " + message.getData2();
			break;
		}
		if (message.getCommand() != 0xF0)
		{
			int	nChannel = message.getChannel() + 1;
			String	strChannel = "channel " + nChannel + ": ";
			strMessage = strChannel + strMessage;
		}
		smCount++;
		smByteCount+=message.getLength();
		return "["+getHexString(message)+"] "+strMessage;
	}
private String intToHex(int i) {
		return ""+hexDigits[(i & 0xF0) >> 4]
		         +hexDigits[i & 0x0F];
	}

public String getHexString(ShortMessage sm)
	{
		// bug in J2SDK 1.4.1
		// return getHexString(sm.getMessage());
		int status = sm.getStatus();
		String res = intToHex(sm.getStatus());
		// if one-byte message, return
		switch (status) {
			case 0xF6:			// Tune Request
			case 0xF7:			// EOX
	    		// System real-time messages
			case 0xF8:			// Timing Clock
			case 0xF9:			// Undefined
			case 0xFA:			// Start
			case 0xFB:			// Continue
			case 0xFC:			// Stop
			case 0xFD:			// Undefined
			case 0xFE:			// Active Sensing
			case 0xFF: return res;
		}
		res += ' '+intToHex(sm.getData1());
		// if 2-byte message, return
		switch (status) {
			case 0xF1:			// MTC Quarter Frame
			case 0xF3:			// Song Select
					return res;
		}
		switch (sm.getCommand()) {
			case 0xC0:
			case 0xD0:
					return res;
		}
		// 3-byte messages left
		res += ' '+intToHex(sm.getData2());
		return res;
	}



public String getHexString(byte[] aByte)
	{
		StringBuffer	sbuf = new StringBuffer(aByte.length * 3 + 2);
		for (int i = 0; i < aByte.length; i++)
		{
			sbuf.append(' ');
			sbuf.append(hexDigits[(aByte[i] & 0xF0) >> 4]);
			sbuf.append(hexDigits[aByte[i] & 0x0F]);
			/*byte	bhigh = (byte) ((aByte[i] &  0xf0) >> 4);
			sbuf.append((char) (bhigh > 9 ? bhigh + 'A' - 10: bhigh + '0'));
			byte	blow = (byte) (aByte[i] & 0x0f);
			sbuf.append((char) (blow > 9 ? blow + 'A' - 10: blow + '0'));*/
		}
		return new String(sbuf);
	}


  public void send(MidiMessage message, long lTimeStamp){
    //System.out.println("Message received");
    String	strMessage = null;
		if (message instanceof ShortMessage)
		{
			strMessage = decodeMessage((ShortMessage) message);
                        System.out.println(strMessage);
		}

  }
  
  public void close(){
  }

  public void printMidiDevices() {
    MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo();
    for (int i = 0; i < aInfos.length; i++) {
    try {
     MidiDevice device = MidiSystem.getMidiDevice(aInfos[i]);
       boolean bAllowsInput = (device.getMaxTransmitters() != 0);
       boolean bAllowsOutput = (device.getMaxReceivers() != 0);
       System.out.println("" + i + "  "
           + (bAllowsInput ? "IN " : "   ")
           + (bAllowsOutput ? "OUT " : "    ")
           + aInfos[i].getName() + ", " + aInfos[i].getVendor()
           + ", " + aInfos[i].getVersion() + ", "
           + aInfos[i].getDescription());
    }  
    catch (MidiUnavailableException e) {
       // device is obviously not available...
       System.err.println(e);
    }
  } 
  
    }
    MidiDevice inputDevice = null;
    Transmitter t = null;
    Receiver r = null;
    public void openForInput(int idx){
        try{
          MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo();
          inputDevice = MidiSystem.getMidiDevice(aInfos[idx]);
          inputDevice.open();
          t = inputDevice.getTransmitter();
          t.setReceiver(this);
        }catch(MidiUnavailableException e){
          System.err.println(e);
          
        }
    }

}
/* end of MyMidi Class */


MyMidi myMidi;

void setup(){
  size(480,360);
  myMidi = new MyMidi();
  myMidi.printMidiDevices();
  // Set the index of the device to open for input according
  // to your system
  myMidi.openForInput(0);
}

void draw()
{
  background(255);
  if(myMidi.lastNoteOnByChannels[0] != 0){
    translate(width/2, height/2);
    rotate(myMidi.lastNoteOnByChannels[0]);
    rect(-10,-10,20,20);
  }
}

FAWM 2008 – My entry so far

FAWM (February Album Writing Month) is a yearly community challenge to write 14 songs (a complete album) in February. 14 songs, that’s a song every 2 days, at least. This is the perfect excuse for me to produce stuff, no matter if it is good or bad. Here’s what I’ve done so far (this list will get update as February goes along.)



Next%20Door%20Ninja
Quantcast

Also, here is my myspace page http://myspace.com/nextdoorninja

The importance of having an open relationship with your IDE.

IDE’s: you either love them or you hate them, but there is no question about it: they do make a developer’s life easier. Developers that are really good with such a tool can seriously count on them being an extension of their body, an invisible limb, a partner. They physically hurt when the IDE crashes, they clean it, take care of it. But is this good or bad? Are developers leaving part of their brain on software? I think so. The worst part if they leave it there for too long they might not get it back.
Technology changes way too rapidly for programmers to develop such a strong relationship with a tool like this. Is this relationship beneficial? Absolutely, but you have to be ready to dump your software partner at a time when you least expect it. I know of stories where broken software hearts means having to change jobs.
The beauty of this relationship is that cheating on your IDE does actually benefit you as a developer. Besides, the IDE won’t get mad at you, even if it finds out. So my fellow developers, free yourselves. Play with other IDE’s, languages, techonologies and don’t be afraid. Times change rapidly, embrace change.

That1Guy, taking the one man band to the next level

I just came back from another great High Sierra and saw some excellent bands, but the ones they always stick up are the ones that do something unique. This year, the uniqueness prize (i.e. ultra-super-freak) went to That1Guy.

His main instrument is a home-made invention he calls “The Magic Pipe”, an industrial looking steel pipe contraption that has two ends, where he either plays bass or lead (and he is pretty damn good at both). The 2 strings have an amazingly natural envelope filter like sound, which comes out just as if he was playing a synth bass.

Apart from the strings on the pipe, he has an assortment of midi sensors. There are 13 of them alone on the Magic Pipe and who knows how many more on bass-drum-pedal-driven-cowbells and a single snare that gets no compassion during the live show.

His music is a refreshing mix between crazy funk and industrial, that can easily drive a crowd insane. And, the lyrics are a perfect extension of his instruments: definitely nuts. Don’t believe me? check out this video.

Playing JawBreaker with your friends’ head

I wrote this little game a couple of months ago and get a kick out of it every I see the main page. It is a clone of the JawBreaker game that comes with PocketPC, but I changed the “balls” with some friend’s heads. If anyone wants their own custom version (with the heads of _your_ friends instead) drop me a line.

You can click on the images to download the game.