Friday, May 25, 2012

Compiler Construction and JavaCC

Scanning and Parsing are two important phases of compilation process.While it is possible to code a scanner and a parser all by hand, it becomes tedios, specially when the grammar of the language gets more complex. There are Lexer and Parser generators so that we can generate them from a specified grammer.

JavaCC is one such compiler generator. Here are key points about JavaCC.
  • It can generate both scanner and parser.
  • TopDown parsing: generate the parse tree in a top-down manner.
  • It generates Recursive Descent parsers. The parser will execute a set of recursive methods to process the input (not based on parse tables)
  • Predictive (non-backtracking). It looks ahead a number of symbols to decide which grammar rule to use.
  • Supports LL(K) grammars. That means there must not be left recursion, and the grammar should be left refactored.
  • Detects left-recursion, possible ambiguities and warns during compiler generation.
  • Can use different look-ahead values in different local sections
  • Can use syntactic look-ahead. Hence can be considered as a LL(*) parser generator.
  • Gammar can be provided in EBNF notation. Removing left recursion is easy and the grammar is more readable.
  • Provides debugging support: tokenizing / parsing / looking ahead.
  • Supports panic-mode error recovery.
  • Supports Unicode.
  • Lots of good documentation / resources to follow.
  • Good tooling support, including an Eclipse plugin, IntelliJ IDEA plugin and a Maven plugin.
Having unicode support means you can build your compiler using any (natural) language you prefer! You'll only have to change the (programming) language keywords for the new (natural) language. You can also change the (context-free) grammar a bit if you want to make your (programming) language closer to the new (natural) language.

Here is my attempt to create a compiler in my own language, සිංහල (Sinhala). This uses a simplified version of c grammer.
https://github.com/amilamanoj/CMinus/



Recording Music from a Musical Instrument

You can record high quality audio by direct cable connection between your computer and musical instrument (such as musical keyboard, electric guitar).

You need a two way audio cable. (with 3.5mm TRS connectors). Just connect it to audio out of the instrument and line-in/mic of the computer.
Most of the instruments have a 6.35mm socket for audio output. In that case you also need a 6.35mm male to 3.5mm female jack stereo audio adapter. You can get these from a local electronics store or a site like amazon, ebay.

Moving on to software, you don't need expensive professional sound editing software. Audacity is a free and open source cross-platform audio recorder/editor and perfectly fits our purpose.
 
Next comes the tricky part. During recording, you hear what you play through the computer. If there's a delay between what you play and what you hear, it's very difficult to play. Let's look at solutions for this.

Windows

When it comes to Windows, drivers pass sound through the system kernel, resulting considerable amount of latency.
This won't be a big issue on sound cards that support ASIO. ASIO is a sound card driver  protocol that minimizes the latency by bypassing operating system layers and connecting directly to the soundcard. However, not many soundcards support ASIO (specially integrated audio chipsets).

ASIO4ALL may help you in this case. It is an independent universal emulated ASIO driver and brings ASIO support to virtually all consumer-grade soundcards and integrated audio chipsets.
The problem here is that, you need a recording program that supports ASIO. Though Audacity can support ASIO, they don't distribute it with ASIO support since it's proprietary and has an incompatible license. You maybe able to find an unofficial version with ASIO support to download, or if you are a software geek, you can compile Audacity yourself with ASIO support.

Linux

Most modern distributions (Ubuntu, Fedora, Mint, OpenSUSE)  use PluseAudio with ALSA. Usually it results in lower latencies. If you are lucky, you may be able to record without any tweaking.
Within audacity, just goto Edit -> Preferences -> Recording and select Software Playthorugh.

If you experience some delay, you can route the input at PulseAudio level by engaging loopback module. Goto terminal and execute:
pactl unload-module module-loopback
In my experience, this can also have some latency, and if your computer (laptop) has a built in microphone, you might get a loud noise.

What worked best for me is using the pacat command. What we do here is capturing the raw audio steam from the specific device we want and playing it back from the output device on the fly, specifying minimum latency. You can quickly get this working by following these instructions. Make sure you have selected "pulse" as both playback and recording device in Audacity Preferences -> Devices, otherwise you won't be able to record while pacat is active.

After you have recorded, you can easily get the mp3 by using Audacity's Export command.

Here is a recording I made. This is a part of the song "Never Forget" in Halo3. Played with Yamaha PSR-E323. Recorded with Audacity in Linux with the last technique above.
Never Forget (cover) by Amila Manoj