« December 2007 | Main | February 2008 »

January 28, 2008

AJAX, browsers, and TextAreas

Hey open source develoeprs! Time to fix textareas with ajax. How many times have you lost an email, blog entry, any large chunk of text because it failed to upload when you hit submit? This is an indictment against software writers. Guess what, with ajax you can just save off the data periodically and automatically as a draft. No shit. I wish Movabletype did that (yes, I am pissed because I just lost an entry in my blog.) How about firefox, too. Just add a little extra cache that says, "Hey, I know something just went wrong. Want that data back?"

January 27, 2008

Football 2.0

Why bother hiring new NFL coaches each year? Save some money and just let the fans calls the plays using the Internet! Dan Snyder should like this. He can just hire some guys on the cheap to run practice, an actor to provide the correct motivation from the sideline (imagine your "coach" being Ed Harris or Denzel Washington), and use the wisdom of the crowd to call the plays. You can also cut out the offensive and defensive coordinators. Think of the profits! You could even charge people to participate.

But seriously, this could be done easily using a meaningless game like the All-Pro game in Hawaii. I realize the coaches want to go for the boondoggle, but who needs them? Just run the service through XBox live or the PS3 or a plain website and use the Madden play book. The fans have got to be better than the Dolphins staff.

Time Warner, wi-fi, and someone else's bill

Time Warner is going to bill you based on how much data you use. But is it really you using the data? Do you have a wifi network? Is it secure? It better be, if Time Warner provides your service. This came to mind because right now I am using an open wifi network to blog this. A couple of days ago I pulled down my monthly allotment of eMusic tunes over the same network- the download total was 662MB. Might this affect someone's bill? What if you were renting movies from Bittorrent and iTunes? Now we are talking serious usage.

Wifi network owners need to watch out. There are currently 7 people with DHCP addresses on this particular network. That's quite a few- I'm guessing only one is paying. Change your router password, too, or a griefer will get you.

January 26, 2008

Adventures in Facebook, part 2

Good news. I have no messages in my facebook in box. I am a non-entity. I'm pleased because when I had a MySpace account, I would routinely get requests for people to be my friend (disingenuous doesn't begin to explain MySpace). I quit.

Now on to finding friends in facebook. This works! Just found a high school buddy and saw half a dozen other people I recognized. The networks work well- you have to prove you belong, such as with an email address for a college. This is great and helps keep it legit. I did join my work network. I was surprised to see over 2,000 people from Sprint on facebook.

More importantly is that they are using Facebook discussion forums for important topics on the business.  Hopefully we can get the same spirit internally on our own community platform.

Back on topic. I started checking out facebook groups. They suffer the same problems as groups on any social site (like YouTube)- too many about the same thing. How many Sean Taylor RIP groups does DC need? I propose that one big group is better than several smaller ones (Metcalfe's law). But how is this done? Group creation should be moderated- that is manageable and would produce a better community. At the very least, the system should recommend to you similar groups to the one you are trying to create BEFORE you can create it. You should also have to explain why your group is different that the others like it.

BTW, Facebook is a clear winner in my opinion over the clutter and self-pimping on MySpace.

 

January 23, 2008

Attack of the spambots

I just checked the comments on my entry about Microsoft's failure to produce a decent phone OS. I had 32!! Oh boy- I must have really hit a nerve- Not. All were spam. All came in a 4 day window. I guess the pattern is meaningful.

My hypothesis:

Spambots wake up on a periodic schedule, run wild for a few days, then get shutdown to avoid discovery (assuming they are running on compromised machines).

I have to watch for this pattern again to confirm.

Or maybe I just blog about microsoft again- perhaps they are behind it?? Tongue out

January 18, 2008

Adventures in Facebook, part 1

Is facebook worth it? Is it superior to MySpace (which wouldn't be saying much)? I just joined today-

Let the games begin!

So far, the bullshit meter is pegging high (or I'm just stupid). I see an inbox at the top of my facebook page saying someone has a crush on me! OMG! And I only just joined. What a wonderful system.

See page

Turns out some zobes took the facebook look and feel and built and ad that looks like facebook but takes you to their crappy web site when you click on it. I guess that's what I get for being a facebook nube.

So, what I really need now is a facebook widget to strip out the ads. Wouldn't that be sweet. Of course, if would also destroy their supposed targeted advertising based business model (and a chunk of the $15B imaginary value) Oh, by the way, my facebook profile says I'm married and looking to network with people, not find a date. I guess that ad targeting algorithm is working real well.

Next up, finding friends in facebook.

January 17, 2008

The Soul of a Clone

Let's ask some hard questions. First, I pre-suppose there will be human clones.

  1. Will human clones be animate or just a meat bag used for spare body parts (like death row prisoners in China)?
  2. Will they be animate but not sentient (soul-less, like some non-human animal)?
  3. Will we, their creators, be able to control whether they are animate or not? Should we?
  4. Will they be citizens or slaves?

There is a bio-ethics community. I'd love to see them look ahead and propose some answers (or at least thought), rather than simple things like "of course clones will have souls" or equating twins to clones and using that to explain the soul factor.

By the way, I am glad stem cells are being made from lots of things that don't require human-sacrifice (i.e., a fetus). This proves I do have a soul.

January 10, 2008

Rookie phone OS mistakes- brought to you by Microsoft

Is Microsoft really a rookie when it comes to mobile phones? No, but they sure act like one. They have had soooo many phone and PDA OSes and still can't get it close to right. Maybe having so many IS the problem? Basic lack of focus.

So here are the lamest things on my new Motorola Q Smartphone with some odd flavor of Windows Mobile 6.

My phone has a missed call list, but doesn't say when the call came in.

You can download new applications (.cab files) using the browser, but cannot install them UNLESS they were specifically made for download/install on the phone. Why add the extra layer of confusion? So some apps that are cab files work, and some don't. Great.

For the ringer (which, by the way they do have cool free ringtones) you can choose vibrate or some sound but no vibrate with sound, which is the best option and works in crowds, or when you want your phone quiet, etc.

You can record voice memos and write text memos but the app doesn't integrate with the email client. To send the file you must find it (voice notes are in My Documents\notes). Remeber my rule:

If you can create it, you must be able to easily share it

The new voicemail indicator doesn't say how many messages you have or how many are new.

I downloaded a new ringtone from microsoft directly, but they installed it in the wrong place so I can't use it. Wow is that annoying.

January 07, 2008

Java Audio File Processing for loops and samples

Let's talk about sound. Making interesting new sounds is challenging- they even gives Oscars for it! I focus on making samples and loops for use with software like Sonar and Acid and my Alesis QSR. Here I will focus on the techniques for creating Alesis QCards I have developed over the years using the Java language. The truth is there are tools that do what I want, but I don't own them. I prefer to hack my own way.

The general process:
get a cool sound (such as from my custom java synthesizer, mini analog synths, bent toys, or other techniques)
turn it into a smoothly looping audio file (here I use Sound Forge)
set the audio file properties (see the RIFF file specification and my code samples) to make a file that the QSR will play as a loop when played from a midi keyboard
have fun with your unique sounds and make some music

I'm not planning to make much effort to explain the code below. If you are reading this, you can figure it out, but hopefully it is not easy ;) You should take a look at the RIFF specification. Go google it.

This snippet is called from a java class with a 'main' method from the command line. I actually use a batch file and run from a directory full of audio files to be processed. Key
points are that wav files are full of bytes of audio data, but 16-bit audio is composed of two byte values (I only deal with mono), so conversion is required.

  /*
     * This takes a regular wave file and adds the extra
     * data (smpl chunk) to it and makes it 'loop forward'. Takes two inputs:
     * file name and midi pitch (of the sample).
     */
    public static void convertWavToQSRLoop (String fileName, int midiPitch) throws IOException
    {
     //store the wav data in 16-bit sample format
     short[] data = null;
     //store the wav data in byte format
     byte[] dataChunk = null;
     //must read in the datachunk from the original file
     RandomAccessFile output = new RandomAccessFile(fileName, "rw");
        //skip to where the size of the data chunk is stored
     output.seek(40);
     //read the size
     byte[] size = new byte[4];
     output.read(size);
     int dataSize = getLittleEndianInt(size);
     //read in the byte audio data
     dataChunk = new byte[dataSize];
        output.read(dataChunk);
     //convert to short samples
        data = byteToShort(dataChunk);
        System.out.println("number of samples is " + data.length);
        //changed resulting file name
     writeMonoAudioLoop (data, "qsr_" + fileName, midiPitch);
    }
   

This is required to read certain 4 byte values from a data file (unless I'm totally stupid). I tried regular java techniques and they could not read the values properly. It is not simple enough to read and write integer values, since java use a platform independent technique but I use an Intel-based computer which uses little endian data formats.

    public static int getLittleEndianInt(byte[] bytes) throws IOException
    {
        //reverse
        byte b1 = bytes[0];
        byte b2 = bytes[1];
        byte b3 = bytes[2];
        byte b4 = bytes[3];
       
        bytes[0] = b4;
        bytes[1] = b3;
        bytes[2] = b2;
        bytes[3] = b1;
       
        //reverse and re-read
        DataInputStream bais = new DataInputStream(new ByteArrayInputStream(bytes));
        return bais.readInt();
    }
   
This converts an array of bytes from a file that represents audio data into an array of 16-bit audio samples.

    public static short[] byteToShort(byte[] data)
    {
        byte lsb;
        byte msb;
       
        short[] output = new short[data.length / 2];
       
        int index = 0;
        for (int i = 0; i < data.length; i+=2)
        {
         //read two bytes at a time( lsb and msb) and convert to a short. lsb is first (littleendian)?
            lsb = (data[i]);
            msb = (data[i + 1]);
           
            output[index++] = (short)((msb * 255) + lsb);
        }
       
        return output;
    }

Once you get the samples, it is time to write the file. Java Sound is used, somewhat. One trick is getting the pitch. This is non-trivial because many sounds/samples don't necessarily have a pitch. You must listen and compare OR use a guitar tuner and see what you get. Even so, you will likely have to fine tune the samples (+/- tens of cents) in your synthesizer patch editor to get them to be in tune.

    /**
     * For writing mono PCM wav files (CD quality) Key point to this method is that it
    * operates on an array of 16-bit audio samples (mono or stereo). Adds data for making loops.
     */
    public static boolean writeMonoAudioLoop (short[] data, String fileName, int midiPitch)
    {   
        return writeAudioLoop(data, fileName, MONO_WAV_CD, midiPitch);
    }   


The key to audio file modification is to use RandomAccessFile. Some file parameters change once you add the extra 'smpl' chunk data so you must go back and re-write them.

 /**
    * For use when other format is desired. Key point to this method is that it
    * operates on an array of 16-bit audio samples (mono or stereo).
    *
    */
    public static boolean writeAudioLoop(short[] data, String fileName, AudioFormat format, int midiPitch)
    {
        //convert short[] to byte[]
        byte[] byteSamples = shortToByte(data);
        //System.out.println("number of samples written to file= " + data.length);
                      
        AudioInputStream stream = null;
               
        // For encodings like PCM, a frame consists of the set of samples for all
        //channels at a given point in time, and so the size of a frame (in bytes)
        //is always equal to the size of a sample (in bytes) times the number of channels.
        RandomAccessFile output = null;

        try
        {
           
    /**
     * How to add the extra bytes to the audio file. First- open file with intent to append to
     * end of it. Second- create the data to append, based on know byte values to insert PLUS
     * knowledge about the size of the sample data chunk (need to know sample start/end points).
     * Write the new data to end of existing file and make other needed changes.
     *
     * Need to write a bunch of 4 byte little endian int values to the file. Only special value is the     * sample end value. Rest of values are zero- no shit.
     */

         File sampleFile = new File(fileName);
            stream = new AudioInputStream(new ByteArrayInputStream(byteSamples), format, data.length);
           
            AudioSystem.write(stream, AudioFileFormat.Type.WAVE, sampleFile);
            System.out.println("generated file " + fileName);
            stream.close();
            output = new RandomAccessFile(sampleFile, "rw");
            //add the new code to put in the "Loop forward" values in the sample chunk
            //data.length = number of samples (minus 1 is sample end point, I believe- zero based)
            //byes of data = data.length * 2 (data is short[])
           
            System.out.println("wrote samples=" + data.length);
            System.out.println("writing sample chunk info");
           
            int originalSize = (int)output.length();//OK to narrow
            output.seek(originalSize);//go to end of file?
            System.out.println("end of file=" + originalSize);
            output.writeBytes("smpl");//lowercase per the spec
           
            //must write little endian format- what's up? thought this would be the norm, but it is not.
           
            int sampleDataSize = 36 + 24 + (data.length * 2);
            //write chunks of 4 byte arrays
            output.write(getLittleEndianInt(60));//just the chunk data- not sample data size!!
            output.writeInt(0);//manufacturer- n/a
            output.writeInt(0);//product- n/a
            output.write(getLittleEndianInt(22675));//sample period- 1/44100 in nanoseconds       
            output.write(getLittleEndianInt(midiPitch));//midi unity note (sample root note)
            output.writeInt(0);//midi pitch fraction- 0 means no sample fine tuning
            output.writeInt(0);//smpte format- not used
            output.writeInt(0);//smpte offset- no offset
            output.write(getLittleEndianInt(1));//num sample loops- one
            output.writeInt(0);//sample data- no extra data needed so use zero
           
            //list of sample loops
            output.writeInt(0);//cue point ID
            output.writeInt(0);//type - the all-important "loop forward"
            output.writeInt(0);//start
            output.write(getLittleEndianInt(data.length - 1));//end (in samples)
            output.writeInt(0);//fraction of sample to loop at (not used)
            output.writeInt(0);//playcount; 0 = infinite sustain

            //change overall file size in original wav header!! -original plus 68.
            output.seek(4);
            output.write(getLittleEndianInt(originalSize + 68));
           
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return false;
        }
        finally
        {
         try
         {
          output.close();
         }
         catch (IOException e)
         {
          e.printStackTrace();
          return false;
         }
        }
       
        //if all went OK
        return true;
    }
 

Still with me? Files to download:

http://www.erichizdepski.com/code/AudioUtils.java

http://www.erichizdepski.com/code/QSRLooper.java

http://www.erichizdepski.com/code/WavReader.java

 

 

 


Hosting by Yahoo!