Saturday, July 24, 2010

iPhone/Qt: UDP Voice using AudioQueue/QAudioOutput

Qt 4.6 Introduces QtMultimedia with support for raw audio input/output, while Mac OS X and iPhone OS has well known CoreAudio/AudioQueue from a long time.

This example show how to implement a really rudimentary VOIP between an iOS (iPhone/iPod Touch/iPad) and a Desktop (using Qt). To simplify the example is just unidirectional iOS to Qt, because doing Qt to iOS part is just the specular code.

The idea is very simple, Fetch the sample data from the microphone, and send over UDP. No compression no packet number just send raw data in simple way as possible.

On iOS we've AudioQueueNewInput() that creates a new recording audio queue object, and AudioQueueNewOutput() that creates a new playback audio queue object.

The specular Qt 4.6+ classes are QAudioInput class that provides an interface for receiving audio data from an audio input device, and QAudioOutput class that provides an interface for sending audio data to an audio output device. To handle audio samples we can easily wrap QIODevice read() and write() calls.

The source code is really easy. iOS code contains AudioRecorder.h/AudioRecorder.m that is a C code that wrap AudioQueue Input to record a stream, with a callback handler to intercept packet data. The Qt4 Source code contains just  a QIODevice Wrapper that read from UDP and prepare for QAudioOutputStream. It's really really simple, but gives you an idea.

The Source code is available here, and contains both Qt 4.6+ and iOS sources: iPhone/Qt UDP Voice Source Code.

Note: Due to a QTBUG-8878 we cannot use 8, 16, 24 KHz Frequency. Will be fixed in Qt 4.6.4.

Saturday, July 10, 2010

RaleighFS is moving to Flash Disks

No, this is not going to happen for a couple of years, I love spinning disk, because file-system can really do the difference in term of performance.

But… This week I've talked a bit with my colleague batt, that is working on some new features of his BattFS available on BeRTOS. And I've discovered that flash disk are challenging too, especially on embedded devices where you cannot use large cache due to ram limitation.

What changes, on flash, from a traditional File-System? First of all due to limited rewrite cycle of a block, you cannot modify a block in place (Append-Only Data Structure needed). Append-Only Index is not a problem, but Traditional file-system heavily rely on a fixed location super-block that contains the root pointer, and append-only tree root changes every time, so super-block need to be re-writed.

The first solution that RaleighFS can quickly implement is to write a new super-block each flush. In this way each flush (or transaction) can be easily identified. But how can I reach the last super-block and what is the last super-block?

The Worst case is to scan the whole disk to find the super-block "magic" number in block header.

But what we can do is to add some information to the super-block
  • Super-Block Id
  • Next Super-Block Id
  • Next Super-Block Location

In this way on each flush we "predict" what is the location of the next super-block, and we give it an unique id just to be sure to identify the next one. In this way we can avoid to scan the whole disk but just a few Mb (flush size) and then we can easily jump to the next super-block until the super-block next location isn't valid.

Block allocation is just a "round-robin" allocation in this way we're able to keep aligned "every" block erase cycle, and this solve the super-block location problem.

What about the tree? Tree is the common B*Tree of RaleighFS with a few changes:
  • Modified leaf node is allocated/writed in a new place
  • Root and Twigs Nodes are rewritten only if keys changes.

Wait wait, how we can reach the new leaf node? To avoid large Twigs rewrite we keep a small BTree (high fanout) that maps old leafs block numbers with the new ones. Free blocks can be stored on disk or better due to 0-seek time we can just check all the tree pointers to see what's allocated.

I'm not really convinced about the map BTree, but seems to solve the "large update" of value modification in key/value storage case… This is just a fast "port" of current RaleighFS to SSD but maybe something really different can be used...

Thursday, July 8, 2010

PyQt4: Electronic Oscillator

An electronic oscillator is an electronic circuit that produces a repetitive electronic signal: sine wave, square wave and any other repetitive mathematical function.

So, why an Oscillator? Because, I'm currently looking at Audio, and Audio Effects (Distortion, Chorus, Delay, Flange, Reverb, ...) and the sound is basically a wave with a certain frequency.

How can you visualize your effect function? I've created this one above using Python and PyQt4. Less than 200 lines of code. Including the Oscillator class with 5 types of wave (ok, not so difficult).

You can find the source code here: PyQt4 Electronic Oscillator Source Code.