Friday, May 4, 2012

Cure your hangover by preventing it with DrinkPacer for iOS




I made a new app called DrinkPacer and it's the solution to cure hangovers by preventing them the night before.

Friday, February 10, 2012

Running Dropbox Referral ads got me banned from Adwords

NOTE: My blog has now moved.  Please visit my new blog where I write about audio apps, diy synthesizers, and CNCs.

This is a short tale of warning for those who are considering running their Dropbox affiliate link in Adwords ads to get the full 10 gigs of free space.

I did this and it cost me my Adwords account.

I had never used Adwords before so I opened a new account and used a $100 free credit coupon.  I ran ads similar to those provided by the guides on how to do this.  Nothing extremely spamming, just connecting with phrases like "free storage" and "free cloud backup" and ads with copy like "Download and get 2GB space free!".

As an aside, if you decide to ignore my warning: Put the words "download app" in your ad.  Before I did that I had more clicks but less referrals since Dropbox requires the app installed to count the referral.  Telling the user they'd have to download the app reduced my click's but increased signups, saving me money.

Anyways, all was well.  I ended up with 10 gigs of space, and still had $10 left of Adwords credit.

Until I received this email:

"Dear AdWords Advertiser,

Google maintains a high standard for the quality of our advertisements and our user experience. We have recently determined that your business maintains multiple AdWords accounts simultaneously serving ads for similar or related keywords and/or businesses.

In addition, our records indicate that some or all of these accounts were opened using promotional coupons limited to one redemption per individual or business. As a result, we have suspended your AdWords accounts and would ask that you refrain from creating additional accounts using other AdWords promotional coupons that you may already possess or obtain in the future.

Sincerely,
The Google AdWords Team"

Ouch.

Reading the letter, it makes sense: From their perspective a bunch of new Adwords accounts are being created, using coupons, and all advertising the same website.  Fraud!  Ban them!

And they did.




Blatant Ad: Want to DJ on your Android device or HP TouchPad? Get DJPad:
For Android: Pro | Lite
For WebOS: Pro | Lite


Saturday, February 4, 2012

DJPad: Android DJ App Now Available On Market

After a night of beer & coding I'm proud to announce that DJPad has been ported Android and is available on the Android Market!

DJPad is now an Android DJ application!

DJPad Full on Android Market

DJPad Free on Android Market

For more information check out my new software & eventually hardware company's website Burns Modular

Sunday, January 22, 2012

DJPad DJ app for HP TouchPad: Demo Video!

With my morning coffee I made a little demo video of DJPad today.

DJPad is available for sale right now: DJPad on the WebOS App Store

Sunday, January 8, 2012

DJPad: WebOS DJ App for HP TouchPad released!

I have just released a DJ app for the TouchPad. It's called DJPad and it's available right now in the App Store.

https://developer.palm.com/appredirect/?packageid=com.tugbits.djpad

It's a 100% PDK app and is very fast. It gets around 40ms latency on the TouchPad. I wrote my own DSP routines.

In it's current form it is rather barebones. As long as the app sees support I will add features.

Right now it features:
- plays 2 MP3s with +/-8% pitch control and simple (set, recall) cue points.
- mixer with 3 band EQ, crossfader, auto-normalization
- simple "Scratch" ability (drag finger over waveform)

I have a ton of plans for features including:
-split L/R output for cueing in one ear / master mix in the other, or for deck 1 out L and deck 2 out R for using an external mixer.
- better, configurable GUI with parallel waveforms and circular "scratch" discs.
- FX
- proper playlist support, with auto-mix functionality

Please download and rate, and most of all.. if you buy it and are unhappy please request features and I will see what I can do!


For feature requests please use the forum thread on WebOS Nation.


Friday, December 2, 2011

Decoding the Korg Monotribe Firmware Upgrade

NOTE: My blog has now moved.  Please visit my new blog where I write about audio apps, diy synthesizers, and CNCs.

NOTE: This is still a work in progress.  Keep watching the blog & github as we figure out more of the file encoding.

Korg released a firmware update for the monotribe.  It's an audio file that you play to the sync input of the monotribe.  Interesting, yeah?  Let's take a look at the content of the file and see how far we can get towards disassembly.  This would be the first steps towards a custom firmware for the korg monotribe.

The tutorial assumes you're running ubuntu linux, but any OS should be fine.  Just use your preferred methods to get the utilities we're going to use.

The firmware is delivered as an stereo m4a file.  We want a binary object file.

First, convert to a .wav with the free utility "faad":


sudo apt-get install faad
faad -o monotribe-fw.wav MONOTRIBE_SYS_0201.m4a

Before loading it into python lets also make a raw version of the file and just glance at the data to get an idea of what's up.

faad -f 2 -o monotribe-fw.raw MONOTRIBE_SYS_0201.m4a
hexdump -C monotribe-fw.raw | head -n 40
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000700  f7 ff f7 ff 18 00 18 00  e5 ff e5 ff 24 00 24 00  |............$.$.|
00000710  e5 ff e5 ff 1d 00 1d 00  de ff de ff 12 00 12 00  |................|

First of all we see each sample is 2 bytes, and most likely little endian.  Remember that there were 2 channels?  The upload process would be very finicky if it depended on a different sample on the L and R channels, and if you look here, it definitely appears that the L and R samples are always the same.

What I'm expecting is that the wave content will mostly look like a squarewave, and that we're sending a serial data stream of 1's and 0's which the firmware reconstitutes, checksums, and writes to the onboard flash.

Looking at the wave in audacity, this appears correct:



Let's remove one channel so we can process the samples easier in python.

sox monotribe_fw.wav -c 1 monotribe_fw1.wav mixer -l

Time to fire up the python interpreter and play with some data!  We will use the wave library to decode the audio.


python
Python 2.7 (r27:82500, Apr 14 2011, 00:58:22)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.


>>> import wave
>>> fw = wave.open("monotribe_fw1.wav", "r")


>>> fw.getframerate()
44100
>>> fw.sampwidth()
2

Yup!  Looks like our data.  Lets read the first few samples.


>>> fw.readframes(8)
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

After looking at the waveform in audacity it's clear that the wavefile is not a perfect squarewave with only values at -1 and +1.  We need our data normalized over time.  It looks like near the start of the file is a pure squarewave, probably to get the monotribe to sync to the playback rate.

We are going to ingest this waveform in a similar way that the monotribe does.  First, we'll categorize every sample as being either a 1, 0.  Then we'll group the sampled 1's and 0's to decide what the next bit is of the firmware.

Note that at this point we could be wrong and a 1 could be a 0 or vice versa.  I'm just using that as a guess right now.


# convert the variable data to either a 1 or a 0.
from struct import unpack
fw.rewind()
s = fw.readframes(1)
samplestr = ""
while not s == "":
   val = unpack("h", s)[0]
   if (val > 0):
      samplestr += "1"
   elif (val < -0):
      samplestr += "0"
   s = fw.readframes(1)
 
Let's dump this to a file in case we screw it up:

f = open("samplestr", "w")
f.write(samplestr)
f.close()

 We have to do a bit of fuzzy processing to turn (batch of 1 samples) into a single 1, and (batch of 0 samples) into a single 0.  But how long are the batches that represent a single bit?  I'm a BASH man for string processing, so into the shell we go.

Let's break the file into separate lines of sequential 1's and 0's:

cat samplestr | sed 's/10/1\n0/g' | sed 's/01/0\n1/g' > lines

Now let's build a histogram of sequence lengths:

cat lines | sort | uniq -c
     21 0
      8 00
      2 000
      3 0000
 170376 00000
      1 0000000
 160543 0000000000
     20 1
      8 11
      2 111
      4 1111
 170375 11111
      1 111111
      1 1111111
 160543 1111111111

Now before we go any farther lets look at the data.

*snip...*
11111
00000
1111111111
0000000000
11111
00000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
*snip...*

Interesting.  Looks like there's two signals - a "short square wave" that lasts 10 samples, and a "long square wave" that lasts 20 samples.    Maybe a short wave is a 1, and a long wave is a 0? Or vice-versa?  First lets assume everything else is garbage and all we want is a sequence of numbers that denotes the order of "long wave, long wave, short wave, long wave"... etc.  We can get rid of all the 0's since they're duplicate data for indicating if the bit is set, so filter down to just the 1 lines.

cat lines | grep '^11111$\|^1111111111$' > bitlines
cat bitlines | sed 's/^11111$/0/' | sed 's/^1111111111$/1/' > bits

Now 'bits' is a file with either a 1 or a 0 on every line.  Let's try converting that to a binary file and see if it looks recognizable.

in Python:
from struct import pack
f = open("bits", "r")
finished = ""
i = 0
f.seek(0)
str=""
for b in f.readlines():
    if b[0] == "0":
       str = "0" + str
    elif b[0] == "1":
       str = "1" + str
    i+=1
    if i == 8:
       finished += pack("B", int(str, 2))
       i = 0
       str = ""


f = open("firmware", "w")
f.write(finished)
f.close()

Let's look at the data now...
*
000004e0  00 01 6a 2d 0d b5 1d fb  35 65 35 d5 5d 4d fb 9d  |..j-....5e5.]M..|
000004f0  6d cd 5d 00 1b e4 ff ff  00 bf 7f ff ff ff ff ff  |m.].............|
00000500  ff ff ff e1 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000510  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000006f0  00 00 00 00 00 00 00 00  b5 7f fd ff fd a7 bf ff  |................|
00000700  ff 89 bf ff ff 89 bf ff  ff 89 bf ff ff 89 bf ff  |................|
00000710  ff 89 bf ff ff bf ff ff  ff ff ff ff ff ff ff ff  |................|

I'm hoping that there's a nice header at the start that says KORG or similar.  This does not have it.  What if we were not properly aligned on a byte? What if what we think is a 0, is a 1?  What if we're using the wrong bit-endianness?

To speed up the process I wrote a quick python script that tries all of the values for the issues above, and then ran the output binaries through strings.  And did it work??? YES!  We now have the firmware file!


strings 13.bin | grep KORG
KORG SYSTEM FILE
KORG

Download and run this python script in the same directory as that "bits" file and it'll output the firmware

UPDATE: there were alignment issues with that script.  nitro2k1 uploaded a new script to his blog that fixes the alignment issues

happy hacking :D

Thursday, November 24, 2011

MAME with Ubuntu 11.10 in a JAMMA Arcade Cabinet

NOTE: My blog has now moved.  Please visit my new blog where I write about audio apps, diy synthesizers, and CNCs.


NOTE: After trying to get MAME running with Ubuntu 11.10 on an arcade monitor I actually ran into a ton of trouble with some X11 crashes that would not go away.  Since then, I've found Groovy Arcade Linux which is made for linux in arcade cabinets.  I will be writing a review/tutorial for installing Groovy soon as I move to it as a possible solution!


Like this post? Consider following me on twitter!

This blog post describes the work necessary to get a PC running Ubuntu 11.10 running MAME and various other emulators inside a real JAMMA arcade cabinet with a real monitor.

For the interface between the PC and the arcade cabinet I chose a J-PAC adapter.  On the computer side it plugs accepts a VGA and PS/2 connection, and it plugs directly into the JAMMA connector inside the arcade cabinet.  I considered manually hacking the buttons of an xbox controller to the arcade buttons, but for $100 including shipping, this also includes an amplifier for the video signal which I did not want to build myself.

1. Parts needed

  • JAMMA arcade cabinet.  The monitor and arcade controls should work and be connected to the JAMMA standard connector.
  • Computer.  The faster, the better, if you want to emulate newer games.  Needs video card, sound card, some sort of network card.  I chose to install a wifi PCI adapter so that I could SSH/FTP to the computer while it's inside the arcade cabinet.
  • J-PAC, as mentioned previously
  • Another computer, networked to the MAME computer
  • MAME ROMs.  Can't help ya.
Read more »

Labels: , , , ,