Updates and fixes in 2001/coupard
Format fix README.md. Update .gitignore with file referenced by the author.
This commit is contained in:
1 parent
6f86a4053f
commit
323f089a81
2 files changed
+47
-40
No files matched your search
@@ -1 +1,2 @@
|
|||||||
coupard
|
coupard
|
||||||
|
test.wav
|
||||||
+46
-40
@@ -1,11 +1,11 @@
|
|||||||
# Most obfuscated sound
|
# Most obfuscated sound
|
||||||
|
|
||||||
Pierre-Philippe Coupard
|
Pierre-Philippe Coupard
|
||||||
Lineo, Inc.
|
Lineo, Inc.
|
||||||
ATTN : Pierre-Philippe Coupard
|
ATTN : Pierre-Philippe Coupard
|
||||||
390 South 400 West
|
390 South 400 West
|
||||||
Lindon, UT 84042
|
Lindon, UT 84042
|
||||||
USA
|
USA
|
||||||
|
|
||||||
## To build:
|
## To build:
|
||||||
|
|
||||||
@@ -27,9 +27,13 @@ make
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you're using macOS then you won't have these devices. If however you install
|
If you're using macOS then you won't have these devices. If however you install
|
||||||
sox from MacPorts or Homebrew you can do something like:
|
[sox](https://en.wikipedia.org/wiki/SoX) from
|
||||||
|
[MacPorts](https://www.macports.org) or [Homebrew](https://brew.sh) you can do
|
||||||
|
something like:
|
||||||
|
|
||||||
./coupard | sox -q -traw -r8000 -b8 -e unsigned-integer - -tcoreaudio
|
```sh
|
||||||
|
./coupard | sox -q -traw -r8000 -b8 -e unsigned-integer - -tcoreaudio
|
||||||
|
```
|
||||||
|
|
||||||
Thanks go to [Yusuke Endoh](/winners.html#Yusuke_Endoh) for providing a proper
|
Thanks go to [Yusuke Endoh](/winners.html#Yusuke_Endoh) for providing a proper
|
||||||
command line (see [/2013/endoh3/README.md](2013/endoh3/README.md).
|
command line (see [/2013/endoh3/README.md](2013/endoh3/README.md).
|
||||||
@@ -45,41 +49,42 @@ your arm or the wall for confirmation.
|
|||||||
Past years' IOCCC entries do many marvellous things in small packages,
|
Past years' IOCCC entries do many marvellous things in small packages,
|
||||||
such as console utilities, games, math, languages or even X
|
such as console utilities, games, math, languages or even X
|
||||||
applications. But they all have one thing in common (despite being hard
|
applications. But they all have one thing in common (despite being hard
|
||||||
to read obviously) : when they interact with the user, they only
|
to read obviously): when they interact with the user, they only
|
||||||
*display* things, i.e. they display either text or drawings.
|
*display* things, i.e. they display either text or drawings.
|
||||||
|
|
||||||
So, for a change, this program titillates the sense of hearing instead
|
So, for a change, this program titillates the sense of hearing instead
|
||||||
of sight : this program is a self-contained speech synthesizer that
|
of sight: this program is a self-contained speech synthesizer that
|
||||||
tells the current time through the computer's sound card - in just under
|
tells the current time through the computer's sound card - in just under
|
||||||
2 Kb of source code !
|
2 Kb of source code !
|
||||||
|
|
||||||
In the 2001 IOCCC rules and guidelines documents, there is no mention of
|
In the 2001 IOCCC [rules](/2001/rules.txt) and
|
||||||
what is or isn't acceptable regarding audio I/Os, but it is mentioned
|
[guidelines](/2001/guidelines.txt) documents, there is no mention of
|
||||||
|
what is or isn't acceptable regarding audio I/O, but it is mentioned
|
||||||
that hardware-specific and/or non-portable programs are not welcome. So,
|
that hardware-specific and/or non-portable programs are not welcome. So,
|
||||||
in order to do audio and satisfy those requirements, the format required
|
in order to do audio and satisfy those requirements, the format required
|
||||||
by /dev/audio has been chosen : /dev/audio is a rather ancient
|
by `/dev/audio` has been chosen: `/dev/audio` is a rather ancient
|
||||||
fixed-format audio interface that is supported by the majority of Unices
|
fixed-format audio interface that is supported by the majority of Unices
|
||||||
that can do sound, as a lowest-denominator sound I/Os interface.
|
that can do sound, as a lowest-denominator sound I/O interface.
|
||||||
|
|
||||||
### Program usage:
|
### Program usage
|
||||||
|
|
||||||
* To listen to what the program says directly, invoke
|
To listen to what the program says directly, invoke
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./coupard > /dev/audio
|
./coupard > /dev/audio
|
||||||
```
|
```
|
||||||
|
|
||||||
the program then speaks out something like
|
The program then speaks out something like
|
||||||
|
|
||||||
"The time is HH hours MM minutes SS seconds"
|
"The time is HH hours MM minutes SS seconds"
|
||||||
|
|
||||||
in military time (24 hours). Of course, you need to have permissions
|
in military time (24 hours). Of course, you need to have permissions
|
||||||
to write to /dev/audio, have your sound card enabled, the volume up,
|
to write to `/dev/audio`, have your sound card enabled, the volume up,
|
||||||
the speakers connected ... :-)
|
the speakers connected ... :-)
|
||||||
|
|
||||||
* If you want to convert the audio output of the program into another
|
If you want to convert the audio output of the program into another audio
|
||||||
audio format, you can pipe it to sox for example (sox is the
|
format, you can pipe it to [sox](https://en.wikipedia.org/wiki/SoX) for example
|
||||||
Swiss army knife of Unix audio tools) : the command
|
(`sox` is the Swiss army knife of Unix audio tools): the command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./coupard | sox -c1 -r8000 -tub - -c2 -r44100 -twav test.wav
|
./coupard | sox -c1 -r8000 -tub - -c2 -r44100 -twav test.wav
|
||||||
@@ -90,28 +95,30 @@ file and saves it into "test.wav".
|
|||||||
|
|
||||||
The output format of the program is 8KHz, unsigned 8-bit samples.
|
The output format of the program is 8KHz, unsigned 8-bit samples.
|
||||||
|
|
||||||
NOTE : the program's return code is meaningless
|
NOTE: the program's return code is meaningless.
|
||||||
|
|
||||||
### Audio quality:
|
### Audio quality
|
||||||
|
|
||||||
The quality of the sound produced by the program is cross between a
|
The quality of the sound produced by the program is cross between a
|
||||||
yogurt-pot-and-string telephone and a bad gramophone, i.e. the S/N
|
yogurt-pot-and-string telephone and a bad gramophone, i.e. the S/N ratio is very
|
||||||
ratio is very low and the signal's top frequency is very low as well.
|
low and the signal's top frequency is very low as well. This is because the
|
||||||
This is because the audio is stored internally at a sampling rate of
|
audio is stored internally at a sampling rate of 4KHz (the [Nyquist
|
||||||
4KHz (the Nyquist frequency is only 2KHz) with only 4-bit samples
|
frequency](https://en.wikipedia.org/wiki/Nyquist_frequency) is only 2KHz) with
|
||||||
(adding 24db of quantization noise to an already poor signal).
|
only 4-bit samples (adding 24db of quantization noise to an already poor
|
||||||
|
signal).
|
||||||
|
|
||||||
In short, you might have to listen twice to understand what the
|
In short, you might have to listen twice to understand what the
|
||||||
program is saying. 2048 bytes including the sound generation program
|
program is saying. 2048 bytes including the sound generation program
|
||||||
doesn't leave much room for audio quality ;-)
|
doesn't leave much room for audio quality ;-)
|
||||||
|
|
||||||
### Speech generation:
|
### Speech generation
|
||||||
|
|
||||||
Only 9 phonemes are used to generate the speech. Beside the limited
|
Only 9 phonemes are used to generate the speech. Beside the limited
|
||||||
number of words the program has to generate (66 words), the low sound
|
number of words the program has to generate (66 words), the low sound
|
||||||
quality is actually exploited to take liberties with certain
|
quality is actually exploited to take liberties with certain
|
||||||
consonants (for example, "s" and "f" sound very much the same at 4KHz,
|
consonants (for example, "s" and "f" sound very much the same at 4KHz,
|
||||||
so they can be merged into one phoneme). Because the psychoacoustic
|
so they can be merged into one phoneme). Because the
|
||||||
|
[psychoacoustic](https://en.wikipedia.org/wiki/Psychoacoustics)
|
||||||
context around those phonemes is just sufficient, the words can be
|
context around those phonemes is just sufficient, the words can be
|
||||||
interpreted correctly most of the time despite the fact that they are
|
interpreted correctly most of the time despite the fact that they are
|
||||||
pronounced quite wrongly.
|
pronounced quite wrongly.
|
||||||
@@ -120,7 +127,7 @@ Internally, a table is used to generate most of the words, and
|
|||||||
composite words such as "thirty-five" are made up by the C code
|
composite words such as "thirty-five" are made up by the C code
|
||||||
externally.
|
externally.
|
||||||
|
|
||||||
### Data compression:
|
### Data compression
|
||||||
|
|
||||||
Even at 4KHz / 4 bits, the weight of all the phoneme samples and the
|
Even at 4KHz / 4 bits, the weight of all the phoneme samples and the
|
||||||
word-to-phonemes table put together is over 1600 bytes, which is well
|
word-to-phonemes table put together is over 1600 bytes, which is well
|
||||||
@@ -134,22 +141,21 @@ decompression code can't be made small enough.
|
|||||||
|
|
||||||
The best compression compromise was found using a simple Huffman
|
The best compression compromise was found using a simple Huffman
|
||||||
compressor, and encoding the compressed data by blocks of 13 bits in
|
compressor, and encoding the compressed data by blocks of 13 bits in
|
||||||
pairs of printable ASCII characters : the raw data is compressed to
|
pairs of printable ASCII characters: the raw data is compressed to
|
||||||
8465 bits, and the resulting C string is therefore about 1300
|
8465 bits, and the resulting C string is therefore about 1300
|
||||||
characters, which leaves just enough room for the decompressor with a
|
characters, which leaves just enough room for the decompressor with a
|
||||||
hard-coded Huffman tree, and the code that plays the phonemes in the
|
hard-coded Huffman tree, and the code that plays the phonemes in the
|
||||||
right order.
|
right order.
|
||||||
|
|
||||||
### Note on compiler warnings and lint:
|
### Note on compiler warnings and lint
|
||||||
|
|
||||||
The program should build with gcc's -Wall -Werror and -ansi flags. If
|
The program should build with `gcc -Wall -Werror -ansi`. If the `-pedantic`
|
||||||
the -pedantic flag is used, gcc will complain about the length of the
|
flag is used, gcc will complain about the length of the data string and the sign
|
||||||
data string and the sign of its type, and also the fact that main()
|
of its type, and also the fact that `main()` returns with no value. The
|
||||||
returns with no value. The confusion with the sign of the char type
|
confusion with the sign of the char type doesn't matter with the data string
|
||||||
doesn't matter with the data string because it's composed only of
|
because it's composed only of printable characters under 127.
|
||||||
printable characters under 127.
|
|
||||||
|
|
||||||
When linting the program with lclint, it complains about a huge list
|
When linting the program with `lclint`, it complains about a huge list
|
||||||
of things that, if corrected to make lint happy, would probably double
|
of things that, if corrected to make lint happy, would probably double
|
||||||
the size of the source code.
|
the size of the source code.
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user