Bug#567395: unixcw: truncated CW dah's on some audio devices
For some audio devices (soundcards) the 'cwlib' library generates truncated Morse code elements (dah's and dit's) due to audio buffer underruns.
'cwlib' works by assuming that it will be able to store at least one second of audio in the audio card fragment buffers (given the 8192 Hz DSP rate and 128 byte fragment size that it tries to set up). Audio devices which do offer enough buffers to satisfy this condition do not exhibit this bug.
But some audio devices do not offer enough buffers (at that particular rate anyway) to hold that much audio data, or even enough for a whole Morse code "dah" at the default 12 WPM Morse output speed. On such devices, all the dah's get truncated when the audio buffer underruns.
Setting the Morse WPM speed to a higher rate alleviates the problem (because the dit's and dah's are shorter so cwlib refills the audio buffers frequently enough to keep up). Likewise setting the Morse WPM speed to a lower rate exacerbates the problem.
A Morse code K should sound like "-.-" (dah-dit-dah)
echo K | cw # 12 WPM underruns: sounds like "- .-"
echo K | cw -w 20 # 20 WPM is fine: sounds "-.-"
echo K | cw -w 4 # 4 WPM underruns: sounds like ". . ."
Running with the environment variable CWLIB_DEBUG=0xFFFFFFFE makes cwlib emit interesting debug info. These two lines hint at the problem:
cwlib tries to set the fragment size to 2^7 == 128, but on one soundcard with the problem, I get:
> cw: dsp fragment size not set, 131
Then when cwlib tries to write "about 1 second of audio", it only manages to write 2096 bytes (~ 1/4 second) before the audio fragment buffers are full:
> cw: dsp data buffered, 800 Hz, 2096
By fiddling with the DSP rate setting code and/or the fragment size setting code, I am able to resolve the "fragment size not set" issue, but even with valid fragment sizes I still can only get about 1/4 second of audio into the buffer.
Note: On soundcards which don't show this cwlib problem, the fragment size does get set to 128, and the data buffered in the first write is 8192 bytes (one second of audio).