简体   繁体   中英

How to convert 8bit sound to 16bit

I'm using DynamicSoundEffectInstance to stream in raw PCM data. This data is 16bit and signed. My code works fine, not a single problem. The issue is compressing this raw PCM yields poor results: 13.9mb down to 13.7mb.

If I encode the PCM data as 8bit signed values, and then compress it, the result is a small 5.24mb file - this is approx. 1mb smaller than an Ogg file.

Why not just use Ogg? Too much hassle. I don't want any dependencies and need cross-platform support and raw PCM does that just fine with DynamicSoundEffectInstance.

I've figured out that I've got to somehow get the 8bit data back to 16bit so XNA can play it as it. This is where I'm lost. I've spent countless hours looking at how to do this but haven't gotten anywhere. Nowhere at all.

How would I convert an 8bit byte to a 16bit integer? Convert.ToInt16 is of no help and the sound is still garbled nonsense.

Does anyone know a simple way to do this or am I looking at this all wrong? Can you not convert 8bit to 16bit like this regarding audio?

EDIT: Here is some VERY shocking VB code using Convert.ToInt16. The data array holds 44,100 bytes of the audio.

Dim buffer((44100 * 2) - 1) As Byte ' place to dump 8-16bit data
For i As Integer = 0 To data.Count - 1 ' data holds 8bit data

    Dim aaa = Convert.ToInt16(data(i))
    Dim bb() As Byte = BitConverter.GetBytes(aaa)

    buffer(i * 2) = bb(0)
    buffer(i * 2 + 1) = bb(1)
Next

This does work, albeit, Windows needs to the system volume on 100 to even hear it, it is still barely audible and full of static.

Based on your code example, it appears that the only thing you have left remaining to do is to shift the 8-bit samples left 8 bits, so that the data occupies the most-significant-bits of the 16-bit sample.

Ie:

Dim buffer((44100 * 2) - 1) As Byte ' place to dump 8-16bit data

For i As Integer = 0 To data.Count - 1 ' data holds 8bit data

    Dim aaa = Convert.ToInt16(data(i)) << 8 ' shift to most-significant-bits
    Dim bb() As Byte = BitConverter.GetBytes(aaa)

    buffer(i * 2) = bb(0)
    buffer(i * 2 + 1) = bb(1)
Next

You may still experience noise issues, as halving the sample size also halves the signal-to-noise ratio.

I just ran into a similar issue while trying to build an audio player from scratch. To my surprise, I found out that 8 bit audio is typically unsigned while 16 bit audio is usually signed. See this answer from another SO user:

https://stackoverflow.com/a/43939741/7732473

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM