Creating a simple tone using DirectSound
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:
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..
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..
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 :)
I'm not 100% certain it works, since I haven't touched directsound ever. I haven't tested the code either..
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...
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
Popular Topics
Advertisement
Recommended Tutorials
Advertisement