Archived

This topic is now archived and is closed to further replies.

Crispy

Hmm - precision issues or some memory tweak?

Recommended Posts

Ok - I'm not really sure where to post this, so I picked the most mathematical forum. I've been messing for two hours or even more now trying to figure out why the following (read as pseudocode):
AClass::Update(float * data, int datasize)
{
 static float p = 0;

 DXBuffer->Lock();

 for(int x = 0; x < datasize; x++)
  {
  DSoundBuffer[x] = (short)(sin(p) * scale); //<-

  //ofstr << data[x] << endl;


  p += 0.04;
  }

 DXBuffer->Unlock();
}

BClass::Mix()
{
 static BufferToSend[65000];

 static float p = 0;

 for(int x = 0; x < datasize; x++)
  {
  BufferToSend[x] = (short)(sin(p) * scale); //<-

  //ofstr << BufferToSend[x] << endl;

 
  p += 0.04;
  }

 AClass->Update(BufferToSend, datasize);
}
works just fine, whereas the following:
AClass::Update(float * data, int datasize)
{
 DXBuffer->Lock();

 for(int x = 0; x < datasize; x++)
  {
  DSoundBuffer[x] = (short)(data[x]); //<-

  //ofstr << data[x] << endl;

  }

 DXBuffer->Unlock();
}

BClass::Mix()
{
 static BufferToSend[65000];

 static float p = 0;

 for(int x = 0; x < datasize; x++)
  {
  BufferToSend[x] = (short)(sin(p) * scale); //<-

  //ofstr << BufferToSend[x] << endl;


  p += 0.04;
  }

 AClass->Update(BufferToSend, datasize);
}
produces a crackly sound on top of the sine wave. In the above samples, disregard everything that isn't given - the only truly important lines are the ones that are highlighted. When ouputting BufferToSend[] in BClass::Mix(), the output is a perfect sine with a very beautiful frequency response and absolutely no noise. However, when I output data[] from AClass:: Play in code sample B, there is a discernible noise which can easily be see in the frequency spectrum and is very irritating on the ear when played back. Nothing too heavy - just some (rather) small cracks ~6-8 times a seconds. But it's still very irritating. Code sample A produces perfect sound and equally perfect is the frequency response. As can be seen, the output of BClass::Mix() is ignore entirely. The problem here is that after data[] is filled in in BClass::Mix(), nothing is done to affect it in any way. Since no truncation of values seems to take place in the bounds of the same function, my question is: where the heck does the interference come from?! I distictly ouput the same array - see the commented lines with ofstr. I haven't tried double precision yet, but quite frankly I don't see a reason to (even if sin() produces a double precision value) since the float array still seems to be able to hold the precision required...

"Finishing in second place, simply means you are the first loser." - PouyaCat
  
[edited by - crispy on March 20, 2004 2:54:56 PM] [edited by - crispy on March 20, 2004 2:55:57 PM]

Share this post


Link to post
Share on other sites
One problem is that BufferToSend is an array of ints and AClass::Update is expecting an array of floats (though I don''t see how the compiler would let you do that).

If that is just a typo in the post and BufferToSend is actually an array of floats, then perhaps the conversion from float to short to float to short is adding some noise. If so, then getting rid of the cast-to-short in BClass::Mix would solve that.

Share this post


Link to post
Share on other sites
Yeah - that's a typo - I downsized the code quite a bit to create this example. Anyway - after two more days of messing around I found the only feasible solution to be to actually ask AClass for the approprate pointer in DSoundBuffer between calls to DXBuffer->Lock() and DXBuffer->Unlock(). This way there is no interference and evidently it's looking to be a better solution altogether as this eliminates one temporary array and allows more flexibility as to what kind of data and how is written to the buffer.

The downside is that now the application (as opposed to AClass) is responsible for making sure there is no buffer overflow (even if AClass tells the application how many bytes can be written, it still is more prone to error).

Nevertheless - I never really understood why something like that happened... Weird - that's all I can say.

edit: you can't get rid of the cast - that's the whole problem (although casting isn't the source of this interferences - this is way more severe) because, for a 16 bit audio buffer, the only acceptable data type is a 16-bit signed short. I'm keeping all data in floating point format internally for calculations and higher precision (which could be required for something like 24-bit or 32-bit wav rendering) and casting it to meet DirectX's buffer format is pretty much the only way.




"Finishing in second place, simply means you are the first loser." - PouyaCat



[edited by - crispy on March 21, 2004 4:07:37 PM]

Share this post


Link to post
Share on other sites