Tuesday, April 29, 2008

Text to speech: making a book on tape on a mac for free

Picture 2.pngI love Bill M0HBR's regular podcast SolderSmoke, the ongoing story of a home brewing ham radio enthusiast who is currently on the air from a flat in Italy using an end fed long wire antenna.

In SolderSmoke82 Bill mentioned a book by Henry David Thoreau called Walden that is about his observations while living as simply for more than two years in a crude cabin in the woods. I wanted to read the book, which is freely available as text at Project Gutenberg here.

As I mostly listen to stuff on an iPod to ease the noisy bus and train trip I endure, I wanted to try turning it in to a book on tape. Turns out it's easy and free on a mac, and it sounds reasonably good.

Download the text file, open a terminal and do this:


$ say <walden.txt -o walden.aiff


It's pretty quick, then drag the .aiff file into iTunes and right click to choose "Convert Selection to AAC".

I don't know what those warnings it spits out, but the file seems fine.

Update: Incidentally, I found a really great use for the "Speech - Start Speaking Text" item in the Services menu. Often when making a payment I have to transcribe a long series of digits from the bill to a payment web form. After entering the digits, select the text and choose "start speaking text" to have the system read back the digits for easy checking.

Sunday, April 27, 2008

Clothesline style antenna hoist for experiments

AntennaHoist.jpgI'm experimenting with antennas again and wanted a way to string up a dipole so that I could easily pull it down and make adjustments.

My best antenna is a dipole tuned for PSK31 on 14.070Mhz that is over the roof of the house but while playing with a simple wire dipole between some trees next to the house I noticed it it appeared to pick up less electrical hash and it got me wondering if I should try suspending the dipole out beside the house where I currently have an end fed long wire (that picks up tons of noise).

This is a very simple idea, I'm positive others have used it too. I bought 30m of 3mm venetian blind cord and two little pulleys. (I already have a pulley up a tree from previous squid pole activities that was used to hold up the far end).

antenna hoist diagram.jpg
It's too early to tell if having the dipole away from the house is better than having it up higher but over the house but it's great to be able to drag it out and back in again for tuning. (I've got this dipole perfectly tuned on my second clipping).

Yes, I will need some weather proofing before leaving the balun out too long.

Friday, April 25, 2008

Chinese torch relay tactics in Canberra

chinese crowd.jpgAs a family, we decided to travel to Canberra to watch the torch relay and join the crowd in support of the Tibetan community. I headed out early for a commitment with the ABC and was surprised to see young Chinese people starting to mass along Northbourne avenue quite a long way from the city centre.

It was about 7:40am and 5 degrees C, so it was pretty chilly to be standing out there. I had a chat with the young Chinese people who seemed nice and had taken on "ozzie" nationalistic behaviours such as being wrapped in flags and with flag temporary tattoos on their cheeks. At that time all seemed pretty well, except for the stream of busses arriving with more while I watched.

Later we walked to the lawn in front of parliament house. Here we had to get past a large crowd of Chinese nationalists who were chanting "One China", so we could join the Tibet crowd. It was a nice group although some people had rather gruesome images of dead Tibetans out for display. There were speeches from Bob Brown and K.D. Lang as well as others.

BobBrown.jpgBob's a real trooper, he gave a great speech and freely mingled with the crowd. He's pictured here talking with a reporter from Deutsche Welle.

The pro-Tibetans and pro-Chinese groups stayed pretty separate until after the torch went by and we started to move over the river to try to catch up with it again.

As we walked the groups started to interact and it was not pretty. The Tibetans were basically saying that they are not anti-china, but just want basic human rights for Tibet and would like China to at least talk with the Dali Lama. The Chinese crowd were quite intimidating, both in their numbers, their organised uniformity and what they were shouting at us. There were people driving by in cars aggressively giving us "the finger" through the window, their faces hidden behind red flags.

The Chinese would shout "One China" and if someone asked about human rights, they'd shout back "you know NOTHING", which really didn't help as it wasn't clear what they know that we are yet to be informed about.

We all walked down from parliament house, past a rather ominous blood bank bus with "don't ignore the need for blood" painted on it, and over the bridge to a park on the other side. Here we were getting stuck and the intermingled crowd was getting agitated. The huge police numbers in Canberra were clearly focussed on the torch and were not much use where we were or even in directing traffic. The mood was turning and I suggested we exit. My wife felt it best to stay as her presence as a witness might prevent violence.

troops.jpg
As I left the scene the riot police turned up and ran in to settle things down.

baloon.jpgAll in all, it was a good day for democracy in Australia, as Bob Brown pointed out, if we'd done this in China we'd all have been arrested and I'd add that there would be no trace of it in the news or on the internet.

We watched the evening TV news versions and the local ABC TV had by far the most accurate version of events.

I like and respect the Chinese people but I'm puzzled about what the government is so fearful of that they must violently put down any opposition and censor the news and internet. Are they so brittle that words will harm them?

Monday, April 21, 2008

Web based software defined radio

Picture 1.pngJust stumbled upon an amazing remote controlled receiver available on the internet called WebSDR.

Unlike other radios available on the internet this one uses software to decode the spectrum coming in from the radio in such a way that multiple people can be listening to different frequencies simultaneously.

This system is hanging out the back of a PC at the Faculty for Electrical Engineering Mathematics and Computer Science at the University of Twente Enschede - The Netherlands. It looks wonderfully home brew.

Click and drag in the black area under the "waterfall" and you can tune. The great thing is that many users can be doing the same and streaming audio at the same time.

Great stuff!receiver.jpg

A Chat podcast - episode 22

Google App Engine and more.

  • Google App Engine experiences

  • YUI

  • Home brew electronics

  • Amazon Web services action

  • Amazon MP3

  • SafariAdBlock

  • Trying Twitter

  • iPhone Australia gossip

  • Open Source Corporations



Subscribe in iTunes here, or for everything else here.

Saturday, April 19, 2008

Sun buys MySQL, what does it mean when open source is bought?

logo_mysql_sun.gifMySQL has been a hugely popular database and is unambiguously the M in LAMP. (Whereas the P could be Perl, Python or PHP). That must annoy the Postgres folks.

Certainly I've had good success with MySQL over the years, for me, it just works, easy to install, easy to use and seems really fast. Sure it used to miss some of the SQL that others had but frankly I rarely ran in to anything I couldn't do or find a way to get around.

So on January 16 it was announced that Sun has purchased "the developer" of MySQL. But MySQL is open source, so anyone can get the source and work on it. What does it mean when a company buys an open source project?

There are some other examples of companies buying open source developers:


  • Apple bought CUPS printing

  • RedHat bought JBoss

  • RedHat was open source but they bought themselves I guess

  • Oracle bought Sleepycat which commercialised Berkeley DB (probably mostly legacy due to sqlite)

  • Citrix bought XenSource

  • Sun bought VitualBox



So what will it mean for MySQL? I had a look at what's happened to VirtualBox since Sun aquired Innotek and the first thing you notice is that they announced on February 12, 2008 they announced it for OpenSolaris. There are only a few posts in the forum so I guess there's not a lot of interest so far.

I'm just speculating here, but I have worked for a major web company that switched many hundreds of servers from Solaris to Linux (a stripped down RedHat distro) and reportedly was happy and saved a significant amount of money. Sun must have been devastated by the success and acceptance of Linux as a server operating system. If I want to run up a web server then Linux/Apache is the way to go today.

What could they do? RedHat split into the free Fedora and the commercially supported RedHat Enterprise with great success and I assume that Sun copied that strategy with Solaris and OpenSolaris.

Presumably the MySQL developers will be tasked with making MySQL run best on Solaris, so in a few years if you want a robust, supported MySQL database you'll choose Solaris/MySQL. That's the theory, but there's a big community of folks who like MySQL on Linux and they'll be looking closely to bring any improvements over to Linux and FreeBSD.

I'm starting to wonder if the days of the SQL databases is coming to an end. With Google's BigTable and Amazon's Simple Storage Service (S3) plus the fact that these days we always talk to the backend via some sort of Object Relational Mapper service, perhaps we won't care so much about the SQL capabilities any more.

Wednesday, April 16, 2008

I miss HyperCard


My thanks go out to Geoff Balemans for pointing me to a wonderful video by Douglas Adams, narrated by Tom Baker, called Hyperland.

This show illustrates all sorts of good stuff that was coming before the Internet was implemented as we know it today.

One of the highlights is all the technology demos done with HyperCard. I loved HyperCard as soon as I saw it. At first it was black and white, in fact 2 bit, they added colour through extensions but it just got worse. In the end, Apple dropped the project, but perhaps it was already perfect.

There are some alternatives but nothing comes close to the seamless environment created by the great Bill Atkinson.



Created in 1990, predicting life in 2005, it's well worth a look.

Sunday, April 13, 2008

Built an over-boxed QRP Power Meter

QRP Power Meter.jpgIn preparation for the next NSW Home Brew group meeting at Dural where we will be having a power meter calibrate-athon, I've built a crazy box for my simple QRP power meter. Haven't tried to calibrate it but the output of a Pixie 2 (at 200-300mW) bashes the needle full over.

The box was constructed with 12mm angle aluminium at the edges and 0.5mm aluminium plate. That aluminium plate is probably a bit too thin but it's very easy to work with using simple tin snips. I was even able to cut the round hole for the meter with the snips.

All boxed up, it feels pretty sturdy and looks rather steam-punk.

The blue is a plastic protective layer that came on the sheet metal from Bunnings, I'll peel it off when it gets a bit scruffy.

I look forward to calibrating it in a few weeks.

Saturday, April 12, 2008

Tiny morse beacon keyer in an ATTiny85

morsebeacon.jpgUsing some code based on the excellent example here I built a morse beacon keyer using an ATMega8 but it seemed like a massive waste of pins so I ordered a bunch of the 8 pin ATTiny85 chips from Digi-key. (Great service by the way)

With just 8 pins, if you use the internal oscillator, you get 6 available pins for input and output which is really quite a lot for many simple tasks like this.

In the code below, pin 5 is the keyer output, pin 6 is an inverted version and pin 7 is an audio side tone output.

My code is a simplification and an extension (to include the full alphabet and make a side tone) of the code that is "© 1997-2006 by AWC, 310 Ivy Glen, League City, TX 77573" so I hope it's ok to present it here:


/*
Morse ident, based on code from:
http://www.awce.com/cbasic.htm
*/

#include
#include
#define F_CPU 800000UL // Sets up the default speed for delay.h
#include
#include

/* dit delay for morse code */
#define DITDELAY 50 /* mS */
#define OUTPORT PORTB
#define OUTPORTDIRECTION DDRB

// the normal output bit
#define OUTBIT 0

// inverted version out bit
#define INVERTED_OUTBIT 1

// tone output bit
#define TONE_OUTBIT 2

void sendchar(int c);
void tone(int length);

int main (void)
{
// Put beacon message in program memory
PGM_P *message=PSTR("cq cq cq cq de vk2tpm ");
OUTPORTDIRECTION = _BV(OUTBIT) | _BV(INVERTED_OUTBIT) | _BV(TONE_OUTBIT);

while (1)
{
int c;
// Send each character in message
PGM_P ptr=message;
for (c=pgm_read_byte(ptr); c; c=pgm_read_byte(++ptr))
{
sendchar(c);
}
_delay_ms(30000); // wait 30 seconds
}
return 0;
}

/* Send a Morse code element (.- or space) */
void send(char c)
{
switch (c)
{
case '-':
OUTPORT = _BV(OUTBIT);
tone(3*DITDELAY);
OUTPORT = _BV(INVERTED_OUTBIT);
break;
case '.':
OUTPORT = _BV(OUTBIT);
tone(DITDELAY);
OUTPORT = _BV(INVERTED_OUTBIT);
break;
case ' ':
_delay_ms(4*DITDELAY);
break;
}
_delay_ms(DITDELAY); /* inter element space */
}

// play a tone for the given length
void tone(int length)
{
int i;
for(i = 0; i < length; i++)
{
// leave the other bits in place
OUTPORT ^= _BV(TONE_OUTBIT);
_delay_ms(2);
}
}
// Send a character (made from dots/dashes) from program memory
void sendc(PGM_P s)
{
int c;
for (c=pgm_read_byte(s);c;c=pgm_read_byte(++s))
{
send(c);
}
}
// Send an ASCII character
void sendchar(int c)
{
switch (toupper(c))
{
case ' ': sendc(PSTR(" ")); break;
case 'A': sendc(PSTR(".-")); break;
case 'B': sendc(PSTR("-...")); break;
case 'C': sendc(PSTR("-.-.")); break;
case 'D': sendc(PSTR("-..")); break;
case 'E': sendc(PSTR(".")); break;
case 'F': sendc(PSTR("..-.")); break;
case 'G': sendc(PSTR("--.")); break;
case 'H': sendc(PSTR("....")); break;
case 'I': sendc(PSTR("..")); break;
case 'J': sendc(PSTR(".---")); break;
case 'K': sendc(PSTR("-.-")); break;
case 'L': sendc(PSTR(".-..")); break;
case 'M': sendc(PSTR("--")); break;
case 'N': sendc(PSTR("-.")); break;
case 'O': sendc(PSTR("---")); break;
case 'P': sendc(PSTR(".--.")); break;
case 'Q': sendc(PSTR("--.-")); break;
case 'R': sendc(PSTR(".-.")); break;
case 'S': sendc(PSTR("...")); break;
case 'T': sendc(PSTR("-")); break;
case 'U': sendc(PSTR("..-")); break;
case 'V': sendc(PSTR("...-")); break;
case 'W': sendc(PSTR(".--")); break;
case 'X': sendc(PSTR("-..-")); break;
case 'Y': sendc(PSTR("-.--")); break;
case 'Z': sendc(PSTR("--..")); break;
case '1': sendc(PSTR(".----")); break;
case '2': sendc(PSTR("..---")); break;
case '3': sendc(PSTR("...--")); break;
case '4': sendc(PSTR("....-")); break;
case '5': sendc(PSTR(".....")); break;
case '6': sendc(PSTR("-....")); break;
case '7': sendc(PSTR("--...")); break;
case '8': sendc(PSTR("---..")); break;
case '9': sendc(PSTR("----.")); break;
case '0': sendc(PSTR("-----")); break;
}
send(' ');
}



When I burn it with the fabulous AVRDUDE I get:


Writing | ################################################## | 100% 34.10s

avrdude: 1026 bytes of flash written

avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK

avrdude done. Thank you.


So the code uses just 1026 bytes out of the available 8k which means a lot more can be done on one of these chips.

Thursday, April 10, 2008

Google's App Engine

In a brave move that I'm sure had the producer at least a little sceptical, I attempted to explain Google's new App Engine on ABC Radio National this morning. You can hear it here.

I've started playing with it and so far it's a good experience. Very happy to have python as the language they've chosen to start with, and I love the adoption of parts of django.

Monday, April 07, 2008

Sunday, April 06, 2008

Visualising WSDL with GraphViz and python

sample.jpgI'm working with SOAP and WSDL at the moment and golly that xml can be hard to read.

In the past I've used GraphViz to draw pictures of data structures, once I did an IVR call flow diagram that helped to define what the client wanted and then the source was used to write the dialplan directly.

This is only roughly working, but it's starting to be useful. The python program takes a wsdl file on the command line, and outputs a "dot" file that can be rendered with GraphViz. Note that on the Mac OmniGraffle can also render this format really nicely.

Please let me know if a better tool exists, for the Mac or Unix in general - surely it must, and any improvements would be gratefully accepted. (I am aware of XMLSpy, which looks great but there is no version for the Mac and it looks like it costs "Starting at €399" whatever that means).

#!/usr/bin/env python
"""
A little utility to visualise wsdl using Graphviz.
(http://www.graphviz.org/)
OmniGraffle does an excellent job too.
by Peter B Marks
http://marxy.org

License: You are free to use this for any purpose.

History:
6-April-2008 1 Roughly working for comment.
6-April-2008 2 Skip duplicate arcs.
6-April-2008 3 Add verbose command line switch.
6-April-2008 4 Add levels and outfile options.
"""
import sys
import string
from optparse import OptionParser
import logging
import xml.etree.ElementTree as ET

# global list of nodes we've already outout
# so we don't overwrite them
ALREADY_DONE_NODES = []
ALREADY_DONE_ARCS = []

RECURSE_LEVELS = 50
CURRENT_LEVEL = 0

def main():
global RECURSE_LEVELS
parser = OptionParser()
parser.usage = "%prog [options] infile"
parser.add_option("-v", "--verbose", dest="verbose",
action="store_true", help="print lots of info")
parser.add_option("-o", "--outfile",
dest="outfile", help="Output file to write to")
parser.add_option("-l", "--levels",
dest="levels",
help="Number of levels to recurse or %d" % RECURSE_LEVELS)
(options, args) = parser.parse_args()

if len(args) > 0:
fileName = args[0]
else:
parser.print_help()
return

if options.verbose:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.ERROR)

if options.levels:
RECURSE_LEVELS = int(options.levels)

if options.outfile:
outfile = options.outfile
else:
outfile = fileName + ".dot"

logging.debug("Reading file %s" % fileName)
infile = open(fileName, "r")
xmldata = infile.read()
infile.close()

logging.debug("Writing to file: %s" % outfile)

of = open(outfile, "w")
of.write('digraph g {graph [rankdir = "LR"];\n')
tree = ET.parse(fileName)
root = tree.getroot()

outputLevel(of, root, root.tag)

of.write('}')
of.close()
logging.debug("Done.")

def removeNamespace(fullString):
where = string.rindex(fullString, "}")
return fullString[where + 1:]

def outputLevel(of, itemList, itemListName):
"""Recursive function for outputting a level"""
global ALREADY_DONE_NODES, ALREADY_DONE_ARCS, RECURSE_LEVELS, CURRENT_LEVEL

itemListLabel = "%s" % (removeNamespace(itemList.tag))
logging.debug("Processing: %s" % itemList.tag)
itemCounter = 0
for item in itemList:
itemName = "%s-%d" % (item.tag, itemCounter)
itemCounter += 1
itemLabel = "%s" % (removeNamespace(item.tag))
for attribute in item.attrib.keys():
itemLabel += "|%s:%s" % (attribute, item.attrib[attribute])

if item.text:
itemText = item.text.strip()
if len(itemText) > 0:
itemLabel += "|%s" % item.text

if itemListName not in ALREADY_DONE_NODES:
ALREADY_DONE_NODES.append(itemListName)
of.write('"%s" [ label = "%s", shape="record" ];\n' % (itemListName, itemListLabel))
else:
logging.debug("Skipping duplicate node:%s" % itemListName)

if itemName not in ALREADY_DONE_NODES:
ALREADY_DONE_NODES.append(itemName)
of.write('"%s" [ label = "%s", shape="record" ];\n' % (itemName, itemLabel))
else:
logging.debug("Skipping duplicate node:%s" % itemName)

arc = '"%s" -> "%s";\n' % (itemListName, itemName)
if arc not in ALREADY_DONE_ARCS:
ALREADY_DONE_ARCS.append(arc)
of.write(arc) # the arc
else:
logging.debug("Skipping duplicate arc:%s" % arc)

CURRENT_LEVEL += 1
logging.debug("Recursed to level %d" % CURRENT_LEVEL)
if CURRENT_LEVEL >= RECURSE_LEVELS:
logging.debug("Hit maximum recursion level %d" % RECURSE_LEVELS)
else:
outputLevel(of, item, itemName) # recurse

if __name__ == "__main__":
main()


The diagram above is a clipping from the output generated from some annotated WSDL.

While I'm here can I mention how useful the techniques shown in this example make python for making little command line utilities. See how OptionParser makes it simple to handle short and long style command line options. Marvel at how you can use the logging module to write output if chosen by the --verbose switch.

It's sometimes a bit hard to find simple examples like this.

Friday, April 04, 2008

A visit to the Sydney Horological Centre

Horological1.jpgActing on a tip from a work colleague, I dropped in to "Smith & Smith" Pty Ltd, also known as The Sydney Horological Centre at Level 5, 193 Clarence Street, Sydney.

A rare pleasure indeed. Not since shopping at The Test Tube Factory in Ultimo have I enjoyed a shop so much.

The shop has a fantastic display of watch and clock parts, tools and servicing do-dads. They also stock an amusing array of cuckoo clocks and some impressive grandfather clocks. There are electronic movements you can put into an existing clock - you can choose between ticking and smooth too.

Horological2.jpgI came away with an "OptiVisor" head magnifier that I need for my recent forays into surface mount soldering, really I wanted the steampunk style that the guy I spoke with was wearing (left) but he told me that regrettably, they are no longer available.

If I ever need a small battery, this is certainly the place to get it - a huge range.

Wednesday, April 02, 2008

Apple's weakness is Microsoft's strength

MiniMouse.jpgMicrosoft makes really great mice. Apple just can't seem to get it right.

I've bought four "mighty" mice since the launch, assuming that the bad one I got was a one-off. They are all bad. The little ball thing that lets me scroll sideways works pretty well for about a week and then it starts to get intermittent.

All the tips about cleaning say to use a wet, lint free, cloth and hold the mouse upside down. It works a bit but doesn't fix the problem.

After much frustration I paid just AU$19 for a basic optical Microsoft "comfort 3000" mouse from Microsoft and it seems excellent. Thinking back, all the Microsoft mice have been very good.

Apple has produced some real lemons in the mouse "space": remember the puck that came with the original iMacs? The subtle second button has always annoyed me and when I see others trying to use it with less care than me they just can't get the second button to work reliably.

The mouse is so important to the use of a graphical computer, it's time to make one that really works.

I wonder if Vista will become popular due to the Microsoft mouse "halo" effect?