1

I am working on an electronics project and I need to store speech data in an extrememly limited memory. Since the microcontroler is not equipped to dynamically decompress audio data I am stuck with having to use uncompressed audio.

After some experimentation I figured out that 4 bit audio sampled at 4000Hz is enough to convey spech without being annoying. It takes 2000 bytes to store a second of audio, which is manageable if not perfect.

The problem here is that no audio editor I know of can output any lower than 8 bit audio at 8000 Hz.

I have tried using Nyquist prompt to quantize sound data to 4 bits and downsampling audio to 4000 Hz in Audacity. It sort of works, but I can still only export to 8 bit 8000 hz PCM RAW. And even then, I found that the RAW binary still has full 8 bit data. There are hex values like 0x86, 0x7f all over the place where I would have expected all samples to have 0 in their lower 4 bits. Further, the Nyquist prompt output is full of high frequency noise. Filtering this noise with an equalization filter does filter the noise but it also "de-quantizes" the audio. This is only logical, I guess, because the track is in 8 bit PCM and there is no way to tell audacity not to mess with the quantizaition.

So, I am essentially looking for an audio editor that can work with 4 bits. It need not be as fully featured as the more famous ones, but as long as it can import 8 bit data and output 4 bit data after equalization, it will work. Also, it can be a command line tool, some abandoned open source project or anything as long as it does my job.

I don't have a digital audio background, so I might not have asked this question properly or followed proper terminology, and I apologise for that.

Any general advice pertaining to this question/alternate methods/pointers in the right direction are welcome.

  • Hello. Notice that if your 8 to 4 bits conversion is successful, 1 byte of output will actually represent 2 samples, it is therefore not surprising that the lower 4 bits are not always equal to 0 (unless one sample out of two in your input data is equal to zero). How do you plan to implement digital to analog conversion of these audio data ? – audionuma May 19 '18 at 15:25
  • @audionuma Even though the conversion done in software, it is still internally stored as 8 bit samples in audacity. And there is no option to export to 4 bit RAW PCM. The exported RAW should have 8 bit samples with zero for the lower 4 bits but it isn't working that way. Thats why I am looking for a audio editor where sound is internally handled as 4 bit. – Nirav May 19 '18 at 16:08
  • @audionuma I intend to create a very minimal R-2R DAC to play the samples. – Nirav May 19 '18 at 16:13
1

There doesn't seem to be an already existing tool for your purpose. (At least, I couldn't find one). You might have to build your own tool in your language of choice.

Some basic building blocks could be :

Export your audio as unsigned 8 bits 8 kHz raw. Before exporting, apply a low-pass filter with a cut-off frequency below 2 kHz with a steep attenuation. That is to prevent aliasing when down-sampling to 4 kHz sampling rate.

Read data from the input file four bytes at a time. You get four bytes that represent four samples of the input audio signal b0, b1, b2, b3.

One way to down-sample is by decimation. So you will only keep b0and b2.

The brutal way to reduce quantization (from 8 bits to 4 bits) is to use the right bit shifting operator (>>). This is not ideal, might cause some rounding errors, but that is worth trying. Another option would be to use dithering but that will not be covered here.

qb0 = b0 >> 4 qb2 = b2 >> 4

Now, you need to output these two quantized samples and save them in a file. It would be nice (as you are looking to save space) to code these two 4 bits samples into one byte. For this, you can use binary operators AND (&) and OR (|).

out = (qb0 << 4) | qb2

The four leftmost bits of out are one sample coded as unsigned four bits, the four rightmost bits of outare the next sample.

Both bits manipulation steps can be done as :

out = (b0 & 0xF0) | (b2 >> 4)

Corner case : depending on the input file size, your last read might only return 1, 2 or 3 valid bytes. If it's 3, just use the same process on b0and b2. Else, you must stuff the last output byte with zero :

out = b0 & 0xF0

Example

input file : 7F A2 C1 D8 E4. That's 5 samples coded as unsigned int. (Spaces added for readability, they are not part of the input file).

Get 4 bytes 7F, A2, C1, D8.

7F & F0 -> 70

C1 >> 4 -> 0C

70 | 0C-> 7C that will be the first byte of the output file.

Get 4 bytes. Actually, there's only one left D8.

D8 & F0-> D0 that will be the second byte of the output file.

The output file ends up like this : 7C D0.

  • I did something like this too. I converted the raw into a comma separated list of hex data and wrote a simple c++ code to ignore every other sample and then mix the remaining ones. Since I had to embed the binary into a c code file, this approach was more preferable to what you suggested. It sort of works, but it results in an extremely noisy sound (even for 4 bit audio). That is what prompted me to search for a 4 bit audio editor. – Nirav May 21 '18 at 13:18
  • If only there were some way to filter out the high frequencies from the final output file in this method you suggest, I would not need a dedicated 4 bit audio editor. If you know a way to do that (I suspect it has got something to do with fourier analysis for discrete samples) it would be awesome. I am, however, very close to giving up and going with this noise-prone method. If no better answers come by in a few days, I will select this as the accepted answer because it (sort of) answers my question. – Nirav May 21 '18 at 13:24
  • I do not clearly understand your workflow. If you insert the 8 bit / 8 kHz data as a C array in a header, you're not saving any space ? You mean that you then process this data at compile time so that only the quantized/down-sampled data is stored in the binary ? In any case, you have to low-pass the input data before down-sampling. This can be done in audacity before exporting the raw 8 bits / 8 kHz data. – audionuma May 21 '18 at 13:34
  • No, the program that does the downsampling and bitcrushing outputs an array of bytes which I then copy into the main program (come on, I'm not that stupid). Sorry for being confusing. Low pass before downsampling. Okay I will try that next (I was under the impression that decreasing the bit depth results in high frequency noise regardless of the original audio's max frequency.) – Nirav May 22 '18 at 3:50
  • @KittyHawk I'm sorry if I gave the impression that I consider you are stupid. About the lowpass before downsampling, see en.wikipedia.org/wiki/Aliasing – audionuma May 22 '18 at 4:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.