Advertisement

Creating a simple tone using DirectSound

Started by June 23, 2004 10:52 AM
3 comments, last by frostburn 20 years, 7 months ago
Hi I've just written some quick C++ code using DirectSound8 to load and play wav files. However, I was wandering if anyone knew how I could programmatically generate a pure sinusoidal tone and then write it into a DIRECTSOUNDBUFFER. Any help would be much appreciated.
I don't know too much about DIRECTSOUNDBUFFER, but assuming 16 bit signed integer (short) and 44100 Khz sample rate in mono:
1 second is 44100 shorts.

I've concentrated on the code to generate the data, not on the soundbuffer stuff since I know little about it.

pseudocode:
int bufferSize = 2*44100; // 2 secondsshort buffer[bufferSize];int fillBuffer(float frequency){  float step = PI/frequency;  for(int i = 0; i<bufferSize;i++)  {    buffer = sin(step*i);  }}

Either memcopy buffer to the directsound buffer, or rewrite this code to directyl fill the directsound buffer instead of the short array I used here.

See the article Streaming Wave Files with DirectSound for info on how to create and write to soundbuffers. EDIT: I noticed that this article is quite old and may no longer be correct..
Advertisement
Here's some (probably) working code to fill the buffer with a sine. I'll let you handle the code to create the static buffer :)

int fillSine(IDirectSoundBuffer8 *lpdsbStatic, float frequency){  LPVOID lpvWrite;  DWORD  dwLength;  double pi = 3.14159265359;  float  step = pi/frequency;  if (DS_OK == lpdsbStatic->Lock(        0,          // Offset at which to start lock.        0,          // Size of lock; ignored because of flag.        &lpvWrite,  // Gets address of first part of lock.        &dwLength,  // Gets size of first part of lock.        NULL,       // Address of wraparound not needed.         NULL,       // Size of wraparound not needed.        DSBLOCK_ENTIREBUFFER))  // Flag.  {    for(int i = 0; i> dwLength; i++)    {      *lpvWrite = sin(step*i);      lpvWrite++;    }    lpdsbStatic->Unlock(        lpvWrite,   // Address of lock start.        dwLength,   // Size of lock.        NULL,       // No wraparound portion.        0);         // No wraparound size.  }  else  (    ErrorHandler();  // Add error-handling here.  }


I'm not 100% certain it works, since I haven't touched directsound ever. I haven't tested the code either..
frostburn: two things.

1) I think you're dereferencing a void* ( *lpvWrite = sin(step*i); ), which you can't do. You'll need a cast.

2) Your buffer won't allow streaming, which I'd persoanlly want for a tone generator...
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Quote: Original post by Crispy
frostburn: two things.

1) I think you're dereferencing a void* ( *lpvWrite = sin(step*i); ), which you can't do. You'll need a cast.

2) Your buffer won't allow streaming, which I'd persoanlly want for a tone generator...


1: Quite possibly... I suck at c++, and have never actually used the function. I just pieced it together from a documentation example. There they used memcpy, and I don't know enough about pointers appearantly :)
What should I have done? "(short*)lpvWrite = (short)(sin(step*i) * 32767);" ? - I also forgot to convert the floating point -1 to 1 result of the sin to a short int value :)

2: True, but I wanted to keep it simple.

Also, a better way to do it would be to create 1 period of the sound and use several memcpy instead of calculating it over and over. At 1Khz 1 second contains 1000 identical blocks, but it would be more complicated to make and I wanted to keep it as simple as possible. :)

This topic is closed to new replies.

Advertisement