Using launchd, you could save a property list like this as `~/Library/LaunchAgents/com.stackexchange.apple.40705.plist`.

	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
	http://www.apple.com/DTDs/PropertyList-1.0.dtd>
	<plist version="1.0">
	<dict>
		<key>Label</key>
		<string>com.stackexchange.apple.40705</string>
		<key>ProgramArguments</key>
		<array>
			<string>say</string>
			<string>yy</string>
		</array>
		<key>WatchPaths</key>
		<array>
			<string>/Users/username/Desktop/</string> <!-- cannot use ~/ -->
		</array>
		<key>ThrotteInterval</key>
		<integer>10</integer> <!-- run at most every 10 seconds (default) -->
	</dict>
	</plist>

It can be loaded by logging out and back in or with `launchctl load ~/Library/LaunchAgents/com.stackexchange.apple.40705.plist`.

WatchPaths only registers modifications to files if they are saved atomically. (Or deleted and recreated every time they are saved, which is what most OS X apps do.) But for example TextMate and vim don't perform atomic saves by default.