Wednesday, May 26, 2010

how to build a simple audio sound recorder with clam

Once I had the opportunity to get involved with the clam project, with the help of google summer of code. Being the lazy person I am, I didn't keep up my involvement, unfortunately, since it is a great piece of code. Being the great piece of code it is, I decided to use it for a project that required me to simply record audio to files, but also have the room to grow to a bigger better application (speech recognition). Being the lazy person I am, I searched google for a tutorial about how to do this. Since I didn't find anything, I figured that I know enough about clam to write that how-to that I was looking for. Without further ado, here goes:

(please let me know if this works/doesn't work for you)

First, fire up the network editor. I like to just use the command line so I can see the diagnostics. If you're using the command line too, remember that it is capital N NetworkEditor, unless you happened to name it something else.

Next, create the network. Drag and drop an AudioSource (under the heading "Audio I/O", and a MonoAudioFileWriter (under the heading of "Audio file I/O"). Then connect them by dragging from the little blue circle (its "output port") of the audio source box ("processing"), to the little blue circle of the mono audio file writer (its "input port"). Notice that the mono audio file writer is red. This means that it needs to be configured, so right click on it and select "configure" . Then you can set the the file name and the sampling rate. Save it (network editor has an uncanny knack for crashing probably due to it's use of a mix of compiled and run time generated components). Then click run (aka "play", the blue circle with the sideways triangle) to start recording and stop to finish recording. Then check the audio file to make sure it was created, and that it has audio content. If it doesn't have content, you'll need to fiddle with you audio recording settings. You can do this several ways: you might have audio controls in the system tray/menu bar of your desktop, it might be in some control panel, or you can set it from the command line (e.g., "alsamixer").

Most likely this doesn't merit a how-to since you could probably figure that out by dropping processings on the canvas and connecting them at random. I said a simple audio recorder, but I wanted a few frills, such as a vu meter and having it be a stand-alone compiled application. Since it is so easy with clam, let's start with the vu meter (which is used to visualize the recording level. These types of meters are called vu meters because they were made popular by the Velvet Underground in the 60's and 70's -- that's not true, I only want to keep you from getting distracted by googling "vu meter"). Pull that out of the tree side menu labeled "graphical monitors". Do not be tempted to play with other graphical monitors. They are fun and they WILL distract you. Once you put it on the canvas, you can just connect it to the audio source like you did for the connecting the audio source to the mono audio file writer. Test it out by recording yourself, and don't be self conscious because everyone sounds funny when they are recorded.

Here is a screen shot of what the network should look like:


Now, to make a gui for the standalone application. Clam makes it very easy to do this but it is not as intuitive as dragging, dropping and connecting. Here's when I need to check myself how to do it ( you can see the more in depth, serious article here). First, you have to know some basics about qt designer. It is a graphical user interface (gui) design tool for the Qt framework. It is kind of like the Network Editor, except that it helps you design guis instead of audio applications. Fire it up (from the start menu or by simply typing "designer" at the command line), and select "dialog without buttons" (we are going to add our own buttons, and it is a dialog because it will be something that will be used inside a larger application as a pop up dialog... stay tuned for another tutorial about the larger application sometime later). Let's say the buttons we want are "record", "play", and "submit". Drag 3 push buttons from the side menu, arrange them how you like (you can experiment with different "layouts", which are just boxes that will sort the buttons vertically or horizontally. Change their names to read "record", "play", and "submit". For the VU meter, check to make sure that there is a submenu for the clam widgets. In my case, there wasn't, so I had to locate shared object (a "dll" in *nix parlance) that contains the clam widget plugins for qt designer and copy it to the right place. I found the plugin shared object at /usr/lib/qt4/plugins/designer/libCLAMWidgets.so and after a little poking around, I realized that it should be at /usr/lib64/qt4/plugins/designer/ so I copied it to that location and then designer found it (see "help" -> "about plugins" ). Now I can drag out a vu meter just like I did for the buttons. Now it should look like this:



Now we have the audio network and the gui, but we need a way to connect the two. To do this we need the "signals and slots editor" mode in designer. it should be in one of the myriad of menus and tabs (you can check the view menu to make sure it's being displayed). You also need to go into the "edit" menu and change to "edit signals and slots". This will allow you to select the buttons and drag their behavior to where it needs to be connected to. For the "submit" button, the behavior we be connected to a close event, so select the submit button and click+drag to the background canvas. A dialog will pop up and you should map the clicked() signal to accept(). If you hit control-r you can preview the gui to make sure that clicking the submit button closes the application. The submit button is the only button that we can connect within designer because the other buttons will be connected within clam. Change back to "edit" -> "edit widgets" and change the names of the button objects from pushButton, pushButton01, ..., to informative names like RecordButton, PlayButton, and SubmitButton. Changing the object names will make it easy to remember the names so that we can connect the object behaviors. Some of the object names might actually be bound to the behaviors by their naming conventions... we'll soon find out. If you save the designer file as the same name as the clam network, except the the extension .ui, then you can use the clam tool "Prototyper" to run the gui. Give it a try.

It turns out that there is a problem due to naming conventions. The name "PlayButton" conflicts with the "PlayButton" of the network editor. Hence, clicking the PlayButton will start recording because it will "Play" the network. So, change the record button's name to "PlayButton", and for now, the button labeled "play" will do nothing (check back later to see if I can figure it out).

For the vu meter, we need to go back to the NetworkEditor. On the output port of the AudioSource processing, right click and select "copy connection name". What you copy should be something like OutPort__AudioSource__AudioOut. Go back to qt designer and change the object name of the vu meter to whatever you copied from the network editor (remember that you can right click on the vu meter in designer to change it's object name. Try running it with prototyper. From what I can tell, it starts recording from the get-go, so that's one defect that we will have to consider. But for now, I'm satisfied with an evening's work, so I'll leave it at that for now.

No comments: