Converting a 32 bit wave form to a 16 bit wave for

2019-04-12 14:59发布

问题:

I've been capturing audio using the loopback capture mode. The captured waveform is a 32 bit waveform. I'm struggling with converting this to a 16 bit waveform so encoders like lame can deal with it (it says Unsupported data format: 0x0003).

I've tried shifting the bits (not my strong point) in the wave stream itself from 32 bit to 16 bit but the result still sounds distorted.

The Wave32To16Stream class seems to blow up on this case: if (sourceStream.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat) throw new ApplicationException("Only 32 bit Floating point supported");

Ideally I would want to just capture straight to 16 bit, is there no way to set the capture bit depth? If not, could somebody help me with converting the wavestream?

An example of a captured waveform can be found here: http://dl.dropbox.com/u/454409/test.wav (10mb)

I would also settle for some way to encode this to mp3 with lame, I've tried every parameter permutation I can think of to get it to accept the wave file. What's interesting is Audacity (which uses lame_enc to encode mp3s) was able to create an mp3 from the waveform (but maybe Audacity automatically converts it to 16bit before passing it to lame).

回答1:

Format 0x0003 is in fact ieeeFloat, you shouldn't get this exception. Better check the value it read. You cannot convert the values with bit shifting, you have to convert from float to short. A simple cast gets the job done.



回答2:

Sox can convert this for you.

http://sox.sourceforge.net/

Suitable commandlines:

http://sox.sourceforge.net/Docs/FAQ

sox any-file -b 16 outfile rate -I 22050 dither -s

N.B. Both resampling and dithering require some headroom. If SoX reports that any clipping has occurred during processing then the conversion should be redone with some attenuation, e.g.

sox any-file -b 16 outfile gain -1 rate 44100 dither -s



回答3:

If your 32-bit format is float, then most likely the sample values range from -1 to 1. To convert to 16-bit (integers) you would need to multiply by 32767 and cast to INT16.

If the 32-bit float range is larger than -1..1 then you need to find the minimum and maximum values and calculate a scale factor that gets the samples within the INT16 range.

You may need to add some dither.