Pergunta

I have a problem with the waveOut interface. I want to write a simple class structure where i have a class AudioStream that makes it very simple to have audio output. I have a constructor that takes the following arguments: AudioStream32(int sampleRate, int sampleSize, bool stereo, int bufferSize) (sampleSize is the size of the samples in bytes, the rest is hopefully self-explanatory)

The idea is that I initialize the AudioStream once and then call setSample(float sample) to set the audio stream. The class is in a beginning phase, so only double buffering and mono sound is currently implemented.

In the setSample method, I convert the float sample to an unsigned int in the range 0 to 2^(8*sampleSize), and then convert that unsigned int to unsigned char's. I could as well use the unsigned int directly, but that way I could not reuse the code I use for other sampleSizes. Code:

void AudioStream32::setSample(float sample)
{
unsigned int discreteSample = 1 + mid + ((float)mid * sample);

for (unsigned int i = 0; i < sampleSize; i++)
{
    data[pointr++] = (char)(discreteSample & 255);
    discreteSample = discreteSample >> 8;
    // (same as dividing by 256)
}

//... Non-relevant code that makes sure the buffer is sent to the audio device

mid is an unsigned int that has been assigned the value (1 << (sampleSize * 8 - 1)) - 1 (which is just a faster way of doing 2^(sampleSize * 8 - 1)) So when sampleSize is 1, this will evaluate to 127 and when sampleSize is 2, to 32767 (or, in general, about half of the maximum value).

This works fine when I use 1 as sampleSize (so, when I use a single character as sample). However, when I use 2 as sampleSize (or 2 bytes or a short int as the size of a sample), I get really weird results.

I try to stream a simple sinewave. When I use 1 as sampleSize I indeed get a sine wave as waveform. However, when I use 2 as sampleSize, I get the following weird waveform:

My weird waveform

I recorded the waveform in Audacity via a minijack cable connecting audio out and mic in, and it's recorded as a 32 bit float stream. The output is in fact a 16 bit int stream.

This seems to indicate an overflow problem, or a problem with converting between unsigned and signed ints or chars. More weird behavior occurs: scaling (or changing the volume, whatever you call it) the sample I send to the setSample method doesn't seem to matter, except when I set it to 0 or very close to zero (0.0001 still yields the same waveform, 0.00001 yields silence).

A very weird thing is, that when I try to divide by 512 instead of 256 (that is, changing ">> 8" to ">> 9" in the setSample method), it all seems to work (including changing the sound). The sound is weaker than when I use 1 as sampleSize though, so it still seems that this is not the right way to do it.

It's a shame that I can't compare the samples I write to the sound device to the output of the sound device in a simple way. That way, I could at least figure out if the problem is in the byte formatting or in the conversions I do.

Does anyone have any idea what is going on?

Foi útil?

Solução

This looks like a sine wave with it's values inverted. In other words if you adjusted the positives values from 1 to .5 to 0 to -.5, and negatives fom -1 to -.5 to 0 to .5 you'd have a sine wave.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top