The ALSA tool
arecord provides a very easy way to record audio. You can run it in the terminal to start recording audio, which is progressively written to a WAV file. You then press Ctrl+C to stop recording. The resulting WAV file can then be played back or edited in a variety of programs.
For my purposes, I run it in the background, then send a
SIGTERM signal to stop the recording, which is a valid way to stop according to the man page. However, I found that certain programs gave some variation of “memory allocation error” when attempting to open a WAV file that had been generated using this
SIGTERM method of stopping the recording.
As a workaround, opening the WAV file in Audacity and saving it again proved to “fix” the WAV file, and allowed all programs to open it successfully. Taking a diff between the two WAV files in a hex viewer showed a lot of bytes being changed, so didn’t help narrow down what exactly was causing the issue, but did lead to hypothesizing that something in the WAV header was perhaps responsible.
This turned out to be true. Specifically, the culprit was the part of the WAV header that indicates the size of the audio content. It was indicating a size of ~2GB, which is far bigger than correct! The actual size of the audio content was in the order of dozens of kilobytes. This would explain the various “memory allocation error” messages; the programs which trust the WAV header attempt to allocate 2GB of memory just for a 12kb WAV. Presumably Audacity has some special handling for this case.
At a guess, the root cause of this issue is that when
arecord first creates the WAV file it does not know the size of the audio content, so puts 2GB as a placeholder. Presumably when the
SIGTERM is received,
arecord stops writing the WAV file but does not update the total size in the header to reflect how much was actually written. Note that I have not confirmed this guess.
Ultimately, the fix was to use this very helpful Python script, which reads the WAV file to determine the size of the audio content, then makes minimal changes in-place to update the header. Thank you kcarnold for sharing your script!