| < August 2008 | Matthew Loar > Blog | October 2008 > |
Today I finally went down to Fry's with my sister. She had wanted to get more RAM for her desktop (Windows XP on 128 MB is the definition of pain and suffering). I had wanted to purchase a new DVD player. The one I had was this Cyberhome thing I paid $40 for about five years ago. Incredibly, it worked fine until a few months ago, when the remote stopped working and then the front panel buttons would work for about a minute after power was applied, so I had to power cycle the thing every time I wanted to use it.
Well, what I got is a DVD player. And a Bluray player. And a Dolby 5.1 surround sound system. I purchased a Panasonic SC-BT100 home theater system, fulfilling a dream I have had for quite a while. It's pretty nice. I also picked up a Spaceballs DVD to try out the surround sound.
One somewhat irritating thing, however, is that when I first powered it up, my wireless network connection dropped out. I checked the manual, and it turns out that the wireless connection for the rear speakers uses the 2.4Ghz band. Great, it's not like I already have a cordless phone competing with my Wi-Fi, not to mention all of my neighbors' wireless networks. It's too bad my laptop doesn't support 802.11a - my access point does, and I'm told that it's a much less crowded band. At any rate, I was able to get my Wi-Fi back by cranking the power setting on the access point back up to the maximum. When I first set it up my building was still pretty empty, and I was able to turn it down to the minimum and still get signal in my bedroom. Since then I had been forced to turn it back up to a medium setting.
Now I just need my couch. I ordered one from
Factory Furniture Direct, but they said it
will be a couple weeks.
I have been playing around with Flite lately, which is basically a way to take a FestVox voice built for Festival and convert it to C code which can then be compiled into one monolithic binary. Flite ships with the KAL diphone voice. However, I don't particularly care for this voice, and have been trying to convert the CMU CLB ARCTIC voice for use with flite. I followed the guide, and the automated conversion went smoothly, but at runtime I got bad synthesis and errors like this:
clunits: unit type "f" not found clunit_get_unit_index: can't find unit type f, using 0
After many hours of studying the flite code and the festival code, I finally discovered what the problem was. In festvox/cmu_us_clb_arctic_clunits.scm, there was a phone-to-clunit mapping function:
(define (cmu_us_clb_arctic::clunit_name i)
"(cmu_us_clb_arctic::clunit_name i)
Defines the unit name for unit selection for us. The can be modified
changes the basic classification of unit for the clustering. By default
this we just use the phone name, but you may want to make this, phone
plus previous phone (or something else)."
(let ((name (item.name i)))
(cond
((and (not cmu_us_clb_arctic::clunits_loaded)
(or (string-equal "h#" name)
(string-equal "1" (item.feat i "ignore"))
(and (string-equal "pau" name)
(or (string-equal "pau" (item.feat i "p.name"))
(string-equal "h#" (item.feat i "p.name")))
(string-equal "pau" (item.feat i "n.name")))))
"ignore")
((string-matches name "[aeiou].*")
(string-append
name
(item.feat i "R:SylStructure.parent.stress")))
((string-equal name "pau")
name)
(t
(string-append
name
(item.feat i "seg_onsetcoda"))))))
However, the converted C code contained just:
static char *cmu_us_clb_arctic_unit_name(cst_item *s)
{
return cst_strdup(item_name(s));
}
Not surprisingly, converting arbitrary Scheme code to C is outside the capabilities of the Flite conversion code. The code I replaced it with doesn't encompass all of the logic of the original, but appears to work fine:
static char *cmu_us_clb_arctic_unit_name(cst_item *s)
{
const char *name = item_name(s);
if (*name == 'a' || *name == 'e' || *name == 'i' || *name == 'o' || *name == 'u')
{
const char *stress = ffeature_string(s, "R:SylStructure.parent.stress");
char *namey = cst_alloc(char, strlen(name) + strlen(stress) + 1);
cst_sprintf(namey, "%s%s", name, stress);
return namey;
}
else if (strcmp(name, "pau"))
{
const char *onsetcoda = ffeature_string(s, "seg_onsetcoda");
char *namey = cst_alloc(char, strlen(name) + strlen(onsetcoda) + 1);
cst_sprintf(namey, "%s%s", name, onsetcoda);
return namey;
}
return cst_strdup(item_name(s));
}
(Before you go emailing me, cst_alloc terminates the process on allocation failure. This code uses the same patterns as elsewhere in the Flite code.)
And now I have a working Flite binary for this voice.
Work has been pretty slow lately - not too many bugs to work on. But I have been keeping busy at night trying to figure out Mono issues. I upgraded the test webserver at ACM to lenny and set up Mono FastCGI, but they still managed to get it to randomly encounter compilation errors due to missing files.
Several nights of tedious debugging later, I believe I have discovered the problem - when a new ApplicationHost is instantiated, it deletes all of the files in the DynamicBase of the AppDomain. Once I discovered this, I remembered that the Mono people do say to only run one FastCGI server at a time. However, I'm not sure I like this approach, and so I'm planning to write a wrapper script that will ensure that different servers use different directories to avoid interference.
Also, I have made some edits to my previous post on Mono FastCGI. My Deny rule was ill-conceived, and so I have changed it to simply send all ASP.NET filetypes to the FastCGI server. And while I realize that the Mono folks recommend using paths instead of extensions, as far as I can tell this is not possible using mod_fcgid and FCGIWrapper.
This brings me to another question - what is the best way to make an edit to a published post? Should I try to preserve the original content, appending edits to the end or using strikeout? Or simply replace? I'm leaning toward the latter, though I would like some kind of audit trail. Since I have this all in a Mercurial repo anyway, I'm thinking I need to get the changelog wired into my system somehow. I tried this once before, but I couldn't tease the log out of hg in a format that cl2xhtml would take.
I suppose I should end this post before I really start to ramble.
ACM has been using Apache with mod_mono for a while (my fault) and while it works relatively well, there are some issues. Namely, every once in a while the mono server will crash and requires manual restarting. So when I heard that Mono now had FastCGI support, I was intrigued, hoping that it might alleviate these problems.
I couldn't find any instructions on setting it up with Apache (using mod_fcgid), so I figured it out on my own. Here's how I configured it to run my development copy of Neztu on Debian lenny:
# apt-get install mono-fastcgi-server2 # mkdir /tmp/mono-fastcgi # chown www-data.www-data /tmp/mono-fastcgi # echo DefaultInitEnv MONO_SHARED_DIR /tmp/mono-fastcgi > /etc/apache2/conf.d/mono-fastcgi
I then put the following in my vhost configuration:
Alias /neztu/ /home/matt/devel/neztu/www/ <Directory "/home/matt/devel/neztu/www"> DirectoryIndex index.aspx Options ExecCGI FollowSymLinks AddHandler fcgid-script .asax .ashx .asmx .aspx .axd .config .cs .dll .rem .soap FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .asax FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .ashx FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .asmx FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .aspx FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .ascx FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .axd FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .config FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .cs FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .dll FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .rem FCGIWrapper "/usr/bin/fastcgi-mono-server2 /applications=/neztu:/home/matt/devel/neztu/www" .soap </Directory>
And that's all there is to it. I will have to test it further to see if it is able to recover from its hiccups with this method.
You may have noticed that I have changed my blog yet again. I had switched to NanoBlogger a while back, but I wasn't quite satisfied with it. For one, it was still separate from the rest of my site. Also, while the concept of blogging software written entirely in bash is novel, it is also quite slow. A thousand invocations of sed can't be the most efficient way to do anything.
So I set about coming up with a way to migrate my blog to use spin like the rest of my site. About this time I was also exploring new languages as part of my "maybe C++ isn't so wonderful after all" epiphany. I had dabbled with Python before and found it kind of nice, so I started working in Python.
However, I soon found something about Python that irritated me. Python has automatic memory management, but for other resources, you still have to do C-style cleanup, which is ridiculous. So it uses refcounting/garbage collection to automatically free memory. Great. I still need deterministic cleanup for file handles, database connections, etc. Not only do you have to explicitly call close() on the object when you are done with it, but you need to build for exception safety through the use of try-finally*. This makes C++ with its RAII designs actually look good.
I had been using Mono and C# for other projects. At least the .NET Framework got this right - objects owning unmanaged resources implement the IDisposable interface. C# contains a using statement which not only automatically calls Dispose on the object no matter how the block is exited, but when used correctly also scopes the variable to the block.
However, I've worked with C# before, and I wanted to try a new language. That's when I discovered Boo. It's a language inspired by Python, but built as a .NET language (IronPython reimplements the Python class libraries on top of the .NET Framework with the goal of compatibility with code written for CPython; Boo doesn't aim for Python compatibility and uses the .NET class libraries). Boo is also statically typed with type inference (and has optional duck typing).
And thus I wrote Bloog. It is designed to take a NanoBlogger database and build a thread-based blog that can be converted by spin. While I could have simply used verbatim blocks and kept the HTML as is, I didn't want to. Luckily, I found html2text, a Python thing that takes raw HTML and converts it to Markdown, which was the syntax I had been using for my most recent entries anyway. After wiring Bloog up to Markdown.NET, I discovered something disturbing. Not only is it not possible to parse the Markdown syntax in a streaming fashion (it supports grouping link URLs at the end of the content), but all the parser implementations I have seen rely on generating a bunch of MD5 sums for the purposes of escaping certain characters. Not surprisingly, the Markdown conversion was very slow. So I hacked up the Markdown converter to output thread instead, and just converted all of my old blog entries to that. On top of that, I do all the timestamp-based optimizations to only generate what I need to, and the result was a compose-preview cycle that is orders of magnitude faster than NanoBlogger. My hope that got me through this project is that this will persuade me to post more often.
I would be extremely surprised if anyone else has the need to convert a NanoBlogger blog to thread, but I've made my Mercurial repository public, just in case.
So, this is my new and hopefully more permanent blog. Please let me know if you see anything out of order.
*Apparently Python 2.5 adds the with statement which works like using, but you still have to import it from __future__.
| < August 2008 | Matthew Loar > Blog | October 2008 > |