ASCIIMath creating images

Wednesday, August 22, 2012

Real life interference again, of the best kind

A short time ago, life has become quite overwhelming, but in a good way.   To announce the reason, I sent a little bit of creative writing to my friends; I'll post it here with the personally identifying information masked out.


CHILD PROCESS (1)        THIEMANN FAMILY INFORMATION        CHILD PROCESS (1)

SUMMARY
     A child process with PID "------ ------ Thiemann" has been successfully
     spawned.  While the process is not yet ready for completely standalone 
     deployment, it operates within all expected parameters.
     
DESCRIPTION
     On --- -- Aug 2012 --:-- CEST, a child process was successfully spawned
     from two parent processes.  The new process was given a PID of "------
     ------ Thiemann".  All parameters are within design specifications, as
     are the parameters of the parent processes.  Note that the new process
     is not functioning as a completely independent unit yet, but relies on
     I/O processing by the parent processes; in particular, the flushed 
     output functionality is not yet present, and instead uses buffered
     output where the buffers are emptied by the parent processes.  Input
     is taken exclusively from one of the parent processes.  Furthermore,
     the self-diagnosis functionality is currently limited to a one-bit sonic
     indicator; if this indicator is activated, it is left to the parent 
     processes to determine if I/O needs to be serviced or if the current
     operating environment is incompatible.
     
     When not performing I/O, the new process spends a considerable amount 
     of time in the sleep state.  A visualization of the process is appended
     to the report, showing the interaction of the new process with its
     parent processes.
     
BUGS
     As of yet, no bugs have been found in the system that merit intervention
     by either the parent processes or the operating system.  However, it is
     expected as the process interacts with the greater system environment,
     some abnormal processing states may occur, but it is expected that the
     self-repair functions will be fully functional by that time.
     

I know the "thing to do" these days is to have a facebook page, twitter account, email address, etc. for a new kid set up.  Well, this kid's information will be off the net for as long as possible, until he is capable of understanding and deciding for himself.  But watch out world once he gets his hands on a soldering iron and/or a compiler!

Tuesday, July 24, 2012

Simple multithreading using clone()

For a bit of hacking I want to do, I need to implement concurrency between two processes sharing the same memory.  So I looked into how to do it (this is all under Linux). My first stab was to look at the old SYSV shared memory interface - but that was kind of ugly, then I looked at pthreads and thought the same. Isn't there a simple way to do fork() without splitting the memory?

Turns out, Linux does have such a mechanism, in the clone() function call. However, there are some pitfalls that one needs to be aware of. Let's see the code first, though.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/sched.h>

Pretty standard stuff, but note the last one: it's important to pick that rather than <sched.h> (as the man page claims), since otherwise you don't have the necessary constants defined!
Next, we need some memory in global space:
#define STACKSIZE 256
int globalint;
char stack[STACKSIZE];
The lone int is the only memory that I'm using to communicate between the threads for now. The stack however, is only used by the child thread/process. It is visible to the parent, but it's not easy (or reliable) to use it to communicate with the child. Now let's define the code for the child process.
int secondp()
{
  int i;

  for (i=0; i<1000; i++) {
    globalint = i;
    usleep(60000);
  }
  return 0;
}
Simple enough: every 60 ms, set the global variable to the value of of the local one being incremented. Note I am NOT "incrementing" the global, since that would be a read-write operation, which gets computer science people all excited in multiprogramming situations! (Or it did, 70 or so years ago.)
Now let's have the main program.
int main()
{
  int i, j, sppid;

  for (i=0; i<STACKSIZE; i++) stack[i] = 0x55;
I initialize the stack so I can observe what happened to it during execution, filling it with a simple 010101... pattern. Next, the interesting bit.
  sppid = clone( secondp, &stack[STACKSIZE], CLONE_VM, NULL );
  if (sppid==-1) {
    printf("clone error.\n");
    exit(1);
  }
  printf("clone pid 0x%08x\n", sppid );
The first line creates the child process, given the pointer to the function as the first argument. The second argument is what that process gets as a stack - but note that the pointer points to the TOP of the stack! This is x86 specific and MAY (or may not) be different on other architectures (ARM? amd64?).
The third argument, the options, is what creates the magic to make this shared memory scheme work. Without it, clone() behaves more like fork(), giving the child a copy (-on-write) of the parent memory space, which is exactly what I don't want. Other options allow you to copy or share specific elements, like the file I/O table etc. Read the documentation. Lastly, the following arguments are passed to the child function - useful in many instances, but not used here.
I finish up the program with code that actually demonstrates that things are happening as expected:
  for (i=0; i<10; i++) {
    printf("%d\n", globalint);
    fflush(NULL);
    usleep(1000000);
  }

  for (i=0; i<16; i++) {
    printf( "%04x :", i<<4 );
    for (j=0; j<16; j++) {
      printf( " %02x", stack[j+(i<<4)]&(0xff) );
    }
    printf( "\n" );
  }

  return 0;
}
So, for 10 seconds, the value of the global integer is printed; after that, I dump the stack in a hexdump fashion. This is what I get on my Ubuntu Netbook:
clone pid 0x000005e3
0
16
33
49
66
83
99
116
132
149
0000 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0010 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0020 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0030 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0040 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0050 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0060 : 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0070 : 55 55 55 55 55 55 55 55 55 55 55 55 48 f2 0e 08
0080 : e0 8e 04 08 00 00 00 00 6f 58 08 08 cd 84 05 08
0090 : 08 f2 0e 08 00 00 00 00 55 55 55 55 55 55 55 55
00a0 : 55 55 55 55 55 55 55 55 00 00 00 00 00 87 93 03
00b0 : 55 55 55 55 55 55 55 55 55 55 55 55 03 8f 04 08
00c0 : 60 ea 00 00 55 55 55 55 55 55 55 55 55 55 55 55
00d0 : 55 55 55 55 55 55 55 55 55 55 55 55 a6 00 00 00
00e0 : 55 55 55 55 00 01 00 00 00 00 00 00 2e 96 05 08
00f0 : 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55
Clearly, the global int is modified by the child process while being read by the parent. The stack display is interesting, showing clearly how it's being filled towards lower memory. A x86 expert could probably explain clearly what is there and why the stack is not written to contiguously (presumably, some of it is allocated byt never written to).
Thus, the three main things to keep in mind when using clone() are:

  • Make sure you use the right sched.h file.  (You'll notice this at compile time)
  • Choose the proper options to clone()
  • Make sure you know which way the stack grows, and how big it'll get!  If you get this wrong, it'll clobber the parent variables - if you use malloc() instead, you'll get a memory fault (which is preferrable since it's slightly easier to diagnose).
Enjoy!

Thursday, July 12, 2012

Journée Science et Musique 2012



A few months ago, I got roped into helping to get the "Journée Science et Musique 2012" event off the ground.  Mostly, my contribution to date has been to be a part of the team wrangling an ugly mess of HTML, PHP, and CSS into shape.  Well, as of yesterday that abomination is live and open to the public.  As we get closer to the date, I'll probably get involved into other parts of the event as well - in fact I have two demos that I'm working on that we might show off at the event.

I'm looking forward to it, it should be a lot of fun.

Saturday, June 16, 2012

Classic Computing Redux

When I accepted my current Postdoc position, knowing it would mean a move from Canada to France, I decided to all but completely dissolve my classic computer collection.  I just kept my Commodore 8-bitters, that are now in boxes at a friend's place in Pointe-Claire, QC.

However, here in Rennes (and probably everywhere else in France) there are a lot of "braderies", basically organized neighborhood garage sales; we have found these to be a great source of things we need.

And sometimes, one sees something that can't just be left.  Like this Commodore 4-op calculator (Model 776M).  For €1.  No, I won't hack it, it's just too damn cute.

Tuesday, May 22, 2012

Some new toys to play with

I have just finished up some work for a major deliverable at work; so I predict I have a little more time to work on more fun things.  In the last few weeks, I had some mail-order toys come in - this weekend I finally had some time to at least test them!

The first item is an Arduino Uno, to replace the Diecimila that got left in Montreal with the Laser projects. It's an Arduino - it works like Arduinos do.

The other thing I got though was a JY-MCU Bluetooth serial adapter, which promises to be a lot of fun to mess with.  First though, I wanted to make sure it works, so I need a simple USB TTL serial interface.  This is where the Arduino comes in handy, although in a slightly unorthodox fashion.

Arduino Uno without the chip but as a USB serial
adapter - however, in this picture I had Rx and Tx swapped
Rather than loading up a sketch that provides another serial port on other pins of the ATmega chip, I simply removed the chip and hooked the Bluetooth adapter up to pins 0 and 1.  So, I used the Arduino Uno board as just the plain USB serial adapter with TTL levels that I need.

With this setup I successfully managed to send data (using my Mac) from BT to USB and back; using screen as a terminal emulator.

I am looking forward to messing with all this again.

View of the labels for the BT adapter.

Other Projects

This being said, other projects are getting back on track, too. The (actually work-related) microphone array will get some well-deserved attention again.  And finally, I have been roped into helping out with the next edition of the Journée « Science & Musique » that is being organized here at IRISA/INRIA Rennes.  For now I am just helping out a little with the website (the old one can be seen here) but probably I'll get more involved with some of the exhibits as well. My atrocious french is a problem, but we'll see what happens.

Sunday, March 11, 2012

Building a Microphone Array

With all the holes drilled, the
microphone support rails are
being assembled here for the
first time.
METISS, the group I'm doing my postdoc with, does a considerable amount of research on signal separation and localization.  Given that I have some experience with hardware, I am now helping soon-to-be-ex Ph.D. student Nobutaka Ito (he should be defending soon!) with some work on a microphone array.  Once everything is finished and tested, we will be going out and doing some recordings as raw data to throw at algorithms.

Post-assembly checking for alignment,
and filing off of sharp corners. 
The support structure
Originally, we planned to to the construction rather ad-hoc with hand tools - but then I discovered that INSA/INRIA has a "Atelier Mechanique" that I can use - a nicely equipped workshop!  (There are a few tools that I'd like to use they don't have, but nothing critical.)
The array configuration is four offset linear strips of microphones, with 5 cm distance between microphones along each strip.  The distance between strips is such that 3 microphones (2 on one strip and one on the adjacent strip) form an equilateral triangle, that is each microphone is 5 cm to all of its immediate neighbors.

The array all wired up to the A/D converter and hooked
up to a laptop.  We are forced to use an older laptop
since the drivers don't work on a modern OS,
and the IT department doesn't install XP on new ones.
Fixing the microphones
One of Emmanuel's parameters for us building the array was that we couldn't affix the microphones (Sony ECM-C10) in a permanent fashion.  As a result, we are using sticky tack (the kind used to put posters on the wall).  This is less than ideal - it appears to hold reasonably well, but is not totally solid.

The A/D converter
The A/D converter we are using is a Inrevium (Tokyo Electron Device?) TD-BD-16ADUSB, in what looks very much like a homebrew enclosure (this may have been built in-house at IRISA before I got here).  We have encountered two problems with the setup: the first is the age of the drivers.  The CD provides drivers for Windows and Linux; however, the Windows drivers only work on XP, and the Linux drivers won't compile for a 3.x kernel.  I have attempted to fix the Linux drivers without success so far; the problem is that the driver uses old-style mutex locking, and I don't know enough about the "modern" locking mechanisms in the Linux kernel to replace those in the driver, nor do I have the time to dig deeply into kernel driver writing to do it properly.  If anyone is interested, there is some info on a different website.
Close-up of the microphone array. Note that the
microphones can be a bit hard to distinguish from
the bolts holing the support together.

For now, we are just using an old Dell laptop provided by the IT department that runs XP.  It works reasonably well, but initial tests show that the occasional packet gets lost (the converter pushes 4 ms of audio over USB per packet), rate of packet loss dependent on sampling rate.  We don't know (yet) if this is due to the speed of the laptop or simply a limitation of the USB bus.

Preliminary Evaluation
Given the construction and method to affix the microphones, the tolerances of the microphone placement is about 2 mm.  We are planning to use the array primarily for (wideband) speech processing, so with a sampling rate of 16 kHz.  With a max frequency of about 7 kHz (I should double check the antialiasing filter characteristics of the A/D converter), those errors should be tolerable.  At 16 kHz sampling rate, we also stop dropping packets from the converter.  However, before we go out and make actual field recordings, everything will be double- and triple-checked.

Update: See this post for the recordings we made with the array.

Sunday, February 5, 2012

Postdoc in Rennes

The INRIA building on the campus of Université de Rennes 1
As of mid-January I am a Postdoctoral Fellow with the METISS group at IRISA (Institut de recherche en informatique et systèmes aléatoires) one of the research institutes of INRIA (Institut national de recherche en informatique et en automatique).  Within the group, I will be working on multi-channel source separation - at the moment I'm working on some enhancements to the FASST package, in part to familiarize myself with the code.

En France
Adjusting to living in France has been taking a significant chunk of my time.  This was to be expected - moving to a different country is never a simple endeavor.  While my nationality makes it easy for me to live in France, relocating family is a bit more difficult.  The paperwork is mostly done now, so soon I should have some time again to spend on things like... Arduinos! FPGAs! MIDI!

For that to happen of course I need my equipment and parts.  That should, along with the rest of our furniture, arrive this week - as I'm writing this, our apartment has just one piece of furniture...